diff options
Diffstat (limited to 'thirdparty')
159 files changed, 26760 insertions, 9962 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md index 6f1014cf9b..2584694aaf 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -388,7 +388,7 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 8.5.0 (30485ee8c3d43c553afb9d78b9924cb71c8d2f19, 2024) +- Version: 10.0.1 (a1d9bfe62818ef0fa9cf63b6e6d51436b1c93cbc, 2024) - License: MIT Files extracted from upstream source: @@ -614,7 +614,7 @@ to solve some MSVC warnings. See the patches in the `patches` directory. ## miniupnpc - Upstream: https://github.com/miniupnp/miniupnp -- Version: 2.2.7 (d4d5ec7d48c093b37b2ea5d7171ede21ce9d7ff2, 2024) +- Version: 2.2.8 (b55145ec095652289a59c33603f3abafee898273, 2024) - License: BSD-3-Clause Files extracted from upstream source: @@ -650,6 +650,10 @@ comments and a patch is provided in the `patches` folder. Collection of single-file libraries used in Godot components. +- `bcdec.h` + * Upstream: https://github.com/iOrange/bcdec + * Version: git (3b29f8f44466c7d59852670f82f53905cf627d48, 2024) + * License: MIT - `clipper.{cpp,hpp}` * Upstream: https://sourceforge.net/projects/polyclipping * Version: 6.4.2 (2017) + Godot changes (added optional exceptions handling) @@ -757,7 +761,7 @@ with the provided patch. ## openxr - Upstream: https://github.com/KhronosGroup/OpenXR-SDK -- Version: 1.1.38 (f90488c4fb1537f4256d09d4a4d3ad5543ebaf24, 2024) +- Version: 1.1.41 (7d1c0961351bac61fd7bb72d402649d5ac3f2935, 2024) - License: Apache 2.0 Files extracted from upstream source: @@ -873,23 +877,6 @@ They can be reapplied using the patches included in the `patches` folder, in order. -## squish - -- Upstream: https://sourceforge.net/projects/libsquish -- Version: 1.15 (r104, 2017) -- License: MIT - -Files extracted from upstream source: - -- `LICENSE.txt` -- All `.cpp`, `.h` and `.inl` files - -Some downstream changes have been made and are identified by -`// -- GODOT begin --` and `// -- GODOT end --` comments. -They can be reapplied using the patches included in the `patches` -folder. - - ## tinyexr - Upstream: https://github.com/syoyo/tinyexr diff --git a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh index 835d87f8c6..6b5b104f3d 100644 --- a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh +++ b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh @@ -72,7 +72,7 @@ public: hb_map_t current_glyphs; hb_map_t current_layers; int depth_left = HB_MAX_NESTING_LEVEL; - int edge_count = HB_COLRV1_MAX_EDGE_COUNT; + int edge_count = HB_MAX_GRAPH_EDGE_COUNT; hb_paint_context_t (const void *base_, hb_paint_funcs_t *funcs_, @@ -2339,7 +2339,11 @@ struct COLR c->plan->colrv1_varstore_inner_maps.as_array ())) return_trace (false); - if (!out->varStore.serialize_serialize (c->serializer, + /* do not serialize varStore if there's no variation data after + * instancing: region_list or var_data is empty */ + if (item_vars.get_region_list () && + item_vars.get_vardata_encodings () && + !out->varStore.serialize_serialize (c->serializer, item_vars.has_long_word (), c->plan->axis_tags, item_vars.get_region_list (), @@ -2347,7 +2351,9 @@ struct COLR return_trace (false); /* if varstore is optimized, update colrv1_new_deltaset_idx_varidx_map in - * subset plan */ + * subset plan. + * If varstore is empty after instancing, varidx_map would be empty and + * all var_idxes will be updated to VarIdx::NO_VARIATION */ if (optimize) { const hb_map_t &varidx_map = item_vars.get_varidx_map (); @@ -2579,10 +2585,6 @@ struct COLR { // COLRv1 glyph - ItemVarStoreInstancer instancer (&(this+varStore), - &(this+varIdxMap), - hb_array (font->coords, font->num_coords)); - bool is_bounded = true; if (clip) { diff --git a/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh b/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh index 45baeb4ec5..16b232a2ae 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh @@ -633,8 +633,8 @@ struct GDEFVersion1_2 ligCaretList.sanitize (c, this) && markAttachClassDef.sanitize (c, this) && hb_barrier () && - (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && - (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); + ((version.to_int () < 0x00010002u && hb_barrier ()) || markGlyphSetsDef.sanitize (c, this)) && + ((version.to_int () < 0x00010003u && hb_barrier ()) || varStore.sanitize (c, this))); } static void remap_varidx_after_instantiation (const hb_map_t& varidx_map, @@ -668,13 +668,13 @@ struct GDEFVersion1_2 // the end of the GDEF table. // See: https://github.com/harfbuzz/harfbuzz/issues/4636 auto snapshot_version0 = c->serializer->snapshot (); - if (unlikely (version.to_int () >= 0x00010002u && !c->serializer->embed (markGlyphSetsDef))) + if (unlikely (version.to_int () >= 0x00010002u && hb_barrier () && !c->serializer->embed (markGlyphSetsDef))) return_trace (false); bool subset_varstore = false; unsigned varstore_index = (unsigned) -1; auto snapshot_version2 = c->serializer->snapshot (); - if (version.to_int () >= 0x00010003u) + if (version.to_int () >= 0x00010003u && hb_barrier ()) { if (unlikely (!c->serializer->embed (varStore))) return_trace (false); if (c->plan->all_axes_pinned) @@ -712,7 +712,7 @@ struct GDEFVersion1_2 } bool subset_markglyphsetsdef = false; - if (version.to_int () >= 0x00010002u) + if (version.to_int () >= 0x00010002u && hb_barrier ()) { subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); } @@ -875,7 +875,7 @@ struct GDEF bool has_mark_glyph_sets () const { switch (u.version.major) { - case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0; + case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () && u.version1.markGlyphSetsDef != 0; #ifndef HB_NO_BEYOND_64K case 2: return u.version2.markGlyphSetsDef != 0; #endif @@ -885,7 +885,7 @@ struct GDEF const MarkGlyphSets &get_mark_glyph_sets () const { switch (u.version.major) { - case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets); + case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets); #ifndef HB_NO_BEYOND_64K case 2: return this+u.version2.markGlyphSetsDef; #endif @@ -895,7 +895,7 @@ struct GDEF bool has_var_store () const { switch (u.version.major) { - case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0; + case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () && u.version1.varStore != 0; #ifndef HB_NO_BEYOND_64K case 2: return u.version2.varStore != 0; #endif @@ -905,7 +905,7 @@ struct GDEF const ItemVariationStore &get_var_store () const { switch (u.version.major) { - case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(ItemVariationStore); + case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () ? this+u.version1.varStore : Null(ItemVariationStore); #ifndef HB_NO_BEYOND_64K case 2: return this+u.version2.varStore; #endif diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh index 9c805b39a1..5ffeb5d0c1 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -139,14 +139,8 @@ struct PairPosFormat2_4 : ValueBase return_trace (false); } - unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); - if (!klass2) - { - buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); - return_trace (false); - } - unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); + unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) { buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); diff --git a/thirdparty/harfbuzz/src/OT/Var/VARC/VARC.cc b/thirdparty/harfbuzz/src/OT/Var/VARC/VARC.cc new file mode 100644 index 0000000000..1afb571113 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Var/VARC/VARC.cc @@ -0,0 +1,346 @@ +#include "VARC.hh" + +#ifndef HB_NO_VAR_COMPOSITES + +#include "../../../hb-draw.hh" +#include "../../../hb-geometry.hh" +#include "../../../hb-ot-layout-common.hh" +#include "../../../hb-ot-layout-gdef-table.hh" + +namespace OT { + +//namespace Var { + + +struct hb_transforming_pen_context_t +{ + hb_transform_t transform; + hb_draw_funcs_t *dfuncs; + void *data; + hb_draw_state_t *st; +}; + +static void +hb_transforming_pen_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data; + + c->transform.transform_point (to_x, to_y); + + c->dfuncs->move_to (c->data, *c->st, to_x, to_y); +} + +static void +hb_transforming_pen_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data; + + c->transform.transform_point (to_x, to_y); + + c->dfuncs->line_to (c->data, *c->st, to_x, to_y); +} + +static void +hb_transforming_pen_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data; + + c->transform.transform_point (control_x, control_y); + c->transform.transform_point (to_x, to_y); + + c->dfuncs->quadratic_to (c->data, *c->st, control_x, control_y, to_x, to_y); +} + +static void +hb_transforming_pen_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data; + + c->transform.transform_point (control1_x, control1_y); + c->transform.transform_point (control2_x, control2_y); + c->transform.transform_point (to_x, to_y); + + c->dfuncs->cubic_to (c->data, *c->st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); +} + +static void +hb_transforming_pen_close_path (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + void *user_data HB_UNUSED) +{ + hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data; + + c->dfuncs->close_path (c->data, *c->st); +} + +static inline void free_static_transforming_pen_funcs (); + +static struct hb_transforming_pen_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_transforming_pen_funcs_lazy_loader_t> +{ + static hb_draw_funcs_t *create () + { + hb_draw_funcs_t *funcs = hb_draw_funcs_create (); + + hb_draw_funcs_set_move_to_func (funcs, hb_transforming_pen_move_to, nullptr, nullptr); + hb_draw_funcs_set_line_to_func (funcs, hb_transforming_pen_line_to, nullptr, nullptr); + hb_draw_funcs_set_quadratic_to_func (funcs, hb_transforming_pen_quadratic_to, nullptr, nullptr); + hb_draw_funcs_set_cubic_to_func (funcs, hb_transforming_pen_cubic_to, nullptr, nullptr); + hb_draw_funcs_set_close_path_func (funcs, hb_transforming_pen_close_path, nullptr, nullptr); + + hb_draw_funcs_make_immutable (funcs); + + hb_atexit (free_static_transforming_pen_funcs); + + return funcs; + } +} static_transforming_pen_funcs; + +static inline +void free_static_transforming_pen_funcs () +{ + static_transforming_pen_funcs.free_instance (); +} + +static hb_draw_funcs_t * +hb_transforming_pen_get_funcs () +{ + return static_transforming_pen_funcs.get_unconst (); +} + + +hb_ubytes_t +VarComponent::get_path_at (hb_font_t *font, + hb_codepoint_t parent_gid, + hb_draw_session_t &draw_session, + hb_array_t<const int> coords, + hb_ubytes_t total_record, + hb_set_t *visited, + signed *edges_left, + signed depth_left, + VarRegionList::cache_t *cache) const +{ + const unsigned char *end = total_record.arrayZ + total_record.length; + const unsigned char *record = total_record.arrayZ; + + auto &VARC = *font->face->table.VARC; + auto &varStore = &VARC+VARC.varStore; + auto instancer = MultiItemVarStoreInstancer(&varStore, nullptr, coords, cache); + +#define READ_UINT32VAR(name) \ + HB_STMT_START { \ + if (unlikely (unsigned (end - record) < HBUINT32VAR::min_size)) return hb_ubytes_t (); \ + hb_barrier (); \ + auto &varint = * (const HBUINT32VAR *) record; \ + unsigned size = varint.get_size (); \ + if (unlikely (unsigned (end - record) < size)) return hb_ubytes_t (); \ + name = (uint32_t) varint; \ + record += size; \ + } HB_STMT_END + + uint32_t flags; + READ_UINT32VAR (flags); + + // gid + + hb_codepoint_t gid = 0; + if (flags & (unsigned) flags_t::GID_IS_24BIT) + { + if (unlikely (unsigned (end - record) < HBGlyphID24::static_size)) + return hb_ubytes_t (); + hb_barrier (); + gid = * (const HBGlyphID24 *) record; + record += HBGlyphID24::static_size; + } + else + { + if (unlikely (unsigned (end - record) < HBGlyphID16::static_size)) + return hb_ubytes_t (); + hb_barrier (); + gid = * (const HBGlyphID16 *) record; + record += HBGlyphID16::static_size; + } + + // Condition + bool show = true; + if (flags & (unsigned) flags_t::HAVE_CONDITION) + { + unsigned conditionIndex; + READ_UINT32VAR (conditionIndex); + const auto &condition = (&VARC+VARC.conditionList)[conditionIndex]; + show = condition.evaluate (coords.arrayZ, coords.length, &instancer); + } + + // Axis values + + hb_vector_t<unsigned> axisIndices; + hb_vector_t<float> axisValues; + if (flags & (unsigned) flags_t::HAVE_AXES) + { + unsigned axisIndicesIndex; + READ_UINT32VAR (axisIndicesIndex); + axisIndices = (&VARC+VARC.axisIndicesList)[axisIndicesIndex]; + axisValues.resize (axisIndices.length); + const HBUINT8 *p = (const HBUINT8 *) record; + TupleValues::decompile (p, axisValues, (const HBUINT8 *) end); + record += (const unsigned char *) p - record; + } + + // Apply variations if any + if (flags & (unsigned) flags_t::AXIS_VALUES_HAVE_VARIATION) + { + uint32_t axisValuesVarIdx; + READ_UINT32VAR (axisValuesVarIdx); + if (show && coords && !axisValues.in_error ()) + varStore.get_delta (axisValuesVarIdx, coords, axisValues.as_array (), cache); + } + + auto component_coords = coords; + /* Copying coords is expensive; so we have put an arbitrary + * limit on the max number of coords for now. */ + if ((flags & (unsigned) flags_t::RESET_UNSPECIFIED_AXES) || + coords.length > HB_VAR_COMPOSITE_MAX_AXES) + component_coords = hb_array<int> (font->coords, font->num_coords); + + // Transform + + uint32_t transformVarIdx = VarIdx::NO_VARIATION; + if (flags & (unsigned) flags_t::TRANSFORM_HAS_VARIATION) + READ_UINT32VAR (transformVarIdx); + +#define PROCESS_TRANSFORM_COMPONENTS \ + HB_STMT_START { \ + PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TRANSLATE_X, translateX); \ + PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TRANSLATE_Y, translateY); \ + PROCESS_TRANSFORM_COMPONENT (F4DOT12, HAVE_ROTATION, rotation); \ + PROCESS_TRANSFORM_COMPONENT (F6DOT10, HAVE_SCALE_X, scaleX); \ + PROCESS_TRANSFORM_COMPONENT (F6DOT10, HAVE_SCALE_Y, scaleY); \ + PROCESS_TRANSFORM_COMPONENT (F4DOT12, HAVE_SKEW_X, skewX); \ + PROCESS_TRANSFORM_COMPONENT (F4DOT12, HAVE_SKEW_Y, skewY); \ + PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TCENTER_X, tCenterX); \ + PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TCENTER_Y, tCenterY); \ + } HB_STMT_END + + hb_transform_decomposed_t transform; + + // Read transform components +#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \ + if (flags & (unsigned) flags_t::flag) \ + { \ + static_assert (type::static_size == HBINT16::static_size, ""); \ + if (unlikely (unsigned (end - record) < HBINT16::static_size)) \ + return hb_ubytes_t (); \ + hb_barrier (); \ + transform.name = * (const HBINT16 *) record; \ + record += HBINT16::static_size; \ + } + PROCESS_TRANSFORM_COMPONENTS; +#undef PROCESS_TRANSFORM_COMPONENT + + // Read reserved records + unsigned i = flags & (unsigned) flags_t::RESERVED_MASK; + while (i) + { + HB_UNUSED uint32_t discard; + READ_UINT32VAR (discard); + i &= i - 1; + } + + /* Parsing is over now. */ + + if (show) + { + // Only use coord_setter if there's actually any axis overrides. + coord_setter_t coord_setter (axisIndices ? component_coords : hb_array<int> ()); + // Go backwards, to reduce coord_setter vector reallocations. + for (unsigned i = axisIndices.length; i; i--) + coord_setter[axisIndices[i - 1]] = axisValues[i - 1]; + if (axisIndices) + component_coords = coord_setter.get_coords (); + + // Apply transform variations if any + if (transformVarIdx != VarIdx::NO_VARIATION && coords) + { + float transformValues[9]; + unsigned numTransformValues = 0; +#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \ + if (flags & (unsigned) flags_t::flag) \ + transformValues[numTransformValues++] = transform.name; + PROCESS_TRANSFORM_COMPONENTS; +#undef PROCESS_TRANSFORM_COMPONENT + varStore.get_delta (transformVarIdx, coords, hb_array (transformValues, numTransformValues), cache); + numTransformValues = 0; +#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \ + if (flags & (unsigned) flags_t::flag) \ + transform.name = transformValues[numTransformValues++]; + PROCESS_TRANSFORM_COMPONENTS; +#undef PROCESS_TRANSFORM_COMPONENT + } + + // Divide them by their divisors +#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \ + if (flags & (unsigned) flags_t::flag) \ + { \ + HBINT16 int_v; \ + int_v = roundf (transform.name); \ + type typed_v = * (const type *) &int_v; \ + float float_v = (float) typed_v; \ + transform.name = float_v; \ + } + PROCESS_TRANSFORM_COMPONENTS; +#undef PROCESS_TRANSFORM_COMPONENT + + if (!(flags & (unsigned) flags_t::HAVE_SCALE_Y)) + transform.scaleY = transform.scaleX; + + // Scale the transform by the font's scale + float x_scale = font->x_multf; + float y_scale = font->y_multf; + transform.translateX *= x_scale; + transform.translateY *= y_scale; + transform.tCenterX *= x_scale; + transform.tCenterY *= y_scale; + + // Build a transforming pen to apply the transform. + hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs (); + hb_transforming_pen_context_t context {transform.to_transform (), + draw_session.funcs, + draw_session.draw_data, + &draw_session.st}; + hb_draw_session_t transformer_session {transformer_funcs, &context}; + + VARC.get_path_at (font, gid, + transformer_session, component_coords, + parent_gid, + visited, edges_left, depth_left - 1); + } + +#undef PROCESS_TRANSFORM_COMPONENTS +#undef READ_UINT32VAR + + return hb_ubytes_t (record, end - record); +} + +//} // namespace Var +} // namespace OT + +#endif diff --git a/thirdparty/harfbuzz/src/OT/Var/VARC/VARC.hh b/thirdparty/harfbuzz/src/OT/Var/VARC/VARC.hh new file mode 100644 index 0000000000..d60f7b0c28 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Var/VARC/VARC.hh @@ -0,0 +1,193 @@ +#ifndef OT_VAR_VARC_VARC_HH +#define OT_VAR_VARC_VARC_HH + +#include "../../../hb-ot-layout-common.hh" +#include "../../../hb-ot-glyf-table.hh" +#include "../../../hb-ot-cff2-table.hh" +#include "../../../hb-ot-cff1-table.hh" + +#include "coord-setter.hh" + +namespace OT { + +//namespace Var { + +/* + * VARC -- Variable Composites + * https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md + */ + +#ifndef HB_NO_VAR_COMPOSITES + +struct VarComponent +{ + enum class flags_t : uint32_t + { + RESET_UNSPECIFIED_AXES = 1u << 0, + HAVE_AXES = 1u << 1, + AXIS_VALUES_HAVE_VARIATION = 1u << 2, + TRANSFORM_HAS_VARIATION = 1u << 3, + HAVE_TRANSLATE_X = 1u << 4, + HAVE_TRANSLATE_Y = 1u << 5, + HAVE_ROTATION = 1u << 6, + HAVE_CONDITION = 1u << 7, + HAVE_SCALE_X = 1u << 8, + HAVE_SCALE_Y = 1u << 9, + HAVE_TCENTER_X = 1u << 10, + HAVE_TCENTER_Y = 1u << 11, + GID_IS_24BIT = 1u << 12, + HAVE_SKEW_X = 1u << 13, + HAVE_SKEW_Y = 1u << 14, + RESERVED_MASK = ~((1u << 15) - 1), + }; + + HB_INTERNAL hb_ubytes_t + get_path_at (hb_font_t *font, + hb_codepoint_t parent_gid, + hb_draw_session_t &draw_session, + hb_array_t<const int> coords, + hb_ubytes_t record, + hb_set_t *visited, + signed *edges_left, + signed depth_left, + VarRegionList::cache_t *cache = nullptr) const; +}; + +struct VarCompositeGlyph +{ + static void + get_path_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_session_t &draw_session, + hb_array_t<const int> coords, + hb_ubytes_t record, + hb_set_t *visited, + signed *edges_left, + signed depth_left, + VarRegionList::cache_t *cache = nullptr) + { + while (record) + { + const VarComponent &comp = * (const VarComponent *) (record.arrayZ); + record = comp.get_path_at (font, glyph, + draw_session, coords, + record, + visited, edges_left, depth_left, cache); + } + } +}; + +HB_MARK_AS_FLAG_T (VarComponent::flags_t); + +struct VARC +{ + friend struct VarComponent; + + static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); + + bool + get_path_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_session_t &draw_session, + hb_array_t<const int> coords, + hb_codepoint_t parent_glyph = HB_CODEPOINT_INVALID, + hb_set_t *visited = nullptr, + signed *edges_left = nullptr, + signed depth_left = HB_MAX_NESTING_LEVEL) const + { + hb_set_t stack_set; + if (visited == nullptr) + visited = &stack_set; + signed stack_edges = HB_MAX_GRAPH_EDGE_COUNT; + if (edges_left == nullptr) + edges_left = &stack_edges; + + // Don't recurse on the same glyph. + unsigned idx = glyph == parent_glyph ? + NOT_COVERED : + (this+coverage).get_coverage (glyph); + if (idx == NOT_COVERED) + { + if (!font->face->table.glyf->get_path_at (font, glyph, draw_session, coords)) +#ifndef HB_NO_CFF + if (!font->face->table.cff2->get_path_at (font, glyph, draw_session, coords)) + if (!font->face->table.cff1->get_path (font, glyph, draw_session)) // Doesn't have variations +#endif + return false; + return true; + } + + if (depth_left <= 0) + return true; + + if (*edges_left <= 0) + return true; + (*edges_left)--; + + if (visited->has (glyph) || visited->in_error ()) + return true; + visited->add (glyph); + + hb_ubytes_t record = (this+glyphRecords)[idx]; + + VarRegionList::cache_t *cache = record.length >= 64 ? // Heuristic + (this+varStore).create_cache () + : nullptr; + + VarCompositeGlyph::get_path_at (font, glyph, + draw_session, coords, + record, + visited, edges_left, depth_left, + cache); + + (this+varStore).destroy_cache (cache); + + visited->del (glyph); + + return true; + } + + bool + get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const + { return get_path_at (font, gid, draw_session, hb_array (font->coords, font->num_coords)); } + + bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const + { + funcs->push_clip_glyph (data, gid, font); + funcs->color (data, true, foreground); + funcs->pop_clip (data); + + return true; + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + hb_barrier () && + version.major == 1 && + coverage.sanitize (c, this) && + varStore.sanitize (c, this) && + conditionList.sanitize (c, this) && + axisIndicesList.sanitize (c, this) && + glyphRecords.sanitize (c, this)); + } + + protected: + FixedVersion<> version; /* Version identifier */ + Offset32To<Coverage> coverage; + Offset32To<MultiItemVariationStore> varStore; + Offset32To<ConditionList> conditionList; + Offset32To<TupleList> axisIndicesList; + Offset32To<CFF2Index/*Of<VarCompositeGlyph>*/> glyphRecords; + public: + DEFINE_SIZE_STATIC (24); +}; + +#endif + +//} + +} + +#endif /* OT_VAR_VARC_VARC_HH */ diff --git a/thirdparty/harfbuzz/src/OT/Var/VARC/coord-setter.hh b/thirdparty/harfbuzz/src/OT/Var/VARC/coord-setter.hh new file mode 100644 index 0000000000..a2b483ce25 --- /dev/null +++ b/thirdparty/harfbuzz/src/OT/Var/VARC/coord-setter.hh @@ -0,0 +1,37 @@ +#ifndef OT_VAR_VARC_COORD_SETTER_HH +#define OT_VAR_VARC_COORD_SETTER_HH + + +#include "../../../hb.hh" + + +namespace OT { +//namespace Var { + + +struct coord_setter_t +{ + coord_setter_t (hb_array_t<const int> coords) : + coords (coords) {} + + int& operator [] (unsigned idx) + { + if (unlikely (idx >= HB_VAR_COMPOSITE_MAX_AXES)) + return Crap(int); + if (coords.length < idx + 1) + coords.resize (idx + 1); + return coords[idx]; + } + + hb_array_t<int> get_coords () + { return coords.as_array (); } + + hb_vector_t<int> coords; +}; + + +//} // namespace Var + +} // namespace OT + +#endif /* OT_VAR_VARC_COORD_SETTER_HH */ diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh index 69a0b625c7..7772597e59 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh @@ -7,8 +7,6 @@ #include "GlyphHeader.hh" #include "SimpleGlyph.hh" #include "CompositeGlyph.hh" -#include "VarCompositeGlyph.hh" -#include "coord-setter.hh" namespace OT { @@ -33,9 +31,6 @@ struct Glyph EMPTY, SIMPLE, COMPOSITE, -#ifndef HB_NO_VAR_COMPOSITES - VAR_COMPOSITE, -#endif }; public: @@ -44,22 +39,10 @@ struct Glyph if (type != COMPOSITE) return composite_iter_t (); return CompositeGlyph (*header, bytes).iter (); } - var_composite_iter_t get_var_composite_iterator () const - { -#ifndef HB_NO_VAR_COMPOSITES - if (type != VAR_COMPOSITE) return var_composite_iter_t (); - return VarCompositeGlyph (*header, bytes).iter (); -#else - return var_composite_iter_t (); -#endif - } const hb_bytes_t trim_padding () const { switch (type) { -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: return VarCompositeGlyph (*header, bytes).trim_padding (); -#endif case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding (); case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding (); case EMPTY: return bytes; @@ -70,9 +53,6 @@ struct Glyph void drop_hints () { switch (type) { -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: return; // No hinting -#endif case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return; case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return; case EMPTY: return; @@ -82,9 +62,6 @@ struct Glyph void set_overlaps_flag () { switch (type) { -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: return; // No overlaps flag -#endif case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return; case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return; case EMPTY: return; @@ -94,9 +71,6 @@ struct Glyph void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const { switch (type) { -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: return; // No hinting -#endif case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return; case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return; case EMPTY: return; @@ -120,14 +94,6 @@ struct Glyph if (unlikely (!item.get_points (points))) return false; break; } -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: - { - for (auto &item : get_var_composite_iterator ()) - if (unlikely (!item.get_points (points))) return false; - break; - } -#endif case EMPTY: break; } @@ -303,13 +269,6 @@ struct Glyph { switch (type) { -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: - // TODO - dest_end = hb_bytes_t (); - break; -#endif - case COMPOSITE: if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start, points_with_deltas, @@ -352,7 +311,7 @@ struct Glyph bool shift_points_hori = true, bool use_my_metrics = true, bool phantom_only = false, - hb_array_t<int> coords = hb_array_t<int> (), + hb_array_t<const int> coords = hb_array_t<const int> (), hb_map_t *current_glyphs = nullptr, unsigned int depth = 0, unsigned *edge_count = nullptr) const @@ -360,7 +319,7 @@ struct Glyph if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false; unsigned stack_edge_count = 0; if (!edge_count) edge_count = &stack_edge_count; - if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false; + if (unlikely (*edge_count > HB_MAX_GRAPH_EDGE_COUNT)) return false; (*edge_count)++; hb_map_t current_glyphs_stack; @@ -394,14 +353,6 @@ struct Glyph if (unlikely (!item.get_points (points))) return false; break; } -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: - { - for (auto &item : get_var_composite_iterator ()) - if (unlikely (!item.get_points (points))) return false; - break; - } -#endif case EMPTY: break; } @@ -542,81 +493,6 @@ struct Glyph } all_points.extend (phantoms); } break; -#ifndef HB_NO_VAR_COMPOSITES - case VAR_COMPOSITE: - { - hb_array_t<contour_point_t> points_left = points.as_array (); - for (auto &item : get_var_composite_iterator ()) - { - hb_codepoint_t item_gid = item.get_gid (); - - if (unlikely (current_glyphs->has (item_gid))) - continue; - - current_glyphs->add (item_gid); - - unsigned item_num_points = item.get_num_points (); - hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item_num_points); - assert (record_points.length == item_num_points); - - auto component_coords = coords; - /* Copying coords is expensive; so we have put an arbitrary - * limit on the max number of coords for now. */ - if (item.is_reset_unspecified_axes () || - coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES) - component_coords = hb_array<int> (); - - coord_setter_t coord_setter (component_coords); - item.set_variations (coord_setter, record_points); - - unsigned old_count = all_points.length; - - if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && - !glyf_accelerator.glyph_for_gid (item_gid) - .get_points (font, - glyf_accelerator, - all_points, - points_with_deltas, - head_maxp_info, - nullptr, - shift_points_hori, - use_my_metrics, - phantom_only, - coord_setter.get_coords (), - current_glyphs, - depth + 1, - edge_count))) - { - current_glyphs->del (item_gid); - return false; - } - - auto comp_points = all_points.as_array ().sub_array (old_count); - - /* Apply component transformation */ - if (comp_points) // Empty in case of phantom_only - item.transform_points (record_points, comp_points); - - /* Copy phantom points from component if USE_MY_METRICS flag set */ - if (use_my_metrics && item.is_use_my_metrics ()) - for (unsigned int i = 0; i < PHANTOM_COUNT; i++) - phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; - - all_points.resize (all_points.length - PHANTOM_COUNT); - - if (all_points.length > HB_GLYF_MAX_POINTS) - { - current_glyphs->del (item_gid); - return false; - } - - points_left += item_num_points; - - current_glyphs->del (item_gid); - } - all_points.extend (phantoms); - } break; -#endif case EMPTY: all_points.extend (phantoms); break; @@ -627,7 +503,7 @@ struct Glyph /* Undocumented rasterizer behavior: * Shift points horizontally by the updated left side bearing */ - int v = -phantoms[PHANTOM_LEFT].x; + float v = -phantoms[PHANTOM_LEFT].x; if (v) for (auto &point : all_points) point.x += v; @@ -661,10 +537,7 @@ struct Glyph int num_contours = header->numberOfContours; if (unlikely (num_contours == 0)) type = EMPTY; else if (num_contours > 0) type = SIMPLE; - else if (num_contours == -1) type = COMPOSITE; -#ifndef HB_NO_VAR_COMPOSITES - else if (num_contours == -2) type = VAR_COMPOSITE; -#endif + else if (num_contours <= -1) type = COMPOSITE; else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild. } diff --git a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh index 8099d3c126..fe63066e41 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh @@ -53,23 +53,12 @@ struct SubsetGlyph if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid)) const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid); } -#ifndef HB_NO_VAR_COMPOSITES - for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ()) - { - hb_codepoint_t new_gid; - if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid)) - const_cast<VarCompositeGlyphRecord &> (_).set_gid (new_gid); - } -#endif #ifndef HB_NO_BEYOND_64K auto it = Glyph (dest_glyph).get_composite_iterator (); if (it) { - /* lower GID24 to GID16 in components if possible. - * - * TODO: VarComposite. Not as critical, since VarComposite supports - * gid24 from the first version. */ + /* lower GID24 to GID16 in components if possible. */ char *p = it ? (char *) &*it : nullptr; char *q = p; const char *end = dest_glyph.arrayZ + dest_glyph.length; diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh index 6300cf4be0..f346ae05dc 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh @@ -205,8 +205,12 @@ struct glyf_accelerator_t protected: template<typename T> - bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const + bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer, + hb_array_t<const int> coords = hb_array_t<const int> ()) const { + if (!coords) + coords = hb_array (font->coords, font->num_coords); + if (gid >= num_glyphs) return false; /* Making this allocfree is not that easy @@ -216,7 +220,7 @@ struct glyf_accelerator_t contour_point_vector_t all_points; bool phantom_only = !consumer.is_consuming_contour_points (); - if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only))) + if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only, coords))) return false; unsigned count = all_points.length; @@ -408,6 +412,11 @@ struct glyf_accelerator_t get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); } + bool + get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session, + hb_array_t<const int> coords) const + { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), coords); } + #ifndef HB_NO_VAR const gvar_accelerator_t *gvar; #endif diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh index 2a9d8346c0..b24507ece1 100644 --- a/thirdparty/harfbuzz/src/graph/graph.hh +++ b/thirdparty/harfbuzz/src/graph/graph.hh @@ -368,7 +368,7 @@ struct graph_t // it's parent where possible. int64_t modified_distance = - hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF); + hb_clamp (distance + distance_modifier (), (int64_t) 0, 0x7FFFFFFFFFF); if (has_max_priority ()) { modified_distance = 0; } @@ -1141,7 +1141,7 @@ struct graph_t unsigned clone_idx = duplicate (child_idx); if (clone_idx == (unsigned) -1) return false; - + for (unsigned parent_idx : *parents) { // duplicate shifts the root node idx, so if parent_idx was root update it. if (parent_idx == clone_idx) parent_idx++; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh index c26f376aa6..2ea86a2a19 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh @@ -39,6 +39,7 @@ namespace AAT { using namespace OT; +#define HB_AAT_BUFFER_DIGEST_THRESHOLD 32 struct ankr; @@ -60,6 +61,7 @@ struct hb_aat_apply_context_t : const ankr *ankr_table; const OT::GDEF *gdef_table; const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr; + hb_set_digest_t buffer_digest = hb_set_digest_t::full (); hb_set_digest_t machine_glyph_set = hb_set_digest_t::full (); hb_set_digest_t left_set = hb_set_digest_t::full (); hb_set_digest_t right_set = hb_set_digest_t::full (); @@ -466,11 +468,11 @@ struct Lookup const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const { switch (u.format) { - case 0: return u.format0.get_value (glyph_id, num_glyphs); - case 2: return u.format2.get_value (glyph_id); - case 4: return u.format4.get_value (glyph_id); - case 6: return u.format6.get_value (glyph_id); - case 8: return u.format8.get_value (glyph_id); + case 0: hb_barrier (); return u.format0.get_value (glyph_id, num_glyphs); + case 2: hb_barrier (); return u.format2.get_value (glyph_id); + case 4: hb_barrier (); return u.format4.get_value (glyph_id); + case 6: hb_barrier (); return u.format6.get_value (glyph_id); + case 8: hb_barrier (); return u.format8.get_value (glyph_id); default:return nullptr; } } @@ -479,7 +481,7 @@ struct Lookup { switch (u.format) { /* Format 10 cannot return a pointer. */ - case 10: return u.format10.get_value_or_null (glyph_id); + case 10: hb_barrier (); return u.format10.get_value_or_null (glyph_id); default: const T *v = get_value (glyph_id, num_glyphs); return v ? *v : Null (T); @@ -490,12 +492,12 @@ struct Lookup void collect_glyphs (set_t &glyphs, unsigned int num_glyphs) const { switch (u.format) { - case 0: u.format0.collect_glyphs (glyphs, num_glyphs); return; - case 2: u.format2.collect_glyphs (glyphs); return; - case 4: u.format4.collect_glyphs (glyphs); return; - case 6: u.format6.collect_glyphs (glyphs); return; - case 8: u.format8.collect_glyphs (glyphs); return; - case 10: u.format10.collect_glyphs (glyphs); return; + case 0: hb_barrier (); u.format0.collect_glyphs (glyphs, num_glyphs); return; + case 2: hb_barrier (); u.format2.collect_glyphs (glyphs); return; + case 4: hb_barrier (); u.format4.collect_glyphs (glyphs); return; + case 6: hb_barrier (); u.format6.collect_glyphs (glyphs); return; + case 8: hb_barrier (); u.format8.collect_glyphs (glyphs); return; + case 10: hb_barrier (); u.format10.collect_glyphs (glyphs); return; default:return; } } @@ -514,12 +516,12 @@ struct Lookup if (!u.format.sanitize (c)) return_trace (false); hb_barrier (); switch (u.format) { - case 0: return_trace (u.format0.sanitize (c)); - case 2: return_trace (u.format2.sanitize (c)); - case 4: return_trace (u.format4.sanitize (c)); - case 6: return_trace (u.format6.sanitize (c)); - case 8: return_trace (u.format8.sanitize (c)); - case 10: return_trace (u.format10.sanitize (c)); + case 0: hb_barrier (); return_trace (u.format0.sanitize (c)); + case 2: hb_barrier (); return_trace (u.format2.sanitize (c)); + case 4: hb_barrier (); return_trace (u.format4.sanitize (c)); + case 6: hb_barrier (); return_trace (u.format6.sanitize (c)); + case 8: hb_barrier (); return_trace (u.format8.sanitize (c)); + case 10: hb_barrier (); return_trace (u.format10.sanitize (c)); default:return_trace (true); } } @@ -529,11 +531,11 @@ struct Lookup if (!u.format.sanitize (c)) return_trace (false); hb_barrier (); switch (u.format) { - case 0: return_trace (u.format0.sanitize (c, base)); - case 2: return_trace (u.format2.sanitize (c, base)); - case 4: return_trace (u.format4.sanitize (c, base)); - case 6: return_trace (u.format6.sanitize (c, base)); - case 8: return_trace (u.format8.sanitize (c, base)); + case 0: hb_barrier (); return_trace (u.format0.sanitize (c, base)); + case 2: hb_barrier (); return_trace (u.format2.sanitize (c, base)); + case 4: hb_barrier (); return_trace (u.format4.sanitize (c, base)); + case 6: hb_barrier (); return_trace (u.format6.sanitize (c, base)); + case 8: hb_barrier (); return_trace (u.format8.sanitize (c, base)); case 10: return_trace (false); /* We don't support format10 here currently. */ default:return_trace (true); } @@ -927,7 +929,15 @@ struct StateTableDriver machine (machine_), num_glyphs (face_->get_num_glyphs ()) {} - template <typename context_t, typename set_t = hb_set_digest_t> + template <typename context_t> + bool is_idempotent_on_all_out_of_bounds (context_t *c, hb_aat_apply_context_t *ac) + { + const auto entry = machine.get_entry (StateTableT::STATE_START_OF_TEXT, CLASS_OUT_OF_BOUNDS); + return !c->is_actionable (ac->buffer, this, entry) && + machine.new_state (entry.newState) == StateTableT::STATE_START_OF_TEXT; + } + + template <typename context_t> void drive (context_t *c, hb_aat_apply_context_t *ac) { hb_buffer_t *buffer = ac->buffer; @@ -1005,7 +1015,7 @@ struct StateTableDriver const auto is_safe_to_break_extra = [&]() { /* 2c. */ - const auto wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass); + const auto &wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass); /* 2c'. */ if (c->is_actionable (buffer, this, wouldbe_entry)) diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh index ee08da172e..9531b5e4b3 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh @@ -189,12 +189,12 @@ struct ActionSubrecord switch (u.header.actionType) { - case 0: return_trace (u.decompositionAction.sanitize (c)); - case 1: return_trace (u.unconditionalAddGlyphAction.sanitize (c)); - case 2: return_trace (u.conditionalAddGlyphAction.sanitize (c)); - // case 3: return_trace (u.stretchGlyphAction.sanitize (c)); - case 4: return_trace (u.decompositionAction.sanitize (c)); - case 5: return_trace (u.decompositionAction.sanitize (c)); + case 0: hb_barrier (); return_trace (u.decompositionAction.sanitize (c)); + case 1: hb_barrier (); return_trace (u.unconditionalAddGlyphAction.sanitize (c)); + case 2: hb_barrier (); return_trace (u.conditionalAddGlyphAction.sanitize (c)); + // case 3: hb_barrier (); return_trace (u.stretchGlyphAction.sanitize (c)); + case 4: hb_barrier (); return_trace (u.decompositionAction.sanitize (c)); + case 5: hb_barrier (); return_trace (u.decompositionAction.sanitize (c)); default: return_trace (true); } } diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh index 8d0d87af02..c01c31d735 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh @@ -107,10 +107,14 @@ struct KerxSubTableFormat0 TRACE_APPLY (this); if (!c->plan->requested_kerning) - return false; + return_trace (false); if (header.coverage & header.Backwards) - return false; + return_trace (false); + + if (!(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); accelerator_t accel (*this, c); hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream); @@ -367,6 +371,12 @@ struct KerxSubTableFormat1 driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->font->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); + driver.drive (&dc, c); return_trace (true); @@ -425,10 +435,14 @@ struct KerxSubTableFormat2 TRACE_APPLY (this); if (!c->plan->requested_kerning) - return false; + return_trace (false); if (header.coverage & header.Backwards) - return false; + return_trace (false); + + if (!(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); accelerator_t accel (*this, c); hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream); @@ -635,6 +649,12 @@ struct KerxSubTableFormat4 driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->font->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); + driver.drive (&dc, c); return_trace (true); @@ -710,10 +730,14 @@ struct KerxSubTableFormat6 TRACE_APPLY (this); if (!c->plan->requested_kerning) - return false; + return_trace (false); if (header.coverage & header.Backwards) - return false; + return_trace (false); + + if (!(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); accelerator_t accel (*this, c); hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream); @@ -919,6 +943,9 @@ struct KerxTable { if (st->get_type () == 1) return true; + + // TODO: What about format 4? What's this API used for anyway? + st = &StructAfter<SubTable> (*st); } return false; @@ -962,6 +989,11 @@ struct KerxTable { c->buffer->unsafe_to_concat (); + if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD) + c->buffer_digest = c->buffer->digest (); + else + c->buffer_digest = hb_set_digest_t::full (); + typedef typename T::SubTable SubTable; bool ret = false; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index 4a94e6a8ff..d31834402a 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -170,6 +170,11 @@ struct RearrangementSubtable driver_context_t dc (this); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -267,6 +272,7 @@ struct ContextualSubtable { buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); buffer->info[mark].codepoint = *replacement; + c->buffer_digest.add (*replacement); if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&buffer->info[mark], gdef.get_glyph_props (*replacement)); @@ -296,6 +302,7 @@ struct ContextualSubtable if (replacement) { buffer->info[idx].codepoint = *replacement; + c->buffer_digest.add (*replacement); if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&buffer->info[idx], gdef.get_glyph_props (*replacement)); @@ -328,6 +335,11 @@ struct ContextualSubtable driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -586,6 +598,11 @@ struct LigatureSubtable driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -654,6 +671,7 @@ struct NoncontextualSubtable if (replacement) { info[i].codepoint = *replacement; + c->buffer_digest.add (*replacement); if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&info[i], gdef.get_glyph_props (*replacement)); @@ -788,6 +806,9 @@ struct InsertionSubtable if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; + for (unsigned int i = 0; i < count; i++) + c->buffer_digest.add (glyphs[i]); + ret = true; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); @@ -853,6 +874,11 @@ struct InsertionSubtable driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -1036,7 +1062,8 @@ struct ChainSubtable bool apply (hb_aat_apply_context_t *c) const { TRACE_APPLY (this); - hb_sanitize_with_object_t with (&c->sanitizer, this); + // Disabled for https://github.com/harfbuzz/harfbuzz/issues/4873 + //hb_sanitize_with_object_t with (&c->sanitizer, this); return_trace (dispatch (c)); } @@ -1049,7 +1076,8 @@ struct ChainSubtable c->check_range (this, length))) return_trace (false); - hb_sanitize_with_object_t with (c, this); + // Disabled for https://github.com/harfbuzz/harfbuzz/issues/4873 + //hb_sanitize_with_object_t with (c, this); return_trace (dispatch (c)); } @@ -1348,6 +1376,11 @@ struct mortmorx c->buffer->unsafe_to_concat (); + if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD) + c->buffer_digest = c->buffer->digest (); + else + c->buffer_digest = hb_set_digest_t::full (); + c->set_lookup_index (0); const Chain<Types> *chain = &firstChain; unsigned int count = chainCount; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh index 9840d3a554..dc75f5db57 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh @@ -133,8 +133,8 @@ struct opbd { switch (format) { - case 0: return u.format0.get_bounds (font, glyph_id, extents, this); - case 1: return u.format1.get_bounds (font, glyph_id, extents, this); + case 0: hb_barrier (); return u.format0.get_bounds (font, glyph_id, extents, this); + case 1: hb_barrier (); return u.format1.get_bounds (font, glyph_id, extents, this); default:return false; } } @@ -148,8 +148,8 @@ struct opbd switch (format) { - case 0: return_trace (u.format0.sanitize (c, this)); - case 1: return_trace (u.format1.sanitize (c, this)); + case 0: hb_barrier (); return_trace (u.format0.sanitize (c, this)); + case 1: hb_barrier (); return_trace (u.format1.sanitize (c, this)); default:return_trace (true); } } diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc index 671d6eda8c..345f08d260 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-verify.cc +++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc @@ -412,7 +412,7 @@ hb_buffer_t::verify (hb_buffer_t *text_buffer, &len, HB_BUFFER_SERIALIZE_FORMAT_TEXT, HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS); - buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ); + buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ ? bytes.arrayZ : ""); } #endif } diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index d621a7cc55..3fc869887e 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -271,6 +271,7 @@ hb_buffer_t::similar (const hb_buffer_t &src) replacement = src.replacement; invisible = src.invisible; not_found = src.not_found; + not_found_variation_selector = src.not_found_variation_selector; } void @@ -283,6 +284,7 @@ hb_buffer_t::reset () replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; invisible = 0; not_found = 0; + not_found_variation_selector = HB_CODEPOINT_INVALID; clear (); } @@ -705,6 +707,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, 0, /* invisible */ 0, /* not_found */ + HB_CODEPOINT_INVALID, /* not_found_variation_selector */ HB_BUFFER_CONTENT_TYPE_INVALID, @@ -1361,6 +1364,46 @@ hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer) } /** + * hb_buffer_set_not_found_variation_selector_glyph: + * @buffer: An #hb_buffer_t + * @not_found_variation_selector: the not-found-variation-selector #hb_codepoint_t + * + * Sets the #hb_codepoint_t that replaces variation-selector characters not resolved + * in the font during shaping. + * + * The not-found-variation-selector glyph defaults to #HB_CODEPOINT_INVALID, + * in which case an unresolved variation-selector will be removed from the glyph + * string during shaping. This API allows for changing that and retaining a glyph, + * such that the situation can be detected by the client and handled accordingly + * (e.g. by using a different font). + * + * Since: 10.0.0 + **/ +void +hb_buffer_set_not_found_variation_selector_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found_variation_selector) +{ + buffer->not_found_variation_selector = not_found_variation_selector; +} + +/** + * hb_buffer_get_not_found_variation_selector_glyph: + * @buffer: An #hb_buffer_t + * + * See hb_buffer_set_not_found_variation_selector_glyph(). + * + * Return value: + * The @buffer not-found-variation-selector #hb_codepoint_t + * + * Since: 10.0.0 + **/ +hb_codepoint_t +hb_buffer_get_not_found_variation_selector_glyph (const hb_buffer_t *buffer) +{ + return buffer->not_found_variation_selector; +} + +/** * hb_buffer_set_random_state: * @buffer: An #hb_buffer_t * @state: the new random state diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h index f75fe96b21..dd0edb9b7d 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.h +++ b/thirdparty/harfbuzz/src/hb-buffer.h @@ -488,6 +488,13 @@ HB_EXTERN hb_codepoint_t hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer); HB_EXTERN void +hb_buffer_set_not_found_variation_selector_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found_variation_selector); + +HB_EXTERN hb_codepoint_t +hb_buffer_get_not_found_variation_selector_glyph (const hb_buffer_t *buffer); + +HB_EXTERN void hb_buffer_set_random_state (hb_buffer_t *buffer, unsigned state); diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index 0a198722d6..2a6ad6128c 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -52,6 +52,7 @@ enum hb_buffer_scratch_flags_t { HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u, HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u, HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000040u, + HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK= 0x00000080u, /* Reserved for shapers' internal use. */ HB_BUFFER_SCRATCH_FLAG_SHAPER0 = 0x01000000u, @@ -80,6 +81,7 @@ struct hb_buffer_t hb_codepoint_t replacement; /* U+FFFD or something else. */ hb_codepoint_t invisible; /* 0 or something else. */ hb_codepoint_t not_found; /* 0 or something else. */ + hb_codepoint_t not_found_variation_selector; /* HB_CODEPOINT_INVALID or something else. */ /* * Buffer contents diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh index 1d1f10f2bf..6ca7500af0 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh @@ -624,7 +624,6 @@ struct opset_t } else { /* invalid unknown operator */ env.clear_args (); - env.set_error (); } break; } diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh index a08b10b5ff..b513a1e8c2 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh @@ -84,7 +84,7 @@ struct dict_opset_t : opset_t<number_t> enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END }; - char buf[32]; + char buf[32] = {0}; unsigned char byte = 0; for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count) { diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h index 533de91562..1108545481 100644 --- a/thirdparty/harfbuzz/src/hb-common.h +++ b/thirdparty/harfbuzz/src/hb-common.h @@ -504,6 +504,13 @@ hb_language_matches (hb_language_t language, * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0 * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0 * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0 + * @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0 + * @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0 + * @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0 + * @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0 + * @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0 + * @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0 + * @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0 * @HB_SCRIPT_INVALID: No script set * * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding @@ -731,6 +738,17 @@ typedef enum HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/ HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/ + /* + * Since 10.0.0 + */ + HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/ + HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/ + HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/ + HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/ + HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/ + HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/ + HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/ + /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh index 816c55c7d3..79fee17517 100644 --- a/thirdparty/harfbuzz/src/hb-config.hh +++ b/thirdparty/harfbuzz/src/hb-config.hh @@ -118,6 +118,10 @@ #define HB_NO_VAR_COMPOSITES #endif +#ifdef HB_NO_VAR +#define HB_NO_VAR_COMPOSITES +#endif + #ifdef HB_DISABLE_DEPRECATED #define HB_IF_NOT_DEPRECATED(x) #else diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc index a87cb5cd02..070b8be02f 100644 --- a/thirdparty/harfbuzz/src/hb-coretext.cc +++ b/thirdparty/harfbuzz/src/hb-coretext.cc @@ -48,6 +48,8 @@ /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f +static CTFontRef create_ct_font (CGFontRef cg_font, CGFloat font_size); + static void release_table_data (void *user_data) { @@ -76,6 +78,52 @@ _hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data release_table_data); } +static unsigned +_hb_cg_get_table_tags (const hb_face_t *face HB_UNUSED, + unsigned int start_offset, + unsigned int *table_count, + hb_tag_t *table_tags, + void *user_data) +{ + CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data); + + CTFontRef ct_font = create_ct_font (cg_font, (CGFloat) HB_CORETEXT_DEFAULT_FONT_SIZE); + + auto arr = CTFontCopyAvailableTables (ct_font, kCTFontTableOptionNoOptions); + + unsigned population = (unsigned) CFArrayGetCount (arr); + unsigned end_offset; + + if (!table_count) + goto done; + + if (unlikely (start_offset >= population)) + { + *table_count = 0; + goto done; + } + + end_offset = start_offset + *table_count; + if (unlikely (end_offset < start_offset)) + { + *table_count = 0; + goto done; + } + end_offset= hb_min (end_offset, (unsigned) population); + + *table_count = end_offset - start_offset; + for (unsigned i = start_offset; i < end_offset; i++) + { + CTFontTableTag tag = (CTFontTableTag)(uintptr_t) CFArrayGetValueAtIndex (arr, i); + table_tags[i - start_offset] = tag; + } + +done: + CFRelease (arr); + CFRelease (ct_font); + return population; +} + static void _hb_cg_font_release (void *data) { @@ -294,7 +342,9 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data) hb_face_t * hb_coretext_face_create (CGFontRef cg_font) { - return hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release); + hb_face_t *face = hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release); + hb_face_set_get_table_tags_func (face, _hb_cg_get_table_tags, cg_font, nullptr); + return face; } /** diff --git a/thirdparty/harfbuzz/src/hb-draw.hh b/thirdparty/harfbuzz/src/hb-draw.hh index 25dee1261e..87d03a4882 100644 --- a/thirdparty/harfbuzz/src/hb-draw.hh +++ b/thirdparty/harfbuzz/src/hb-draw.hh @@ -232,7 +232,7 @@ struct hb_draw_session_t funcs->close_path (draw_data, st); } - protected: + public: float slant; bool not_slanted; hb_draw_funcs_t *funcs; diff --git a/thirdparty/harfbuzz/src/hb-face-builder.cc b/thirdparty/harfbuzz/src/hb-face-builder.cc index 84b14d28d6..beea89ed22 100644 --- a/thirdparty/harfbuzz/src/hb-face-builder.cc +++ b/thirdparty/harfbuzz/src/hb-face-builder.cc @@ -42,7 +42,7 @@ struct face_table_info_t { hb_blob_t* data; - signed order; + unsigned order; }; struct hb_face_builder_data_t @@ -153,6 +153,50 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void return hb_blob_reference (data->tables[tag].data); } +static unsigned +_hb_face_builder_get_table_tags (const hb_face_t *face HB_UNUSED, + unsigned int start_offset, + unsigned int *table_count, + hb_tag_t *table_tags, + void *user_data) +{ + hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data; + + unsigned population = data->tables.get_population (); + + if (!table_count) + return population; + + if (unlikely (start_offset >= population)) + { + if (table_count) + *table_count = 0; + return population; + } + + // Sort the tags. + hb_vector_t<hb_tag_t> sorted_tags; + data->tables.keys () | hb_sink (sorted_tags); + if (unlikely (sorted_tags.in_error ())) + { + // Not much to do... + } + sorted_tags.qsort ([] (const void* a, const void* b) { + return * (hb_tag_t *) a < * (hb_tag_t *) b ? -1 : + * (hb_tag_t *) a == * (hb_tag_t *) b ? 0 : + +1; + }); + + auto array = sorted_tags.as_array ().sub_array (start_offset, table_count); + auto out = hb_array (table_tags, *table_count); + + + array.iter () + | hb_sink (out) + ; + + return population; +} + /** * hb_face_builder_create: @@ -171,9 +215,16 @@ hb_face_builder_create () hb_face_builder_data_t *data = _hb_face_builder_data_create (); if (unlikely (!data)) return hb_face_get_empty (); - return hb_face_create_for_tables (_hb_face_builder_reference_table, - data, - _hb_face_builder_data_destroy); + hb_face_t *face = hb_face_create_for_tables (_hb_face_builder_reference_table, + data, + _hb_face_builder_data_destroy); + + hb_face_set_get_table_tags_func (face, + _hb_face_builder_get_table_tags, + data, + nullptr); + + return face; } /** @@ -199,7 +250,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_blob_t* previous = data->tables.get (tag).data; - if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1})) + if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), (unsigned) -1})) { hb_blob_destroy (blob); return false; diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc index e340710586..9b4af16f4d 100644 --- a/thirdparty/harfbuzz/src/hb-face.cc +++ b/thirdparty/harfbuzz/src/hb-face.cc @@ -90,10 +90,6 @@ DEFINE_NULL_INSTANCE (hb_face_t) = { HB_OBJECT_HEADER_STATIC, - nullptr, /* reference_table_func */ - nullptr, /* user_data */ - nullptr, /* destroy */ - 0, /* index */ 1000, /* upem */ 0, /* num_glyphs */ @@ -110,8 +106,9 @@ DEFINE_NULL_INSTANCE (hb_face_t) = * * 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 - * data. With the caveat that hb_face_get_table_tags() does not currently work - * with faces created this way. + * data. With the caveat that hb_face_get_table_tags() would not work + * with faces created this way. You can address that by calling the + * hb_face_set_get_table_tags_func() function and setting the appropriate callback. * * Creates a new face object from the specified @user_data and @reference_table_func, * with the @destroy callback. @@ -194,6 +191,22 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void return blob; } +static unsigned +_hb_face_for_data_get_table_tags (const hb_face_t *face HB_UNUSED, + unsigned int start_offset, + unsigned int *table_count, + hb_tag_t *table_tags, + void *user_data) +{ + hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data; + + const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> (); + const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); + + return ot_face.get_table_tags (start_offset, table_count, table_tags); +} + + /** * hb_face_create: * @blob: #hb_blob_t to work upon @@ -240,6 +253,10 @@ hb_face_create (hb_blob_t *blob, face = hb_face_create_for_tables (_hb_face_for_data_reference_table, closure, _hb_face_for_data_closure_destroy); + hb_face_set_get_table_tags_func (face, + _hb_face_for_data_get_table_tags, + closure, + nullptr); face->index = index; @@ -306,6 +323,9 @@ hb_face_destroy (hb_face_t *face) face->data.fini (); face->table.fini (); + if (face->get_table_tags_destroy) + face->get_table_tags_destroy (face->get_table_tags_user_data); + if (face->destroy) face->destroy (face->user_data); @@ -548,6 +568,37 @@ hb_face_get_glyph_count (const hb_face_t *face) } /** + * hb_face_set_get_table_tags_func: + * @face: A face object + * @func: (closure user_data) (destroy destroy) (scope notified): The table-tag-fetching function + * @user_data: A pointer to the user data, to be destroyed by @destroy when not needed anymore + * @destroy: (nullable): A callback to call when @func is not needed anymore + * + * Sets the table-tag-fetching function for the specified face object. + * + * Since: 10.0.0 + */ +HB_EXTERN void +hb_face_set_get_table_tags_func (hb_face_t *face, + hb_get_table_tags_func_t func, + void *user_data, + hb_destroy_func_t destroy) +{ + if (hb_object_is_immutable (face)) + { + if (destroy) + destroy (user_data); + } + + if (face->get_table_tags_destroy) + face->get_table_tags_destroy (face->get_table_tags_user_data); + + face->get_table_tags_func = func; + face->get_table_tags_user_data = user_data; + face->get_table_tags_destroy = destroy; +} + +/** * hb_face_get_table_tags: * @face: A face object * @start_offset: The index of first table tag to retrieve @@ -568,19 +619,14 @@ hb_face_get_table_tags (const hb_face_t *face, unsigned int *table_count, /* IN/OUT */ hb_tag_t *table_tags /* OUT */) { - if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy) + if (!face->get_table_tags_func) { if (table_count) *table_count = 0; return 0; } - hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data; - - const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> (); - const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); - - return ot_face.get_table_tags (start_offset, table_count, table_tags); + return face->get_table_tags_func (face, start_offset, table_count, table_tags, face->get_table_tags_user_data); } diff --git a/thirdparty/harfbuzz/src/hb-face.h b/thirdparty/harfbuzz/src/hb-face.h index 2e54ccf13b..98d0afec26 100644 --- a/thirdparty/harfbuzz/src/hb-face.h +++ b/thirdparty/harfbuzz/src/hb-face.h @@ -135,6 +135,34 @@ hb_face_set_glyph_count (hb_face_t *face, HB_EXTERN unsigned int hb_face_get_glyph_count (const hb_face_t *face); + +/** + * hb_get_table_tags_func_t: + * @face: A face object + * @start_offset: The index of first table tag to retrieve + * @table_count: (inout): Input = the maximum number of table tags to return; + * Output = the actual number of table tags returned (may be zero) + * @table_tags: (out) (array length=table_count): The array of table tags found + * @user_data: User data pointer passed by the caller + * + * Callback function for hb_face_get_table_tags(). + * + * Return value: Total number of tables, or zero if it is not possible to list + * + * Since: 10.0.0 + */ +typedef unsigned int (*hb_get_table_tags_func_t) (const hb_face_t *face, + unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */, + void *user_data); + +HB_EXTERN void +hb_face_set_get_table_tags_func (hb_face_t *face, + hb_get_table_tags_func_t func, + void *user_data, + hb_destroy_func_t destroy); + HB_EXTERN unsigned int hb_face_get_table_tags (const hb_face_t *face, unsigned int start_offset, diff --git a/thirdparty/harfbuzz/src/hb-face.hh b/thirdparty/harfbuzz/src/hb-face.hh index aff3ff0d07..6401568326 100644 --- a/thirdparty/harfbuzz/src/hb-face.hh +++ b/thirdparty/harfbuzz/src/hb-face.hh @@ -48,13 +48,17 @@ struct hb_face_t { hb_object_header_t header; + unsigned int index; /* Face index in a collection, zero-based. */ + mutable hb_atomic_int_t upem; /* Units-per-EM. */ + mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */ + hb_reference_table_func_t reference_table_func; void *user_data; hb_destroy_func_t destroy; - unsigned int index; /* Face index in a collection, zero-based. */ - mutable hb_atomic_int_t upem; /* Units-per-EM. */ - mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */ + hb_get_table_tags_func_t get_table_tags_func; + void *get_table_tags_user_data; + hb_destroy_func_t get_table_tags_destroy; hb_shaper_object_dataset_t<hb_face_t> data;/* Various shaper data. */ hb_ot_face_t table; /* All the face's tables. */ diff --git a/thirdparty/harfbuzz/src/hb-features.h b/thirdparty/harfbuzz/src/hb-features.h deleted file mode 100644 index 9199864195..0000000000 --- a/thirdparty/harfbuzz/src/hb-features.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2022 Red Hat, 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. - */ - -#ifndef HB_FEATURES_H -#define HB_FEATURES_H - -HB_BEGIN_DECLS - -/** - * SECTION: hb-features - * @title: hb-features - * @short_description: Feature detection - * @include: hb-features.h - * - * Macros for detecting optional HarfBuzz features at build time. - **/ - -/** - * HB_HAS_CAIRO: - * - * Defined if Harfbuzz has been built with cairo support. - */ -# - -/** - * HB_HAS_CORETEXT: - * - * Defined if Harfbuzz has been built with CoreText support. - */ -#undef HB_HAS_CORETEXT - -/** - * HB_HAS_DIRECTWRITE: - * - * Defined if Harfbuzz has been built with DirectWrite support. - */ -#undef HB_HAS_DIRECTWRITE - -/** - * HB_HAS_FREETYPE: - * - * Defined if Harfbuzz has been built with Freetype support. - */ -#define HB_HAS_FREETYPE 1 - -/** - * HB_HAS_GDI: - * - * Defined if Harfbuzz has been built with GDI support. - */ -#undef HB_HAS_GDI - -/** - * HB_HAS_GLIB: - * - * Defined if Harfbuzz has been built with GLib support. - */ -#define HB_HAS_GLIB 1 - -/** - * HB_HAS_GOBJECT: - * - * Defined if Harfbuzz has been built with GObject support. - */ -#undef HB_HAS_GOBJECT - -/** - * HB_HAS_GRAPHITE: - * - * Defined if Harfbuzz has been built with Graphite support. - */ -#undef HB_HAS_GRAPHITE - -/** - * HB_HAS_ICU: - * - * Defined if Harfbuzz has been built with ICU support. - */ -#undef HB_HAS_ICU - -/** - * HB_HAS_UNISCRIBE: - * - * Defined if Harfbuzz has been built with Uniscribe support. - */ -#undef HB_HAS_UNISCRIBE - -/** - * HB_HAS_WASM: - * - * Defined if Harfbuzz has been built with WebAssembly support. - */ -#undef HB_HAS_WASM - - -HB_END_DECLS - -#endif /* HB_FEATURES_H */ diff --git a/thirdparty/harfbuzz/src/hb-ft-colr.hh b/thirdparty/harfbuzz/src/hb-ft-colr.hh index 1afbbbb183..8766a2a2ce 100644 --- a/thirdparty/harfbuzz/src/hb-ft-colr.hh +++ b/thirdparty/harfbuzz/src/hb-ft-colr.hh @@ -108,7 +108,7 @@ struct hb_ft_paint_context_t hb_map_t current_glyphs; hb_map_t current_layers; int depth_left = HB_MAX_NESTING_LEVEL; - int edge_count = HB_COLRV1_MAX_EDGE_COUNT; + int edge_count = HB_MAX_GRAPH_EDGE_COUNT; }; static unsigned diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc index 3de4a6d5d4..f6d8bf4136 100644 --- a/thirdparty/harfbuzz/src/hb-ft.cc +++ b/thirdparty/harfbuzz/src/hb-ft.cc @@ -1104,6 +1104,45 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data buffer, hb_free); } +static unsigned +_hb_ft_get_table_tags (const hb_face_t *face HB_UNUSED, + unsigned int start_offset, + unsigned int *table_count, + hb_tag_t *table_tags, + void *user_data) +{ + FT_Face ft_face = (FT_Face) user_data; + + FT_ULong population = 0; + FT_Sfnt_Table_Info (ft_face, + 0, // table_index; ignored + nullptr, + &population); + + if (!table_count) + return population; + else + *table_count = 0; + + if (unlikely (start_offset >= population)) + return population; + + unsigned end_offset = hb_min (start_offset + *table_count, (unsigned) population); + if (unlikely (end_offset < start_offset)) + return population; + + *table_count = end_offset - start_offset; + for (unsigned i = start_offset; i < end_offset; i++) + { + FT_ULong tag = 0, length; + FT_Sfnt_Table_Info (ft_face, i, &tag, &length); + table_tags[i - start_offset] = tag; + } + + return population; +} + + /** * hb_ft_face_create: * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon @@ -1145,6 +1184,7 @@ hb_ft_face_create (FT_Face ft_face, hb_blob_destroy (blob); } else { face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy); + hb_face_set_get_table_tags_func (face, _hb_ft_get_table_tags, ft_face, nullptr); } hb_face_set_index (face, ft_face->face_index); diff --git a/thirdparty/harfbuzz/src/hb-geometry.hh b/thirdparty/harfbuzz/src/hb-geometry.hh new file mode 100644 index 0000000000..7777ff9ac3 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-geometry.hh @@ -0,0 +1,284 @@ +/* + * Copyright © 2022 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_GEOMETRY_HH +#define HB_GEOMETRY_HH + +#include "hb.hh" + + +struct hb_extents_t +{ + hb_extents_t () {} + hb_extents_t (float xmin, float ymin, float xmax, float ymax) : + xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {} + + bool is_empty () const { return xmin >= xmax || ymin >= ymax; } + bool is_void () const { return xmin > xmax; } + + void union_ (const hb_extents_t &o) + { + xmin = hb_min (xmin, o.xmin); + ymin = hb_min (ymin, o.ymin); + xmax = hb_max (xmax, o.xmax); + ymax = hb_max (ymax, o.ymax); + } + + void intersect (const hb_extents_t &o) + { + xmin = hb_max (xmin, o.xmin); + ymin = hb_max (ymin, o.ymin); + xmax = hb_min (xmax, o.xmax); + ymax = hb_min (ymax, o.ymax); + } + + void + add_point (float x, float y) + { + if (unlikely (is_void ())) + { + xmin = xmax = x; + ymin = ymax = y; + } + else + { + xmin = hb_min (xmin, x); + ymin = hb_min (ymin, y); + xmax = hb_max (xmax, x); + ymax = hb_max (ymax, y); + } + } + + float xmin = 0.f; + float ymin = 0.f; + float xmax = -1.f; + float ymax = -1.f; +}; + +struct hb_transform_t +{ + hb_transform_t () {} + hb_transform_t (float xx, float yx, + float xy, float yy, + float x0, float y0) : + xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {} + + void multiply (const hb_transform_t &o) + { + /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */ + hb_transform_t r; + + r.xx = o.xx * xx + o.yx * xy; + r.yx = o.xx * yx + o.yx * yy; + + r.xy = o.xy * xx + o.yy * xy; + r.yy = o.xy * yx + o.yy * yy; + + r.x0 = o.x0 * xx + o.y0 * xy + x0; + r.y0 = o.x0 * yx + o.y0 * yy + y0; + + *this = r; + } + + void transform_distance (float &dx, float &dy) const + { + float new_x = xx * dx + xy * dy; + float new_y = yx * dx + yy * dy; + dx = new_x; + dy = new_y; + } + + void transform_point (float &x, float &y) const + { + transform_distance (x, y); + x += x0; + y += y0; + } + + void transform_extents (hb_extents_t &extents) const + { + float quad_x[4], quad_y[4]; + + quad_x[0] = extents.xmin; + quad_y[0] = extents.ymin; + quad_x[1] = extents.xmin; + quad_y[1] = extents.ymax; + quad_x[2] = extents.xmax; + quad_y[2] = extents.ymin; + quad_x[3] = extents.xmax; + quad_y[3] = extents.ymax; + + extents = hb_extents_t {}; + for (unsigned i = 0; i < 4; i++) + { + transform_point (quad_x[i], quad_y[i]); + extents.add_point (quad_x[i], quad_y[i]); + } + } + + void transform (const hb_transform_t &o) { multiply (o); } + + void translate (float x, float y) + { + if (x == 0.f && y == 0.f) + return; + + x0 += xx * x + xy * y; + y0 += yx * x + yy * y; + } + + void scale (float scaleX, float scaleY) + { + if (scaleX == 1.f && scaleY == 1.f) + return; + + xx *= scaleX; + yx *= scaleX; + xy *= scaleY; + yy *= scaleY; + } + + void rotate (float rotation) + { + if (rotation == 0.f) + return; + + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240 + rotation = rotation * HB_PI; + float c; + float s; +#ifdef HAVE_SINCOSF + sincosf (rotation, &s, &c); +#else + c = cosf (rotation); + s = sinf (rotation); +#endif + auto other = hb_transform_t{c, s, -s, c, 0.f, 0.f}; + transform (other); + } + + void skew (float skewX, float skewY) + { + if (skewX == 0.f && skewY == 0.f) + return; + + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255 + skewX = skewX * HB_PI; + skewY = skewY * HB_PI; + auto other = hb_transform_t{1.f, + skewY ? tanf (skewY) : 0.f, + skewX ? tanf (skewX) : 0.f, + 1.f, + 0.f, 0.f}; + transform (other); + } + + float xx = 1.f; + float yx = 0.f; + float xy = 0.f; + float yy = 1.f; + float x0 = 0.f; + float y0 = 0.f; +}; + +struct hb_bounds_t +{ + enum status_t { + UNBOUNDED, + BOUNDED, + EMPTY, + }; + + hb_bounds_t (status_t status) : status (status) {} + hb_bounds_t (const hb_extents_t &extents) : + status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {} + + void union_ (const hb_bounds_t &o) + { + if (o.status == UNBOUNDED) + status = UNBOUNDED; + else if (o.status == BOUNDED) + { + if (status == EMPTY) + *this = o; + else if (status == BOUNDED) + extents.union_ (o.extents); + } + } + + void intersect (const hb_bounds_t &o) + { + if (o.status == EMPTY) + status = EMPTY; + else if (o.status == BOUNDED) + { + if (status == UNBOUNDED) + *this = o; + else if (status == BOUNDED) + { + extents.intersect (o.extents); + if (extents.is_empty ()) + status = EMPTY; + } + } + } + + status_t status; + hb_extents_t extents; +}; + +struct hb_transform_decomposed_t +{ + float translateX = 0; + float translateY = 0; + float rotation = 0; // in degrees, counter-clockwise + float scaleX = 1; + float scaleY = 1; + float skewX = 0; // in degrees, counter-clockwise + float skewY = 0; // in degrees, counter-clockwise + float tCenterX = 0; + float tCenterY = 0; + + operator bool () const + { + return translateX || translateY || + rotation || + scaleX != 1 || scaleY != 1 || + skewX || skewY || + tCenterX || tCenterY; + } + + hb_transform_t to_transform () const + { + hb_transform_t t; + t.translate (translateX + tCenterX, translateY + tCenterY); + t.rotate (rotation); + t.scale (scaleX, scaleY); + t.skew (-skewX, skewY); + t.translate (-tCenterX, -tCenterY); + return t; + } +}; + + +#endif /* HB_GEOMETRY_HH */ diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh index 61e05180be..04d09940ae 100644 --- a/thirdparty/harfbuzz/src/hb-iter.hh +++ b/thirdparty/harfbuzz/src/hb-iter.hh @@ -324,6 +324,16 @@ struct hb_is_sink_of (hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator) +struct +{ + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); } + + unsigned operator () (unsigned _) const { return _; } +} +HB_FUNCOBJ (hb_len_of); + /* Range-based 'for' for iterables. */ template <typename Iterable, diff --git a/thirdparty/harfbuzz/src/hb-limits.hh b/thirdparty/harfbuzz/src/hb-limits.hh index 7efc893eae..2cb14a4cc8 100644 --- a/thirdparty/harfbuzz/src/hb-limits.hh +++ b/thirdparty/harfbuzz/src/hb-limits.hh @@ -88,25 +88,24 @@ #define HB_MAX_LOOKUP_VISIT_COUNT 35000 #endif - -#ifndef HB_GLYF_VAR_COMPOSITE_MAX_AXES -#define HB_GLYF_VAR_COMPOSITE_MAX_AXES 4096 +#ifndef HB_MAX_GRAPH_EDGE_COUNT +#define HB_MAX_GRAPH_EDGE_COUNT 2048 #endif -#ifndef HB_GLYF_MAX_POINTS -#define HB_GLYF_MAX_POINTS 20000 +#ifndef HB_VAR_COMPOSITE_MAX_AXES +#define HB_VAR_COMPOSITE_MAX_AXES 4096 #endif -#ifndef HB_GLYF_MAX_EDGE_COUNT -#define HB_GLYF_MAX_EDGE_COUNT 1024 +#ifndef HB_GLYF_MAX_POINTS +#define HB_GLYF_MAX_POINTS 200000 #endif #ifndef HB_CFF_MAX_OPS #define HB_CFF_MAX_OPS 10000 #endif -#ifndef HB_COLRV1_MAX_EDGE_COUNT -#define HB_COLRV1_MAX_EDGE_COUNT 2048 +#ifndef HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH +#define HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH 64 #endif diff --git a/thirdparty/harfbuzz/src/hb-open-file.hh b/thirdparty/harfbuzz/src/hb-open-file.hh index 1157ea46d0..6c98226f21 100644 --- a/thirdparty/harfbuzz/src/hb-open-file.hh +++ b/thirdparty/harfbuzz/src/hb-open-file.hh @@ -250,7 +250,7 @@ struct TTCHeader { switch (u.header.version.major) { case 2: /* version 2 is compatible with version 1 */ - case 1: return u.version1.get_face_count (); + case 1: hb_barrier (); return u.version1.get_face_count (); default:return 0; } } @@ -258,7 +258,7 @@ struct TTCHeader { switch (u.header.version.major) { case 2: /* version 2 is compatible with version 1 */ - case 1: return u.version1.get_face (i); + case 1: hb_barrier (); return u.version1.get_face (i); default:return Null (OpenTypeFontFace); } } @@ -270,7 +270,7 @@ struct TTCHeader hb_barrier (); switch (u.header.version.major) { case 2: /* version 2 is compatible with version 1 */ - case 1: return_trace (u.version1.sanitize (c)); + case 1: hb_barrier (); return_trace (u.version1.sanitize (c)); default:return_trace (true); } } diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh index 9c11f14344..6655259b7a 100644 --- a/thirdparty/harfbuzz/src/hb-open-type.hh +++ b/thirdparty/harfbuzz/src/hb-open-type.hh @@ -132,6 +132,89 @@ struct HBUINT15 : HBUINT16 DEFINE_SIZE_STATIC (2); }; +/* 32-bit unsigned integer with variable encoding. */ +struct HBUINT32VAR +{ + unsigned get_size () const + { + unsigned b0 = v[0]; + if (b0 < 0x80) + return 1; + else if (b0 < 0xC0) + return 2; + else if (b0 < 0xE0) + return 3; + else if (b0 < 0xF0) + return 4; + else + return 5; + } + + static unsigned get_size (uint32_t v) + { + if (v < 0x80) + return 1; + else if (v < 0x4000) + return 2; + else if (v < 0x200000) + return 3; + else if (v < 0x10000000) + return 4; + else + return 5; + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_range (v, 1) && + hb_barrier () && + c->check_range (v, get_size ())); + } + + operator uint32_t () const + { + unsigned b0 = v[0]; + if (b0 < 0x80) + return b0; + else if (b0 < 0xC0) + return ((b0 & 0x3F) << 8) | v[1]; + else if (b0 < 0xE0) + return ((b0 & 0x1F) << 16) | (v[1] << 8) | v[2]; + else if (b0 < 0xF0) + return ((b0 & 0x0F) << 24) | (v[1] << 16) | (v[2] << 8) | v[3]; + else + return (v[1] << 24) | (v[2] << 16) | (v[3] << 8) | v[4]; + } + + static bool serialize (hb_serialize_context_t *c, uint32_t v) + { + unsigned len = get_size (v); + + unsigned char *buf = c->allocate_size<unsigned char> (len, false); + if (unlikely (!buf)) + return false; + + unsigned char *p = buf + len; + for (unsigned i = 0; i < len; i++) + { + *--p = v & 0xFF; + v >>= 8; + } + + if (len > 1) + buf[0] |= ((1 << (len - 1)) - 1) << (9 - len); + + return true; + } + + protected: + unsigned char v[5]; + + public: + DEFINE_SIZE_MIN (1); +}; + /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */ typedef HBINT16 FWORD; @@ -149,6 +232,7 @@ struct HBFixed : Type operator signed () const = delete; operator unsigned () const = delete; + explicit operator float () const { return to_float (); } typename Type::type to_int () const { return Type::v; } void set_int (typename Type::type i ) { Type::v = i; } float to_float (float offset = 0) const { return ((int32_t) Type::v + offset) / shift; } @@ -570,7 +654,7 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, Base unsigned int i = (unsigned int) i_; const OffsetTo<Type, OffsetType, BaseType, has_null> *p = &this->arrayZ[i]; if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Null (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); + hb_barrier (); return this+*p; } Type& operator [] (int i_) @@ -578,7 +662,7 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, Base unsigned int i = (unsigned int) i_; const OffsetTo<Type, OffsetType, BaseType, has_null> *p = &this->arrayZ[i]; if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Crap (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); + hb_barrier (); return this+*p; } @@ -629,14 +713,14 @@ struct ArrayOf { unsigned int i = (unsigned int) i_; if (unlikely (i >= len)) return Null (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return arrayZ[i]; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= len)) return Crap (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return arrayZ[i]; } @@ -756,6 +840,7 @@ template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>; using PString = ArrayOf<HBUINT8, HBUINT8>; /* Array of Offset's */ +template <typename Type> using Array8OfOffset24To = ArrayOf<OffsetTo<Type, HBUINT24>, HBUINT8>; template <typename Type> using Array16OfOffset16To = ArrayOf<OffsetTo<Type, HBUINT16>, HBUINT16>; template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT16>; template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>; @@ -768,14 +853,14 @@ struct List16OfOffsetTo : ArrayOf<OffsetTo<Type, OffsetType>, HBUINT16> { unsigned int i = (unsigned int) i_; if (unlikely (i >= this->len)) return Null (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return this+this->arrayZ[i]; } const Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= this->len)) return Crap (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return this+this->arrayZ[i]; } @@ -813,14 +898,14 @@ struct HeadlessArrayOf { unsigned int i = (unsigned int) i_; if (unlikely (i >= lenP1 || !i)) return Null (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return arrayZ[i-1]; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= lenP1 || !i)) return Crap (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return arrayZ[i-1]; } unsigned int get_size () const @@ -907,14 +992,14 @@ struct ArrayOfM1 { unsigned int i = (unsigned int) i_; if (unlikely (i > lenM1)) return Null (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return arrayZ[i]; } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i > lenM1)) return Crap (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return arrayZ[i]; } unsigned int get_size () const @@ -1099,14 +1184,14 @@ struct VarSizedBinSearchArrayOf { unsigned int i = (unsigned int) i_; if (unlikely (i >= get_length ())) return Null (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return StructAtOffset<Type> (&bytesZ, i * header.unitSize); } Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= get_length ())) return Crap (Type); - _hb_compiler_memory_r_barrier (); + hb_barrier (); return StructAtOffset<Type> (&bytesZ, i * header.unitSize); } unsigned int get_length () const @@ -1163,6 +1248,638 @@ struct VarSizedBinSearchArrayOf }; +/* CFF INDEX */ + +template <typename COUNT> +struct CFFIndex +{ + unsigned int offset_array_size () const + { return offSize * (count + 1); } + + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + bool serialize (hb_serialize_context_t *c, + const Iterable &iterable, + const unsigned *p_data_size = nullptr, + unsigned min_off_size = 0) + { + TRACE_SERIALIZE (this); + unsigned data_size; + if (p_data_size) + data_size = *p_data_size; + else + total_size (iterable, &data_size); + + auto it = hb_iter (iterable); + if (unlikely (!serialize_header (c, +it, data_size, min_off_size))) return_trace (false); + unsigned char *ret = c->allocate_size<unsigned char> (data_size, false); + if (unlikely (!ret)) return_trace (false); + for (const auto &_ : +it) + { + unsigned len = _.length; + if (!len) + continue; + if (len <= 1) + { + *ret++ = *_.arrayZ; + continue; + } + hb_memcpy (ret, _.arrayZ, len); + ret += len; + } + return_trace (true); + } + + template <typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool serialize_header (hb_serialize_context_t *c, + Iterator it, + unsigned data_size, + unsigned min_off_size = 0) + { + TRACE_SERIALIZE (this); + + unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8; + off_size = hb_max(min_off_size, off_size); + + /* serialize CFFIndex header */ + if (unlikely (!c->extend_min (this))) return_trace (false); + this->count = hb_len (it); + if (!this->count) return_trace (true); + if (unlikely (!c->extend (this->offSize))) return_trace (false); + this->offSize = off_size; + if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false))) + return_trace (false); + + /* serialize indices */ + unsigned int offset = 1; + if (HB_OPTIMIZE_SIZE_VAL) + { + unsigned int i = 0; + for (const auto &_ : +it) + { + set_offset_at (i++, offset); + offset += hb_len_of (_); + } + set_offset_at (i, offset); + } + else + switch (off_size) + { + case 1: + { + HBUINT8 *p = (HBUINT8 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += hb_len_of (_); + } + *p = offset; + } + break; + case 2: + { + HBUINT16 *p = (HBUINT16 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += hb_len_of (_); + } + *p = offset; + } + break; + case 3: + { + HBUINT24 *p = (HBUINT24 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += hb_len_of (_); + } + *p = offset; + } + break; + case 4: + { + HBUINT32 *p = (HBUINT32 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += hb_len_of (_); + } + *p = offset; + } + break; + default: + break; + } + + assert (offset == data_size + 1); + return_trace (true); + } + + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr, unsigned min_off_size = 0) + { + auto it = + hb_iter (iterable); + if (!it) + { + if (data_size) *data_size = 0; + return min_size; + } + + unsigned total = 0; + for (const auto &_ : +it) + total += hb_len_of (_); + + if (data_size) *data_size = total; + + unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; + off_size = hb_max(min_off_size, off_size); + + return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total; + } + + void set_offset_at (unsigned int index, unsigned int offset) + { + assert (index <= count); + + unsigned int size = offSize; + const HBUINT8 *p = offsets; + switch (size) + { + case 1: ((HBUINT8 *) p)[index] = offset; break; + case 2: ((HBUINT16 *) p)[index] = offset; break; + case 3: ((HBUINT24 *) p)[index] = offset; break; + case 4: ((HBUINT32 *) p)[index] = offset; break; + default: return; + } + } + + private: + unsigned int offset_at (unsigned int index) const + { + assert (index <= count); + + unsigned int size = offSize; + const HBUINT8 *p = offsets; + switch (size) + { + case 1: return ((HBUINT8 *) p)[index]; + case 2: return ((HBUINT16 *) p)[index]; + case 3: return ((HBUINT24 *) p)[index]; + case 4: return ((HBUINT32 *) p)[index]; + default: return 0; + } + } + + const unsigned char *data_base () const + { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); } + public: + + hb_ubytes_t operator [] (unsigned int index) const + { + if (unlikely (index >= count)) return hb_ubytes_t (); + hb_barrier (); + unsigned offset0 = offset_at (index); + unsigned offset1 = offset_at (index + 1); + if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) + return hb_ubytes_t (); + return hb_ubytes_t (data_base () + offset0, offset1 - offset0); + } + + unsigned int get_size () const + { + if (count) + return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1); + return min_size; /* empty CFFIndex contains count only */ + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + hb_barrier () && + (count == 0 || /* empty INDEX */ + (count < count + 1u && + c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 && + c->check_array (offsets, offSize, count + 1u) && + c->check_range (data_base (), offset_at (count)))))); + } + + public: + COUNT count; /* Number of object data. Note there are (count+1) offsets */ + private: + HBUINT8 offSize; /* The byte size of each offset in the offsets array. */ + HBUINT8 offsets[HB_VAR_ARRAY]; + /* The array of (count + 1) offsets into objects array (1-base). */ + /* HBUINT8 data[HB_VAR_ARRAY]; Object data */ + public: + DEFINE_SIZE_MIN (COUNT::static_size); +}; +typedef CFFIndex<HBUINT16> CFF1Index; +typedef CFFIndex<HBUINT32> CFF2Index; + + +/* TupleValues */ +struct TupleValues +{ + enum packed_value_flag_t + { + VALUES_ARE_ZEROS = 0x80, + VALUES_ARE_BYTES = 0x00, + VALUES_ARE_WORDS = 0x40, + VALUES_ARE_LONGS = 0xC0, + VALUES_SIZE_MASK = 0xC0, + VALUE_RUN_COUNT_MASK = 0x3F + }; + + static unsigned compile (hb_array_t<const int> values, /* IN */ + hb_array_t<unsigned char> encoded_bytes /* OUT */) + { + unsigned num_values = values.length; + unsigned encoded_len = 0; + unsigned i = 0; + while (i < num_values) + { + int val = values.arrayZ[i]; + if (val == 0) + encoded_len += encode_value_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), values); + else if (val >= -128 && val <= 127) + encoded_len += encode_value_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), values); + else if (val >= -32768 && val <= 32767) + encoded_len += encode_value_run_as_words (i, encoded_bytes.sub_array (encoded_len), values); + else + encoded_len += encode_value_run_as_longs (i, encoded_bytes.sub_array (encoded_len), values); + } + return encoded_len; + } + + static unsigned encode_value_run_as_zeroes (unsigned& i, + hb_array_t<unsigned char> encoded_bytes, + hb_array_t<const int> values) + { + unsigned num_values = values.length; + unsigned run_length = 0; + auto it = encoded_bytes.iter (); + unsigned encoded_len = 0; + while (i < num_values && values.arrayZ[i] == 0) + { + i++; + run_length++; + } + + while (run_length >= 64) + { + *it++ = char (VALUES_ARE_ZEROS | 63); + run_length -= 64; + encoded_len++; + } + + if (run_length) + { + *it++ = char (VALUES_ARE_ZEROS | (run_length - 1)); + encoded_len++; + } + return encoded_len; + } + + static unsigned encode_value_run_as_bytes (unsigned &i, + hb_array_t<unsigned char> encoded_bytes, + hb_array_t<const int> values) + { + unsigned start = i; + unsigned num_values = values.length; + while (i < num_values) + { + int val = values.arrayZ[i]; + if (val > 127 || val < -128) + break; + + /* from fonttools: if there're 2 or more zeros in a sequence, + * it is better to start a new run to save bytes. */ + if (val == 0 && i + 1 < num_values && values.arrayZ[i+1] == 0) + break; + + i++; + } + unsigned run_length = i - start; + + unsigned encoded_len = 0; + auto it = encoded_bytes.iter (); + + while (run_length >= 64) + { + *it++ = (VALUES_ARE_BYTES | 63); + encoded_len++; + + for (unsigned j = 0; j < 64; j++) + { + *it++ = static_cast<char> (values.arrayZ[start + j]); + encoded_len++; + } + + start += 64; + run_length -= 64; + } + + if (run_length) + { + *it++ = (VALUES_ARE_BYTES | (run_length - 1)); + encoded_len++; + + while (start < i) + { + *it++ = static_cast<char> (values.arrayZ[start++]); + encoded_len++; + } + } + + return encoded_len; + } + + static unsigned encode_value_run_as_words (unsigned &i, + hb_array_t<unsigned char> encoded_bytes, + hb_array_t<const int> values) + { + unsigned start = i; + unsigned num_values = values.length; + while (i < num_values) + { + int val = values.arrayZ[i]; + + /* start a new run for a single zero value*/ + if (val == 0) break; + + /* from fonttools: continue word-encoded run if there's only one + * single value in the range [-128, 127] because it is more compact. + * Only start a new run when there're 2 continuous such values. */ + if (val >= -128 && val <= 127 && + i + 1 < num_values && + values.arrayZ[i+1] >= -128 && values.arrayZ[i+1] <= 127) + break; + + i++; + } + + unsigned run_length = i - start; + auto it = encoded_bytes.iter (); + unsigned encoded_len = 0; + while (run_length >= 64) + { + *it++ = (VALUES_ARE_WORDS | 63); + encoded_len++; + + for (unsigned j = 0; j < 64; j++) + { + int16_t value_val = values.arrayZ[start + j]; + *it++ = static_cast<char> (value_val >> 8); + *it++ = static_cast<char> (value_val & 0xFF); + + encoded_len += 2; + } + + start += 64; + run_length -= 64; + } + + if (run_length) + { + *it++ = (VALUES_ARE_WORDS | (run_length - 1)); + encoded_len++; + while (start < i) + { + int16_t value_val = values.arrayZ[start++]; + *it++ = static_cast<char> (value_val >> 8); + *it++ = static_cast<char> (value_val & 0xFF); + + encoded_len += 2; + } + } + return encoded_len; + } + + static unsigned encode_value_run_as_longs (unsigned &i, + hb_array_t<unsigned char> encoded_bytes, + hb_array_t<const int> values) + { + unsigned start = i; + unsigned num_values = values.length; + while (i < num_values) + { + int val = values.arrayZ[i]; + + if (val >= -32768 && val <= 32767) + break; + + i++; + } + + unsigned run_length = i - start; + auto it = encoded_bytes.iter (); + unsigned encoded_len = 0; + while (run_length >= 64) + { + *it++ = (VALUES_ARE_LONGS | 63); + encoded_len++; + + for (unsigned j = 0; j < 64; j++) + { + int32_t value_val = values.arrayZ[start + j]; + *it++ = static_cast<char> (value_val >> 24); + *it++ = static_cast<char> (value_val >> 16); + *it++ = static_cast<char> (value_val >> 8); + *it++ = static_cast<char> (value_val & 0xFF); + + encoded_len += 4; + } + + start += 64; + run_length -= 64; + } + + if (run_length) + { + *it++ = (VALUES_ARE_LONGS | (run_length - 1)); + encoded_len++; + while (start < i) + { + int32_t value_val = values.arrayZ[start++]; + *it++ = static_cast<char> (value_val >> 24); + *it++ = static_cast<char> (value_val >> 16); + *it++ = static_cast<char> (value_val >> 8); + *it++ = static_cast<char> (value_val & 0xFF); + + encoded_len += 4; + } + } + return encoded_len; + } + + template <typename T> + static bool decompile (const HBUINT8 *&p /* IN/OUT */, + hb_vector_t<T> &values /* IN/OUT */, + const HBUINT8 *end, + bool consume_all = false) + { + unsigned i = 0; + unsigned count = consume_all ? UINT_MAX : values.length; + if (consume_all) + values.alloc ((end - p) / 2); + while (i < count) + { + if (unlikely (p + 1 > end)) return consume_all; + unsigned control = *p++; + unsigned run_count = (control & VALUE_RUN_COUNT_MASK) + 1; + if (consume_all) + { + if (unlikely (!values.resize (values.length + run_count, false))) + return false; + } + unsigned stop = i + run_count; + if (unlikely (stop > count)) return false; + if ((control & VALUES_SIZE_MASK) == VALUES_ARE_ZEROS) + { + for (; i < stop; i++) + values.arrayZ[i] = 0; + } + else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_WORDS) + { + if (unlikely (p + run_count * HBINT16::static_size > end)) return false; + for (; i < stop; i++) + { + values.arrayZ[i] = * (const HBINT16 *) p; + p += HBINT16::static_size; + } + } + else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_LONGS) + { + if (unlikely (p + run_count * HBINT32::static_size > end)) return false; + for (; i < stop; i++) + { + values.arrayZ[i] = * (const HBINT32 *) p; + p += HBINT32::static_size; + } + } + else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_BYTES) + { + if (unlikely (p + run_count > end)) return false; + for (; i < stop; i++) + { + values.arrayZ[i] = * (const HBINT8 *) p++; + } + } + } + return true; + } + + struct iter_t : hb_iter_with_fallback_t<iter_t, int> + { + iter_t (const unsigned char *p_, unsigned len_) + : p (p_), end (p_ + len_) + { if (ensure_run ()) read_value (); } + + private: + const unsigned char *p; + const unsigned char * const end; + int current_value = 0; + signed run_count = 0; + unsigned width = 0; + + bool ensure_run () + { + if (likely (run_count > 0)) return true; + + if (unlikely (p >= end)) + { + run_count = 0; + current_value = 0; + return false; + } + + unsigned control = *p++; + run_count = (control & VALUE_RUN_COUNT_MASK) + 1; + width = control & VALUES_SIZE_MASK; + switch (width) + { + case VALUES_ARE_ZEROS: width = 0; break; + case VALUES_ARE_BYTES: width = HBINT8::static_size; break; + case VALUES_ARE_WORDS: width = HBINT16::static_size; break; + case VALUES_ARE_LONGS: width = HBINT32::static_size; break; + default: assert (false); + } + + if (unlikely (p + run_count * width > end)) + { + run_count = 0; + current_value = 0; + return false; + } + + return true; + } + void read_value () + { + switch (width) + { + case 0: current_value = 0; break; + case 1: current_value = * (const HBINT8 *) p; break; + case 2: current_value = * (const HBINT16 *) p; break; + case 4: current_value = * (const HBINT32 *) p; break; + } + p += width; + } + + public: + + typedef int __item_t__; + __item_t__ __item__ () const + { return current_value; } + + bool __more__ () const { return run_count || p < end; } + void __next__ () + { + run_count--; + if (unlikely (!ensure_run ())) + return; + read_value (); + } + void __forward__ (unsigned n) + { + if (unlikely (!ensure_run ())) + return; + while (n) + { + unsigned i = hb_min (n, (unsigned) run_count); + run_count -= i; + n -= i; + p += (i - 1) * width; + if (unlikely (!ensure_run ())) + return; + read_value (); + } + } + bool operator != (const iter_t& o) const + { return p != o.p || run_count != o.run_count; } + iter_t __end__ () const + { + iter_t it (end, 0); + return it; + } + }; +}; + +struct TupleList : CFF2Index +{ + TupleValues::iter_t operator [] (unsigned i) const + { + auto bytes = CFF2Index::operator [] (i); + return TupleValues::iter_t (bytes.arrayZ, bytes.length); + } +}; + + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh index c7c3264c08..b49c0be517 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh @@ -68,247 +68,6 @@ using str_buff_t = hb_vector_t<unsigned char>; using str_buff_vec_t = hb_vector_t<str_buff_t>; using glyph_to_sid_map_t = hb_vector_t<code_pair_t>; -struct length_f_t -{ - template <typename Iterable, - hb_requires (hb_is_iterable (Iterable))> - unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); } - - unsigned operator () (unsigned _) const { return _; } -} -HB_FUNCOBJ (length_f); - -/* CFF INDEX */ -template <typename COUNT> -struct CFFIndex -{ - unsigned int offset_array_size () const - { return offSize * (count + 1); } - - template <typename Iterable, - hb_requires (hb_is_iterable (Iterable))> - bool serialize (hb_serialize_context_t *c, - const Iterable &iterable, - const unsigned *p_data_size = nullptr, - unsigned min_off_size = 0) - { - TRACE_SERIALIZE (this); - unsigned data_size; - if (p_data_size) - data_size = *p_data_size; - else - total_size (iterable, &data_size); - - auto it = hb_iter (iterable); - if (unlikely (!serialize_header (c, +it, data_size, min_off_size))) return_trace (false); - unsigned char *ret = c->allocate_size<unsigned char> (data_size, false); - if (unlikely (!ret)) return_trace (false); - for (const auto &_ : +it) - { - unsigned len = _.length; - if (!len) - continue; - if (len <= 1) - { - *ret++ = *_.arrayZ; - continue; - } - hb_memcpy (ret, _.arrayZ, len); - ret += len; - } - return_trace (true); - } - - template <typename Iterator, - hb_requires (hb_is_iterator (Iterator))> - bool serialize_header (hb_serialize_context_t *c, - Iterator it, - unsigned data_size, - unsigned min_off_size = 0) - { - TRACE_SERIALIZE (this); - - unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8; - off_size = hb_max(min_off_size, off_size); - - /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = hb_len (it); - if (!this->count) return_trace (true); - if (unlikely (!c->extend (this->offSize))) return_trace (false); - this->offSize = off_size; - if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false))) - return_trace (false); - - /* serialize indices */ - unsigned int offset = 1; - if (HB_OPTIMIZE_SIZE_VAL) - { - unsigned int i = 0; - for (const auto &_ : +it) - { - set_offset_at (i++, offset); - offset += length_f (_); - } - set_offset_at (i, offset); - } - else - switch (off_size) - { - case 1: - { - HBUINT8 *p = (HBUINT8 *) offsets; - for (const auto &_ : +it) - { - *p++ = offset; - offset += length_f (_); - } - *p = offset; - } - break; - case 2: - { - HBUINT16 *p = (HBUINT16 *) offsets; - for (const auto &_ : +it) - { - *p++ = offset; - offset += length_f (_); - } - *p = offset; - } - break; - case 3: - { - HBUINT24 *p = (HBUINT24 *) offsets; - for (const auto &_ : +it) - { - *p++ = offset; - offset += length_f (_); - } - *p = offset; - } - break; - case 4: - { - HBUINT32 *p = (HBUINT32 *) offsets; - for (const auto &_ : +it) - { - *p++ = offset; - offset += length_f (_); - } - *p = offset; - } - break; - default: - break; - } - - assert (offset == data_size + 1); - return_trace (true); - } - - template <typename Iterable, - hb_requires (hb_is_iterable (Iterable))> - static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr, unsigned min_off_size = 0) - { - auto it = + hb_iter (iterable); - if (!it) - { - if (data_size) *data_size = 0; - return min_size; - } - - unsigned total = 0; - for (const auto &_ : +it) - total += length_f (_); - - if (data_size) *data_size = total; - - unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; - off_size = hb_max(min_off_size, off_size); - - return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total; - } - - void set_offset_at (unsigned int index, unsigned int offset) - { - assert (index <= count); - - unsigned int size = offSize; - const HBUINT8 *p = offsets; - switch (size) - { - case 1: ((HBUINT8 *) p)[index] = offset; break; - case 2: ((HBUINT16 *) p)[index] = offset; break; - case 3: ((HBUINT24 *) p)[index] = offset; break; - case 4: ((HBUINT32 *) p)[index] = offset; break; - default: return; - } - } - - private: - unsigned int offset_at (unsigned int index) const - { - assert (index <= count); - - unsigned int size = offSize; - const HBUINT8 *p = offsets; - switch (size) - { - case 1: return ((HBUINT8 *) p)[index]; - case 2: return ((HBUINT16 *) p)[index]; - case 3: return ((HBUINT24 *) p)[index]; - case 4: return ((HBUINT32 *) p)[index]; - default: return 0; - } - } - - const unsigned char *data_base () const - { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); } - public: - - hb_ubytes_t operator [] (unsigned int index) const - { - if (unlikely (index >= count)) return hb_ubytes_t (); - _hb_compiler_memory_r_barrier (); - unsigned offset0 = offset_at (index); - unsigned offset1 = offset_at (index + 1); - if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) - return hb_ubytes_t (); - return hb_ubytes_t (data_base () + offset0, offset1 - offset0); - } - - unsigned int get_size () const - { - if (count) - return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1); - return min_size; /* empty CFFIndex contains count only */ - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - hb_barrier () && - (count == 0 || /* empty INDEX */ - (count < count + 1u && - hb_barrier () && - c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 && - c->check_array (offsets, offSize, count + 1u) && - c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count)))))); - } - - public: - COUNT count; /* Number of object data. Note there are (count+1) offsets */ - private: - HBUINT8 offSize; /* The byte size of each offset in the offsets array. */ - HBUINT8 offsets[HB_VAR_ARRAY]; - /* The array of (count + 1) offsets into objects array (1-base). */ - /* HBUINT8 data[HB_VAR_ARRAY]; Object data */ - public: - DEFINE_SIZE_MIN (COUNT::static_size); -}; - /* Top Dict, Font Dict, Private Dict */ struct Dict : UnsizedByteStr { @@ -549,8 +308,8 @@ struct FDSelect { switch (format) { - case 0: return format.static_size + u.format0.get_size (num_glyphs); - case 3: return format.static_size + u.format3.get_size (); + case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs); + case 3: hb_barrier (); return format.static_size + u.format3.get_size (); default:return 0; } } @@ -561,8 +320,8 @@ struct FDSelect switch (format) { - case 0: return u.format0.get_fd (glyph); - case 3: return u.format3.get_fd (glyph); + case 0: hb_barrier (); return u.format0.get_fd (glyph); + case 3: hb_barrier (); return u.format3.get_fd (glyph); default:return 0; } } @@ -573,8 +332,8 @@ struct FDSelect switch (format) { - case 0: return u.format0.get_fd_range (glyph); - case 3: return u.format3.get_fd_range (glyph); + case 0: hb_barrier (); return u.format0.get_fd_range (glyph); + case 3: hb_barrier (); return u.format3.get_fd_range (glyph); default:return {0, 1}; } } @@ -588,8 +347,8 @@ struct FDSelect switch (format) { - case 0: return_trace (u.format0.sanitize (c, fdcount)); - case 3: return_trace (u.format3.sanitize (c, fdcount)); + case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount)); + case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount)); default:return_trace (false); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh index 1bbd463841..b84d896e3e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh @@ -51,9 +51,6 @@ namespace CFF { enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; -typedef CFFIndex<HBUINT16> CFF1Index; - -typedef CFFIndex<HBUINT16> CFF1Index; typedef CFF1Index CFF1CharStrings; typedef Subrs<HBUINT16> CFF1Subrs; @@ -242,8 +239,8 @@ struct Encoding unsigned int size = min_size; switch (table_format ()) { - case 0: size += u.format0.get_size (); break; - case 1: size += u.format1.get_size (); break; + case 0: hb_barrier (); size += u.format0.get_size (); break; + case 1: hb_barrier (); size += u.format1.get_size (); break; } if (has_supplement ()) size += suppEncData ().get_size (); @@ -254,8 +251,8 @@ struct Encoding { switch (table_format ()) { - case 0: return u.format0.get_code (glyph); - case 1: return u.format1.get_code (glyph); + case 0: hb_barrier (); return u.format0.get_code (glyph); + case 1: hb_barrier (); return u.format1.get_code (glyph); default:return 0; } } @@ -279,8 +276,8 @@ struct Encoding switch (table_format ()) { - case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break; - case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break; + case 0: hb_barrier (); if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break; + case 1: hb_barrier (); if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break; default:return_trace (false); } return_trace (likely (!has_supplement () || suppEncData ().sanitize (c))); @@ -291,8 +288,8 @@ struct Encoding { switch (table_format ()) { - case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); - case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); + case 0: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); + case 1: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); default:return Null (CFF1SuppEncData); } } @@ -570,9 +567,9 @@ struct Charset { switch (format) { - case 0: return min_size + u.format0.get_size (num_glyphs); - case 1: return min_size + u.format1.get_size (num_glyphs); - case 2: return min_size + u.format2.get_size (num_glyphs); + case 0: hb_barrier (); return min_size + u.format0.get_size (num_glyphs); + case 1: hb_barrier (); return min_size + u.format1.get_size (num_glyphs); + case 2: hb_barrier (); return min_size + u.format2.get_size (num_glyphs); default:return 0; } } @@ -582,9 +579,9 @@ struct Charset { switch (format) { - case 0: return u.format0.get_sid (glyph, num_glyphs); - case 1: return u.format1.get_sid (glyph, num_glyphs, cache); - case 2: return u.format2.get_sid (glyph, num_glyphs, cache); + case 0: hb_barrier (); return u.format0.get_sid (glyph, num_glyphs); + case 1: hb_barrier (); return u.format1.get_sid (glyph, num_glyphs, cache); + case 2: hb_barrier (); return u.format2.get_sid (glyph, num_glyphs, cache); default:return 0; } } @@ -593,9 +590,9 @@ struct Charset { switch (format) { - case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return; - case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return; - case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return; + case 0: hb_barrier (); u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return; + case 1: hb_barrier (); u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return; + case 2: hb_barrier (); u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return; default:return; } } @@ -604,9 +601,9 @@ struct Charset { switch (format) { - case 0: return u.format0.get_glyph (sid, num_glyphs); - case 1: return u.format1.get_glyph (sid, num_glyphs); - case 2: return u.format2.get_glyph (sid, num_glyphs); + case 0: hb_barrier (); return u.format0.get_glyph (sid, num_glyphs); + case 1: hb_barrier (); return u.format1.get_glyph (sid, num_glyphs); + case 2: hb_barrier (); return u.format2.get_glyph (sid, num_glyphs); default:return 0; } } @@ -620,9 +617,9 @@ struct Charset switch (format) { - case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); - case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); - case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 0: hb_barrier (); return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 1: hb_barrier (); return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 2: hb_barrier (); return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); default:return_trace (false); } } @@ -1179,6 +1176,7 @@ struct cff1 if (unlikely (!font_interp.interpret (*font))) goto fail; PRIVDICTVAL *priv = &privateDicts[i]; const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); + if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; num_interp_env_t env2 (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2); priv->init (); @@ -1193,6 +1191,7 @@ struct cff1 PRIVDICTVAL *priv = &privateDicts[0]; const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); + if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; num_interp_env_t env (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env); priv->init (); diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc index 7955565551..e42217b4e8 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc @@ -203,6 +203,11 @@ struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_pa bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const { + return get_path_at (font, glyph, draw_session, hb_array (font->coords, font->num_coords)); +} + +bool OT::cff2::accelerator_t::get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords) const +{ #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ return true; @@ -212,7 +217,7 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h unsigned int fd = fdSelect->get_fd (glyph); const hb_ubytes_t str = (*charStrings)[glyph]; - cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords); + cff2_cs_interp_env_t<number_t> env (str, *this, fd, coords.arrayZ, coords.length); cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t> interp (env); cff2_path_param_t param (font, draw_session); if (unlikely (!interp.interpret (param))) return false; diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh index 4b3bdc9315..c52c0511c6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh @@ -40,8 +40,6 @@ namespace CFF { */ #define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2') -typedef CFFIndex<HBUINT32> CFF2Index; - typedef CFF2Index CFF2CharStrings; typedef Subrs<HBUINT32> CFF2Subrs; @@ -64,9 +62,9 @@ struct CFF2FDSelect { switch (format) { - case 0: return format.static_size + u.format0.get_size (num_glyphs); - case 3: return format.static_size + u.format3.get_size (); - case 4: return format.static_size + u.format4.get_size (); + case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs); + case 3: hb_barrier (); return format.static_size + u.format3.get_size (); + case 4: hb_barrier (); return format.static_size + u.format4.get_size (); default:return 0; } } @@ -78,9 +76,9 @@ struct CFF2FDSelect switch (format) { - case 0: return u.format0.get_fd (glyph); - case 3: return u.format3.get_fd (glyph); - case 4: return u.format4.get_fd (glyph); + case 0: hb_barrier (); return u.format0.get_fd (glyph); + case 3: hb_barrier (); return u.format3.get_fd (glyph); + case 4: hb_barrier (); return u.format4.get_fd (glyph); default:return 0; } } @@ -94,9 +92,9 @@ struct CFF2FDSelect switch (format) { - case 0: return_trace (u.format0.sanitize (c, fdcount)); - case 3: return_trace (u.format3.sanitize (c, fdcount)); - case 4: return_trace (u.format4.sanitize (c, fdcount)); + case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount)); + case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount)); + case 4: hb_barrier (); return_trace (u.format4.sanitize (c, fdcount)); default:return_trace (false); } } @@ -460,6 +458,7 @@ struct cff2 if (unlikely (!font_interp.interpret (*font))) goto fail; const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); + if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; cff2_priv_dict_interp_env_t env2 (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2); privateDicts[i].init (); @@ -521,6 +520,7 @@ struct cff2 hb_glyph_extents_t *extents) const; HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const; HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; + HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords) const; }; struct accelerator_subset_t : accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh index 64d2b13880..0f1edce0b0 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh @@ -43,27 +43,145 @@ namespace OT { static inline uint8_t unicode_to_macroman (hb_codepoint_t u) { - uint16_t mapping[] = { - 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, - 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, - 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, - 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, - 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, - 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, - 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, - 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, - 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, - 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, - 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, - 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, - 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, - 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, - 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, - 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7 + static const struct unicode_to_macroman_t + { + uint16_t unicode; + uint8_t macroman; + } + mapping[] = + { + { 0x00A0, 0xCA }, + { 0x00A1, 0xC1 }, + { 0x00A2, 0xA2 }, + { 0x00A3, 0xA3 }, + { 0x00A5, 0xB4 }, + { 0x00A7, 0xA4 }, + { 0x00A8, 0xAC }, + { 0x00A9, 0xA9 }, + { 0x00AA, 0xBB }, + { 0x00AB, 0xC7 }, + { 0x00AC, 0xC2 }, + { 0x00AE, 0xA8 }, + { 0x00AF, 0xF8 }, + { 0x00B0, 0xA1 }, + { 0x00B1, 0xB1 }, + { 0x00B4, 0xAB }, + { 0x00B5, 0xB5 }, + { 0x00B6, 0xA6 }, + { 0x00B7, 0xE1 }, + { 0x00B8, 0xFC }, + { 0x00BA, 0xBC }, + { 0x00BB, 0xC8 }, + { 0x00BF, 0xC0 }, + { 0x00C0, 0xCB }, + { 0x00C1, 0xE7 }, + { 0x00C2, 0xE5 }, + { 0x00C3, 0xCC }, + { 0x00C4, 0x80 }, + { 0x00C5, 0x81 }, + { 0x00C6, 0xAE }, + { 0x00C7, 0x82 }, + { 0x00C8, 0xE9 }, + { 0x00C9, 0x83 }, + { 0x00CA, 0xE6 }, + { 0x00CB, 0xE8 }, + { 0x00CC, 0xED }, + { 0x00CD, 0xEA }, + { 0x00CE, 0xEB }, + { 0x00CF, 0xEC }, + { 0x00D1, 0x84 }, + { 0x00D2, 0xF1 }, + { 0x00D3, 0xEE }, + { 0x00D4, 0xEF }, + { 0x00D5, 0xCD }, + { 0x00D6, 0x85 }, + { 0x00D8, 0xAF }, + { 0x00D9, 0xF4 }, + { 0x00DA, 0xF2 }, + { 0x00DB, 0xF3 }, + { 0x00DC, 0x86 }, + { 0x00DF, 0xA7 }, + { 0x00E0, 0x88 }, + { 0x00E1, 0x87 }, + { 0x00E2, 0x89 }, + { 0x00E3, 0x8B }, + { 0x00E4, 0x8A }, + { 0x00E5, 0x8C }, + { 0x00E6, 0xBE }, + { 0x00E7, 0x8D }, + { 0x00E8, 0x8F }, + { 0x00E9, 0x8E }, + { 0x00EA, 0x90 }, + { 0x00EB, 0x91 }, + { 0x00EC, 0x93 }, + { 0x00ED, 0x92 }, + { 0x00EE, 0x94 }, + { 0x00EF, 0x95 }, + { 0x00F1, 0x96 }, + { 0x00F2, 0x98 }, + { 0x00F3, 0x97 }, + { 0x00F4, 0x99 }, + { 0x00F5, 0x9B }, + { 0x00F6, 0x9A }, + { 0x00F7, 0xD6 }, + { 0x00F8, 0xBF }, + { 0x00F9, 0x9D }, + { 0x00FA, 0x9C }, + { 0x00FB, 0x9E }, + { 0x00FC, 0x9F }, + { 0x00FF, 0xD8 }, + { 0x0131, 0xF5 }, + { 0x0152, 0xCE }, + { 0x0153, 0xCF }, + { 0x0178, 0xD9 }, + { 0x0192, 0xC4 }, + { 0x02C6, 0xF6 }, + { 0x02C7, 0xFF }, + { 0x02D8, 0xF9 }, + { 0x02D9, 0xFA }, + { 0x02DA, 0xFB }, + { 0x02DB, 0xFE }, + { 0x02DC, 0xF7 }, + { 0x02DD, 0xFD }, + { 0x03A9, 0xBD }, + { 0x03C0, 0xB9 }, + { 0x2013, 0xD0 }, + { 0x2014, 0xD1 }, + { 0x2018, 0xD4 }, + { 0x2019, 0xD5 }, + { 0x201A, 0xE2 }, + { 0x201C, 0xD2 }, + { 0x201D, 0xD3 }, + { 0x201E, 0xE3 }, + { 0x2020, 0xA0 }, + { 0x2021, 0xE0 }, + { 0x2022, 0xA5 }, + { 0x2026, 0xC9 }, + { 0x2030, 0xE4 }, + { 0x2039, 0xDC }, + { 0x203A, 0xDD }, + { 0x2044, 0xDA }, + { 0x20AC, 0xDB }, + { 0x2122, 0xAA }, + { 0x2202, 0xB6 }, + { 0x2206, 0xC6 }, + { 0x220F, 0xB8 }, + { 0x2211, 0xB7 }, + { 0x221A, 0xC3 }, + { 0x221E, 0xB0 }, + { 0x222B, 0xBA }, + { 0x2248, 0xC5 }, + { 0x2260, 0xAD }, + { 0x2264, 0xB2 }, + { 0x2265, 0xB3 }, + { 0x25CA, 0xD7 }, + { 0xF8FF, 0xF0 }, + { 0xFB01, 0xDE }, + { 0xFB02, 0xDF }, }; - uint16_t *c = hb_bsearch (u, mapping, ARRAY_LENGTH (mapping), sizeof (mapping[0]), - _hb_cmp_operator<uint16_t, uint16_t>); - return c ? (c - mapping) + 0x7F : 0; + auto *c = hb_bsearch (u, mapping, ARRAY_LENGTH (mapping), sizeof (mapping[0]), + _hb_cmp_operator<uint16_t, uint16_t>); + return c ? c->macroman : 0; } struct CmapSubtableFormat0 @@ -1379,12 +1497,12 @@ struct CmapSubtable hb_codepoint_t *glyph) const { switch (u.format) { - case 0: return u.format0 .get_glyph (codepoint, glyph); - case 4: return u.format4 .get_glyph (codepoint, glyph); - case 6: return u.format6 .get_glyph (codepoint, glyph); - case 10: return u.format10.get_glyph (codepoint, glyph); - case 12: return u.format12.get_glyph (codepoint, glyph); - case 13: return u.format13.get_glyph (codepoint, glyph); + case 0: hb_barrier (); return u.format0 .get_glyph (codepoint, glyph); + case 4: hb_barrier (); return u.format4 .get_glyph (codepoint, glyph); + case 6: hb_barrier (); return u.format6 .get_glyph (codepoint, glyph); + case 10: hb_barrier (); return u.format10.get_glyph (codepoint, glyph); + case 12: hb_barrier (); return u.format12.get_glyph (codepoint, glyph); + case 13: hb_barrier (); return u.format13.get_glyph (codepoint, glyph); case 14: default: return false; } @@ -1392,12 +1510,12 @@ struct CmapSubtable void collect_unicodes (hb_set_t *out, unsigned int num_glyphs = UINT_MAX) const { switch (u.format) { - case 0: u.format0 .collect_unicodes (out); return; - case 4: u.format4 .collect_unicodes (out); return; - case 6: u.format6 .collect_unicodes (out); return; - case 10: u.format10.collect_unicodes (out); return; - case 12: u.format12.collect_unicodes (out, num_glyphs); return; - case 13: u.format13.collect_unicodes (out, num_glyphs); return; + case 0: hb_barrier (); u.format0 .collect_unicodes (out); return; + case 4: hb_barrier (); u.format4 .collect_unicodes (out); return; + case 6: hb_barrier (); u.format6 .collect_unicodes (out); return; + case 10: hb_barrier (); u.format10.collect_unicodes (out); return; + case 12: hb_barrier (); u.format12.collect_unicodes (out, num_glyphs); return; + case 13: hb_barrier (); u.format13.collect_unicodes (out, num_glyphs); return; case 14: default: return; } @@ -1408,12 +1526,12 @@ struct CmapSubtable unsigned num_glyphs = UINT_MAX) const { switch (u.format) { - case 0: u.format0 .collect_mapping (unicodes, mapping); return; - case 4: u.format4 .collect_mapping (unicodes, mapping); return; - case 6: u.format6 .collect_mapping (unicodes, mapping); return; - case 10: u.format10.collect_mapping (unicodes, mapping); return; - case 12: u.format12.collect_mapping (unicodes, mapping, num_glyphs); return; - case 13: u.format13.collect_mapping (unicodes, mapping, num_glyphs); return; + case 0: hb_barrier (); u.format0 .collect_mapping (unicodes, mapping); return; + case 4: hb_barrier (); u.format4 .collect_mapping (unicodes, mapping); return; + case 6: hb_barrier (); u.format6 .collect_mapping (unicodes, mapping); return; + case 10: hb_barrier (); u.format10.collect_mapping (unicodes, mapping); return; + case 12: hb_barrier (); u.format12.collect_mapping (unicodes, mapping, num_glyphs); return; + case 13: hb_barrier (); u.format13.collect_mapping (unicodes, mapping, num_glyphs); return; case 14: default: return; } @@ -1422,12 +1540,12 @@ struct CmapSubtable unsigned get_language () const { switch (u.format) { - case 0: return u.format0 .get_language (); - case 4: return u.format4 .get_language (); - case 6: return u.format6 .get_language (); - case 10: return u.format10.get_language (); - case 12: return u.format12.get_language (); - case 13: return u.format13.get_language (); + case 0: hb_barrier (); return u.format0 .get_language (); + case 4: hb_barrier (); return u.format4 .get_language (); + case 6: hb_barrier (); return u.format6 .get_language (); + case 10: hb_barrier (); return u.format10.get_language (); + case 12: hb_barrier (); return u.format12.get_language (); + case 13: hb_barrier (); return u.format13.get_language (); case 14: default: return 0; } @@ -1442,9 +1560,9 @@ struct CmapSubtable const void *base) { switch (format) { - case 4: return u.format4.serialize (c, it); - case 12: return u.format12.serialize (c, it); - case 14: return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base); + case 4: hb_barrier (); return u.format4.serialize (c, it); + case 12: hb_barrier (); return u.format12.serialize (c, it); + case 14: hb_barrier (); return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base); default: return; } } @@ -1455,13 +1573,13 @@ struct CmapSubtable if (!u.format.sanitize (c)) return_trace (false); hb_barrier (); switch (u.format) { - case 0: return_trace (u.format0 .sanitize (c)); - case 4: return_trace (u.format4 .sanitize (c)); - case 6: return_trace (u.format6 .sanitize (c)); - case 10: return_trace (u.format10.sanitize (c)); - case 12: return_trace (u.format12.sanitize (c)); - case 13: return_trace (u.format13.sanitize (c)); - case 14: return_trace (u.format14.sanitize (c)); + case 0: hb_barrier (); return_trace (u.format0 .sanitize (c)); + case 4: hb_barrier (); return_trace (u.format4 .sanitize (c)); + case 6: hb_barrier (); return_trace (u.format6 .sanitize (c)); + case 10: hb_barrier (); return_trace (u.format10.sanitize (c)); + case 12: hb_barrier (); return_trace (u.format12.sanitize (c)); + case 13: hb_barrier (); return_trace (u.format13.sanitize (c)); + case 14: hb_barrier (); return_trace (u.format14.sanitize (c)); default:return_trace (true); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh index db1c55490c..dd4befffa1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh +++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh @@ -96,6 +96,9 @@ HB_OT_CORE_TABLE (OT, avar) HB_OT_CORE_TABLE (OT, cvar) HB_OT_ACCELERATOR (OT, gvar) HB_OT_CORE_TABLE (OT, MVAR) +#ifndef HB_NO_VAR_COMPOSITES +HB_OT_CORE_TABLE (OT, VARC) +#endif #endif /* Legacy kern. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc index 1da869d697..2495306d24 100644 --- a/thirdparty/harfbuzz/src/hb-ot-font.cc +++ b/thirdparty/harfbuzz/src/hb-ot-font.cc @@ -43,6 +43,7 @@ #include "hb-ot-hmtx-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. +#include "hb-ot-var-varc-table.hh" #include "hb-ot-vorg-table.hh" #include "OT/Color/CBDT/CBDT.hh" #include "OT/Color/COLR/COLR.hh" @@ -523,6 +524,10 @@ hb_ot_draw_glyph (hb_font_t *font, { // Need draw_session to be destructed before emboldening. hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs, embolden ? &outline : draw_data, font->slant_xy); +#ifndef HB_NO_VAR_COMPOSITES + if (!font->face->table.VARC->get_path (font, glyph, draw_session)) +#endif + // Keep the following in synch with VARC::get_path_at() if (!font->face->table.glyf->get_path (font, glyph, draw_session)) #ifndef HB_NO_CFF if (!font->face->table.cff2->get_path (font, glyph, draw_session)) @@ -563,6 +568,9 @@ hb_ot_paint_glyph (hb_font_t *font, if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return; #endif #endif +#ifndef HB_NO_VAR_COMPOSITES + if (font->face->table.VARC->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; +#endif if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; #ifndef HB_NO_CFF if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh index e259b33748..493bc6e7a1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-ot-maxp-table.hh" #include "hb-ot-hhea-table.hh" +#include "hb-ot-os2-table.hh" #include "hb-ot-var-hvar-table.hh" #include "hb-ot-var-mvar-table.hh" #include "hb-ot-metrics.hh" diff --git a/thirdparty/harfbuzz/src/hb-ot-kern-table.hh b/thirdparty/harfbuzz/src/hb-ot-kern-table.hh index b87ac8f494..2abda78af8 100644 --- a/thirdparty/harfbuzz/src/hb-ot-kern-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-kern-table.hh @@ -132,7 +132,7 @@ struct KernSubTable { switch (get_type ()) { /* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */ - case 0: return u.format0.get_kerning (left, right); + case 0: hb_barrier (); return u.format0.get_kerning (left, right); default:return 0; } } @@ -311,9 +311,9 @@ struct kern bool has_state_machine () const { switch (get_type ()) { - case 0: return u.ot.has_state_machine (); + case 0: hb_barrier (); return u.ot.has_state_machine (); #ifndef HB_NO_AAT_SHAPE - case 1: return u.aat.has_state_machine (); + case 1: hb_barrier (); return u.aat.has_state_machine (); #endif default:return false; } @@ -322,9 +322,9 @@ struct kern bool has_cross_stream () const { switch (get_type ()) { - case 0: return u.ot.has_cross_stream (); + case 0: hb_barrier (); return u.ot.has_cross_stream (); #ifndef HB_NO_AAT_SHAPE - case 1: return u.aat.has_cross_stream (); + case 1: hb_barrier (); return u.aat.has_cross_stream (); #endif default:return false; } @@ -333,9 +333,9 @@ struct kern int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const { switch (get_type ()) { - case 0: return u.ot.get_h_kerning (left, right); + case 0: hb_barrier (); return u.ot.get_h_kerning (left, right); #ifndef HB_NO_AAT_SHAPE - case 1: return u.aat.get_h_kerning (left, right); + case 1: hb_barrier (); return u.aat.get_h_kerning (left, right); #endif default:return 0; } @@ -370,9 +370,9 @@ struct kern AAT::kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const { switch (get_type ()) { - case 0: return u.ot.create_accelerator_data (num_glyphs); + case 0: hb_barrier (); return u.ot.create_accelerator_data (num_glyphs); #ifndef HB_NO_AAT_SHAPE - case 1: return u.aat.create_accelerator_data (num_glyphs); + case 1: hb_barrier (); return u.aat.create_accelerator_data (num_glyphs); #endif default:return AAT::kern_accelerator_data_t (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh index 56290905ce..68a4e7cba7 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh @@ -172,9 +172,9 @@ struct BaseCoord hb_direction_t direction) const { switch (u.format) { - case 1: return u.format1.get_coord (font, direction); - case 2: return u.format2.get_coord (font, direction); - case 3: return u.format3.get_coord (font, var_store, direction); + case 1: hb_barrier (); return u.format1.get_coord (font, direction); + case 2: hb_barrier (); return u.format2.get_coord (font, direction); + case 3: hb_barrier (); return u.format3.get_coord (font, var_store, direction); default:return 0; } } @@ -182,7 +182,7 @@ struct BaseCoord void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const { switch (u.format) { - case 3: u.format3.collect_variation_indices (varidx_set); + case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); default:return; } } @@ -193,9 +193,9 @@ struct BaseCoord if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); TRACE_DISPATCH (this, u.format); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -206,9 +206,9 @@ struct BaseCoord if (unlikely (!u.format.sanitize (c))) return_trace (false); hb_barrier (); switch (u.format) { - case 1: return_trace (u.format1.sanitize (c)); - case 2: return_trace (u.format2.sanitize (c)); - case 3: return_trace (u.format3.sanitize (c)); + case 1: hb_barrier (); return_trace (u.format1.sanitize (c)); + case 2: hb_barrier (); return_trace (u.format2.sanitize (c)); + case 3: hb_barrier (); return_trace (u.format3.sanitize (c)); default:return_trace (false); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 65c8309573..8216f54ca1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -646,8 +646,7 @@ struct FeatureParamsCharacterVariants return; unsigned last_name_id = (unsigned) firstParamUILabelNameID + (unsigned) numNamedParameters - 1; - if (last_name_id >= 256 && last_name_id <= 32767) - nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id); + nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id); } bool subset (hb_subset_context_t *c) const @@ -2068,11 +2067,11 @@ struct ClassDef unsigned int get_class (hb_codepoint_t glyph_id) const { switch (u.format) { - case 1: return u.format1.get_class (glyph_id); - case 2: return u.format2.get_class (glyph_id); + case 1: hb_barrier (); return u.format1.get_class (glyph_id); + case 2: hb_barrier (); return u.format2.get_class (glyph_id); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.get_class (glyph_id); - case 4: return u.format4.get_class (glyph_id); + case 3: hb_barrier (); return u.format3.get_class (glyph_id); + case 4: hb_barrier (); return u.format4.get_class (glyph_id); #endif default:return 0; } @@ -2081,11 +2080,11 @@ struct ClassDef unsigned get_population () const { switch (u.format) { - case 1: return u.format1.get_population (); - case 2: return u.format2.get_population (); + case 1: hb_barrier (); return u.format1.get_population (); + case 2: hb_barrier (); return u.format2.get_population (); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.get_population (); - case 4: return u.format4.get_population (); + case 3: hb_barrier (); return u.format3.get_population (); + case 4: hb_barrier (); return u.format4.get_population (); #endif default:return NOT_COVERED; } @@ -2147,11 +2146,11 @@ struct ClassDef switch (u.format) { - case 1: return_trace (u.format1.serialize (c, it)); - case 2: return_trace (u.format2.serialize (c, it)); + case 1: hb_barrier (); return_trace (u.format1.serialize (c, it)); + case 2: hb_barrier (); return_trace (u.format2.serialize (c, it)); #ifndef HB_NO_BEYOND_64K - case 3: return_trace (u.format3.serialize (c, it)); - case 4: return_trace (u.format4.serialize (c, it)); + case 3: hb_barrier (); return_trace (u.format3.serialize (c, it)); + case 4: hb_barrier (); return_trace (u.format4.serialize (c, it)); #endif default:return_trace (false); } @@ -2165,11 +2164,11 @@ struct ClassDef { TRACE_SUBSET (this); switch (u.format) { - case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); - case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); + case 1: hb_barrier (); return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); + case 2: hb_barrier (); return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); #ifndef HB_NO_BEYOND_64K - case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); - case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); + case 3: hb_barrier (); return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); + case 4: hb_barrier (); return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); #endif default:return_trace (false); } @@ -2181,11 +2180,11 @@ struct ClassDef if (!u.format.sanitize (c)) return_trace (false); hb_barrier (); switch (u.format) { - case 1: return_trace (u.format1.sanitize (c)); - case 2: return_trace (u.format2.sanitize (c)); + case 1: hb_barrier (); return_trace (u.format1.sanitize (c)); + case 2: hb_barrier (); return_trace (u.format2.sanitize (c)); #ifndef HB_NO_BEYOND_64K - case 3: return_trace (u.format3.sanitize (c)); - case 4: return_trace (u.format4.sanitize (c)); + case 3: hb_barrier (); return_trace (u.format3.sanitize (c)); + case 4: hb_barrier (); return_trace (u.format4.sanitize (c)); #endif default:return_trace (true); } @@ -2194,11 +2193,11 @@ struct ClassDef unsigned cost () const { switch (u.format) { - case 1: return u.format1.cost (); - case 2: return u.format2.cost (); + case 1: hb_barrier (); return u.format1.cost (); + case 2: hb_barrier (); return u.format2.cost (); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.cost (); - case 4: return u.format4.cost (); + case 3: hb_barrier (); return u.format3.cost (); + case 4: hb_barrier (); return u.format4.cost (); #endif default:return 0u; } @@ -2210,11 +2209,11 @@ struct ClassDef bool collect_coverage (set_t *glyphs) const { switch (u.format) { - case 1: return u.format1.collect_coverage (glyphs); - case 2: return u.format2.collect_coverage (glyphs); + case 1: hb_barrier (); return u.format1.collect_coverage (glyphs); + case 2: hb_barrier (); return u.format2.collect_coverage (glyphs); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.collect_coverage (glyphs); - case 4: return u.format4.collect_coverage (glyphs); + case 3: hb_barrier (); return u.format3.collect_coverage (glyphs); + case 4: hb_barrier (); return u.format4.collect_coverage (glyphs); #endif default:return false; } @@ -2226,11 +2225,11 @@ struct ClassDef bool collect_class (set_t *glyphs, unsigned int klass) const { switch (u.format) { - case 1: return u.format1.collect_class (glyphs, klass); - case 2: return u.format2.collect_class (glyphs, klass); + case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass); + case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.collect_class (glyphs, klass); - case 4: return u.format4.collect_class (glyphs, klass); + case 3: hb_barrier (); return u.format3.collect_class (glyphs, klass); + case 4: hb_barrier (); return u.format4.collect_class (glyphs, klass); #endif default:return false; } @@ -2239,11 +2238,11 @@ struct ClassDef bool intersects (const hb_set_t *glyphs) const { switch (u.format) { - case 1: return u.format1.intersects (glyphs); - case 2: return u.format2.intersects (glyphs); + case 1: hb_barrier (); return u.format1.intersects (glyphs); + case 2: hb_barrier (); return u.format2.intersects (glyphs); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.intersects (glyphs); - case 4: return u.format4.intersects (glyphs); + case 3: hb_barrier (); return u.format3.intersects (glyphs); + case 4: hb_barrier (); return u.format4.intersects (glyphs); #endif default:return false; } @@ -2251,11 +2250,11 @@ struct ClassDef bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const { switch (u.format) { - case 1: return u.format1.intersects_class (glyphs, klass); - case 2: return u.format2.intersects_class (glyphs, klass); + case 1: hb_barrier (); return u.format1.intersects_class (glyphs, klass); + case 2: hb_barrier (); return u.format2.intersects_class (glyphs, klass); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.intersects_class (glyphs, klass); - case 4: return u.format4.intersects_class (glyphs, klass); + case 3: hb_barrier (); return u.format3.intersects_class (glyphs, klass); + case 4: hb_barrier (); return u.format4.intersects_class (glyphs, klass); #endif default:return false; } @@ -2264,11 +2263,11 @@ struct ClassDef void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const { switch (u.format) { - case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs); - case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs); + case 1: hb_barrier (); return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs); + case 2: hb_barrier (); return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs); - case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs); + case 3: hb_barrier (); return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs); + case 4: hb_barrier (); return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs); #endif default:return; } @@ -2277,11 +2276,11 @@ struct ClassDef void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const { switch (u.format) { - case 1: return u.format1.intersected_classes (glyphs, intersect_classes); - case 2: return u.format2.intersected_classes (glyphs, intersect_classes); + case 1: hb_barrier (); return u.format1.intersected_classes (glyphs, intersect_classes); + case 2: hb_barrier (); return u.format2.intersected_classes (glyphs, intersect_classes); #ifndef HB_NO_BEYOND_64K - case 3: return u.format3.intersected_classes (glyphs, intersect_classes); - case 4: return u.format4.intersected_classes (glyphs, intersect_classes); + case 3: hb_barrier (); return u.format3.intersected_classes (glyphs, intersect_classes); + case 4: hb_barrier (); return u.format4.intersected_classes (glyphs, intersect_classes); #endif default:return; } @@ -2421,12 +2420,12 @@ struct delta_row_encoding_t int combined_width = 0; for (unsigned i = 0; i < chars.length; i++) combined_width += hb_max (chars.arrayZ[i], other_encoding.chars.arrayZ[i]); - + hb_vector_t<uint8_t> combined_columns; combined_columns.alloc (columns.length); for (unsigned i = 0; i < columns.length; i++) combined_columns.push (columns.arrayZ[i] | other_encoding.columns.arrayZ[i]); - + int combined_overhead = get_chars_overhead (combined_columns); int combined_gain = (int) overhead + (int) other_encoding.overhead - combined_overhead - (combined_width - (int) width) * items.length @@ -2471,6 +2470,8 @@ struct VarRegionAxis int peak = peakCoord.to_int (); if (peak == 0 || coord == peak) return 1.f; + else if (coord == 0) // Faster + return 0.f; int start = startCoord.to_int (), end = endCoord.to_int (); @@ -2494,8 +2495,6 @@ struct VarRegionAxis { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); - /* TODO Handle invalid start/peak/end configs, so we don't - * have to do that at runtime. */ } bool serialize (hb_serialize_context_t *c) const @@ -2511,6 +2510,33 @@ struct VarRegionAxis public: DEFINE_SIZE_STATIC (6); }; +struct SparseVarRegionAxis +{ + float evaluate (const int *coords, unsigned int coord_len) const + { + unsigned i = axisIndex; + int coord = i < coord_len ? coords[i] : 0; + return axis.evaluate (coord); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + bool serialize (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + + public: + HBUINT16 axisIndex; + VarRegionAxis axis; + public: + DEFINE_SIZE_STATIC (8); +}; #define REGION_CACHE_ITEM_CACHE_INVALID 2.f @@ -2675,6 +2701,65 @@ struct VarRegionList DEFINE_SIZE_ARRAY (4, axesZ); }; +struct SparseVariationRegion : Array16Of<SparseVarRegionAxis> +{ + float evaluate (const int *coords, unsigned int coord_len) const + { + float v = 1.f; + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + { + float factor = arrayZ[i].evaluate (coords, coord_len); + if (factor == 0.f) + return 0.; + v *= factor; + } + return v; + } +}; + +struct SparseVarRegionList +{ + using cache_t = float; + + float evaluate (unsigned int region_index, + const int *coords, unsigned int coord_len, + cache_t *cache = nullptr) const + { + if (unlikely (region_index >= regions.len)) + return 0.; + + float *cached_value = nullptr; + if (cache) + { + cached_value = &(cache[region_index]); + if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)) + return *cached_value; + } + + const SparseVariationRegion ®ion = this+regions[region_index]; + + float v = region.evaluate (coords, coord_len); + + if (cache) + *cached_value = v; + return v; + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (regions.sanitize (c, this)); + } + + public: + Array16Of<Offset32To<SparseVariationRegion>> + regions; + public: + DEFINE_SIZE_ARRAY (2, regions); +}; + + struct VarData { unsigned int get_item_count () const @@ -2682,7 +2767,7 @@ struct VarData unsigned int get_region_index_count () const { return regionIndices.len; } - + unsigned get_region_index (unsigned i) const { return i >= regionIndices.len ? -1 : regionIndices[i]; } @@ -3036,6 +3121,61 @@ struct VarData DEFINE_SIZE_ARRAY (6, regionIndices); }; +struct MultiVarData +{ + unsigned int get_size () const + { return min_size + - regionIndices.min_size + regionIndices.get_size () + + StructAfter<CFF2Index> (regionIndices).get_size (); + } + + void get_delta (unsigned int inner, + const int *coords, unsigned int coord_count, + const SparseVarRegionList ®ions, + hb_array_t<float> out, + SparseVarRegionList::cache_t *cache = nullptr) const + { + auto &deltaSets = StructAfter<decltype (deltaSetsX)> (regionIndices); + + auto values_iter = deltaSets[inner]; + + unsigned regionCount = regionIndices.len; + unsigned count = out.length; + for (unsigned regionIndex = 0; regionIndex < regionCount; regionIndex++) + { + float scalar = regions.evaluate (regionIndices.arrayZ[regionIndex], + coords, coord_count, + cache); + if (scalar == 1.f) + for (unsigned i = 0; i < count; i++) + out.arrayZ[i] += *values_iter++; + else if (scalar) + for (unsigned i = 0; i < count; i++) + out.arrayZ[i] += *values_iter++ * scalar; + else + values_iter += count; + } + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (format.sanitize (c) && + hb_barrier () && + format == 1 && + regionIndices.sanitize (c) && + hb_barrier () && + StructAfter<decltype (deltaSetsX)> (regionIndices).sanitize (c)); + } + + protected: + HBUINT8 format; // 1 + Array16Of<HBUINT16> regionIndices; + TupleList deltaSetsX; + public: + DEFINE_SIZE_MIN (8); +}; + struct ItemVariationStore { friend struct item_variations_t; @@ -3088,7 +3228,7 @@ struct ItemVariationStore return get_delta (outer, inner, coords, coord_count, cache); } float get_delta (unsigned int index, - hb_array_t<int> coords, + hb_array_t<const int> coords, VarRegionList::cache_t *cache = nullptr) const { return get_delta (index, @@ -3121,7 +3261,7 @@ struct ItemVariationStore return_trace (false); #endif if (unlikely (!c->extend_min (this))) return_trace (false); - + format = 1; if (!regions.serialize_serialize (c, axis_tags, region_list)) return_trace (false); @@ -3136,7 +3276,7 @@ struct ItemVariationStore for (unsigned i = 0; i < num_var_data; i++) if (!dataSets[i].serialize_serialize (c, has_long, vardata_encodings[i].items)) return_trace (false); - + return_trace (true); } @@ -3295,8 +3435,358 @@ struct ItemVariationStore DEFINE_SIZE_ARRAY_SIZED (8, dataSets); }; +struct MultiItemVariationStore +{ + using cache_t = SparseVarRegionList::cache_t; + + cache_t *create_cache () const + { +#ifdef HB_NO_VAR + return nullptr; +#endif + auto &r = this+regions; + unsigned count = r.regions.len; + + float *cache = (float *) hb_malloc (sizeof (float) * count); + if (unlikely (!cache)) return nullptr; + + for (unsigned i = 0; i < count; i++) + cache[i] = REGION_CACHE_ITEM_CACHE_INVALID; + + return cache; + } + + static void destroy_cache (cache_t *cache) { hb_free (cache); } + + private: + void get_delta (unsigned int outer, unsigned int inner, + const int *coords, unsigned int coord_count, + hb_array_t<float> out, + VarRegionList::cache_t *cache = nullptr) const + { +#ifdef HB_NO_VAR + return; +#endif + + if (unlikely (outer >= dataSets.len)) + return; + + return (this+dataSets[outer]).get_delta (inner, + coords, coord_count, + this+regions, + out, + cache); + } + + public: + void get_delta (unsigned int index, + const int *coords, unsigned int coord_count, + hb_array_t<float> out, + VarRegionList::cache_t *cache = nullptr) const + { + unsigned int outer = index >> 16; + unsigned int inner = index & 0xFFFF; + get_delta (outer, inner, coords, coord_count, out, cache); + } + void get_delta (unsigned int index, + hb_array_t<const int> coords, + hb_array_t<float> out, + VarRegionList::cache_t *cache = nullptr) const + { + return get_delta (index, + coords.arrayZ, coords.length, + out, + cache); + } + + bool sanitize (hb_sanitize_context_t *c) const + { +#ifdef HB_NO_VAR + return true; +#endif + + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + hb_barrier () && + format == 1 && + regions.sanitize (c, this) && + dataSets.sanitize (c, this)); + } + + protected: + HBUINT16 format; // 1 + Offset32To<SparseVarRegionList> regions; + Array16OfOffset32To<MultiVarData> dataSets; + public: + DEFINE_SIZE_ARRAY_SIZED (8, dataSets); +}; + #undef REGION_CACHE_ITEM_CACHE_INVALID +template <typename MapCountT> +struct DeltaSetIndexMapFormat01 +{ + friend struct DeltaSetIndexMap; + + unsigned get_size () const + { return min_size + mapCount * get_width (); } + + private: + DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + + template <typename T> + bool serialize (hb_serialize_context_t *c, const T &plan) + { + unsigned int width = plan.get_width (); + unsigned int inner_bit_count = plan.get_inner_bit_count (); + const hb_array_t<const uint32_t> output_map = plan.get_output_map (); + + TRACE_SERIALIZE (this); + if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0)))) + return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); + + entryFormat = ((width-1)<<4)|(inner_bit_count-1); + mapCount = output_map.length; + HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length); + if (unlikely (!p)) return_trace (false); + for (unsigned int i = 0; i < output_map.length; i++) + { + unsigned int v = output_map.arrayZ[i]; + if (v) + { + unsigned int outer = v >> 16; + unsigned int inner = v & 0xFFFF; + unsigned int u = (outer << inner_bit_count) | inner; + for (unsigned int w = width; w > 0;) + { + p[--w] = u; + u >>= 8; + } + } + p += width; + } + return_trace (true); + } + + uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */ + { + /* If count is zero, pass value unchanged. This takes + * care of direct mapping for advance map. */ + if (!mapCount) + return v; + + if (v >= mapCount) + v = mapCount - 1; + + unsigned int u = 0; + { /* Fetch it. */ + unsigned int w = get_width (); + const HBUINT8 *p = mapDataZ.arrayZ + w * v; + for (; w; w--) + u = (u << 8) + *p++; + } + + { /* Repack it. */ + unsigned int n = get_inner_bit_count (); + unsigned int outer = u >> n; + unsigned int inner = u & ((1 << n) - 1); + u = (outer<<16) | inner; + } + + return u; + } + + unsigned get_map_count () const { return mapCount; } + unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; } + unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; } + + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + hb_barrier () && + c->check_range (mapDataZ.arrayZ, + mapCount, + get_width ())); + } + + protected: + HBUINT8 format; /* Format identifier--format = 0 */ + HBUINT8 entryFormat; /* A packed field that describes the compressed + * representation of delta-set indices. */ + MapCountT mapCount; /* The number of mapping entries. */ + UnsizedArrayOf<HBUINT8> + mapDataZ; /* The delta-set index mapping data. */ + + public: + DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ); +}; + +struct DeltaSetIndexMap +{ + template <typename T> + bool serialize (hb_serialize_context_t *c, const T &plan) + { + TRACE_SERIALIZE (this); + unsigned length = plan.get_output_map ().length; + u.format = length <= 0xFFFF ? 0 : 1; + switch (u.format) { + case 0: hb_barrier (); return_trace (u.format0.serialize (c, plan)); + case 1: hb_barrier (); return_trace (u.format1.serialize (c, plan)); + default:return_trace (false); + } + } + + uint32_t map (unsigned v) const + { + switch (u.format) { + case 0: hb_barrier (); return (u.format0.map (v)); + case 1: hb_barrier (); return (u.format1.map (v)); + default:return v; + } + } + + unsigned get_map_count () const + { + switch (u.format) { + case 0: hb_barrier (); return u.format0.get_map_count (); + case 1: hb_barrier (); return u.format1.get_map_count (); + default:return 0; + } + } + + unsigned get_width () const + { + switch (u.format) { + case 0: hb_barrier (); return u.format0.get_width (); + case 1: hb_barrier (); return u.format1.get_width (); + default:return 0; + } + } + + unsigned get_inner_bit_count () const + { + switch (u.format) { + case 0: hb_barrier (); return u.format0.get_inner_bit_count (); + case 1: hb_barrier (); return u.format1.get_inner_bit_count (); + default:return 0; + } + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return_trace (false); + hb_barrier (); + switch (u.format) { + case 0: hb_barrier (); return_trace (u.format0.sanitize (c)); + case 1: hb_barrier (); return_trace (u.format1.sanitize (c)); + default:return_trace (true); + } + } + + DeltaSetIndexMap* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + switch (u.format) { + case 0: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c))); + case 1: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c))); + default:return_trace (nullptr); + } + } + + protected: + union { + HBUINT8 format; /* Format identifier */ + DeltaSetIndexMapFormat01<HBUINT16> format0; + DeltaSetIndexMapFormat01<HBUINT32> format1; + } u; + public: + DEFINE_SIZE_UNION (1, format); +}; + + +struct ItemVarStoreInstancer +{ + ItemVarStoreInstancer (const ItemVariationStore *varStore, + const DeltaSetIndexMap *varIdxMap, + hb_array_t<const int> coords, + VarRegionList::cache_t *cache = nullptr) : + varStore (varStore), varIdxMap (varIdxMap), coords (coords), cache (cache) + { + if (!varStore) + varStore = &Null(ItemVariationStore); + } + + operator bool () const { return varStore && bool (coords); } + + float operator[] (uint32_t varIdx) const + { return (*this) (varIdx); } + + float operator() (uint32_t varIdx, unsigned short offset = 0) const + { + if (varIdxMap) + varIdx = varIdxMap->map (VarIdx::add (varIdx, offset)); + else + varIdx += offset; + return coords ? varStore->get_delta (varIdx, coords, cache) : 0.f; + } + + const ItemVariationStore *varStore; + const DeltaSetIndexMap *varIdxMap; + hb_array_t<const int> coords; + VarRegionList::cache_t *cache; +}; + +struct MultiItemVarStoreInstancer +{ + MultiItemVarStoreInstancer (const MultiItemVariationStore *varStore, + const DeltaSetIndexMap *varIdxMap, + hb_array_t<const int> coords, + SparseVarRegionList::cache_t *cache = nullptr) : + varStore (varStore), varIdxMap (varIdxMap), coords (coords), cache (cache) + { + if (!varStore) + varStore = &Null(MultiItemVariationStore); + } + + operator bool () const { return varStore && bool (coords); } + + float operator[] (uint32_t varIdx) const + { + float v = 0; + (*this) (hb_array (&v, 1), varIdx); + return v; + } + + void operator() (hb_array_t<float> out, uint32_t varIdx, unsigned short offset = 0) const + { + if (coords) + { + if (varIdxMap) + varIdx = varIdxMap->map (VarIdx::add (varIdx, offset)); + else + varIdx += offset; + varStore->get_delta (varIdx, coords, out, cache); + } + else + for (unsigned i = 0; i < out.length; i++) + out.arrayZ[i] = 0.f; + } + + const MultiItemVariationStore *varStore; + const DeltaSetIndexMap *varIdxMap; + hb_array_t<const int> coords; + SparseVarRegionList::cache_t *cache; +}; + + /* * Feature Variations */ @@ -3308,7 +3798,16 @@ enum Cond_with_Var_flag_t DROP_RECORD_WITH_VAR = 3, }; -struct ConditionFormat1 +struct Condition; + +template <typename Instancer> +static bool +_hb_recurse_condition_evaluate (const struct Condition &condition, + const int *coords, + unsigned int coord_len, + Instancer *instancer); + +struct ConditionAxisRange { friend struct Condition; @@ -3401,7 +3900,9 @@ struct ConditionFormat1 return KEEP_RECORD_WITH_VAR; } - bool evaluate (const int *coords, unsigned int coord_len) const + template <typename Instancer> + bool evaluate (const int *coords, unsigned int coord_len, + Instancer *instancer HB_UNUSED) const { int coord = axisIndex < coord_len ? coords[axisIndex] : 0; return filterRangeMinValue.to_int () <= coord && coord <= filterRangeMaxValue.to_int (); @@ -3422,12 +3923,199 @@ struct ConditionFormat1 DEFINE_SIZE_STATIC (8); }; +struct ConditionValue +{ + friend struct Condition; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + private: + template <typename Instancer> + bool evaluate (const int *coords, unsigned int coord_len, + Instancer *instancer) const + { + signed value = defaultValue; + value += (*instancer)[varIdx]; + return value > 0; + } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l, + bool insert_catch_all) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + HBUINT16 format; /* Format identifier--format = 2 */ + HBINT16 defaultValue; /* Value at default instance. */ + VarIdx varIdx; /* Variation index */ + public: + DEFINE_SIZE_STATIC (8); +}; + +struct ConditionAnd +{ + friend struct Condition; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + private: + template <typename Instancer> + bool evaluate (const int *coords, unsigned int coord_len, + Instancer *instancer) const + { + unsigned int count = conditions.len; + for (unsigned int i = 0; i < count; i++) + if (!_hb_recurse_condition_evaluate (this+conditions.arrayZ[i], + coords, coord_len, + instancer)) + return false; + return true; + } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l, + bool insert_catch_all) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, this)); + } + + protected: + HBUINT16 format; /* Format identifier--format = 3 */ + Array8OfOffset24To<struct Condition> conditions; + public: + DEFINE_SIZE_ARRAY (3, conditions); +}; + +struct ConditionOr +{ + friend struct Condition; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + private: + template <typename Instancer> + bool evaluate (const int *coords, unsigned int coord_len, + Instancer *instancer) const + { + unsigned int count = conditions.len; + for (unsigned int i = 0; i < count; i++) + if (_hb_recurse_condition_evaluate (this+conditions.arrayZ[i], + coords, coord_len, + instancer)) + return true; + return false; + } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l, + bool insert_catch_all) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, this)); + } + + protected: + HBUINT16 format; /* Format identifier--format = 4 */ + Array8OfOffset24To<struct Condition> conditions; + public: + DEFINE_SIZE_ARRAY (3, conditions); +}; + +struct ConditionNegate +{ + friend struct Condition; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + private: + template <typename Instancer> + bool evaluate (const int *coords, unsigned int coord_len, + Instancer *instancer) const + { + return !_hb_recurse_condition_evaluate (this+condition, + coords, coord_len, + instancer); + } + + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l, + bool insert_catch_all) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (condition.sanitize (c, this)); + } + + protected: + HBUINT16 format; /* Format identifier--format = 5 */ + Offset24To<struct Condition> condition; + public: + DEFINE_SIZE_STATIC (5); +}; + struct Condition { - bool evaluate (const int *coords, unsigned int coord_len) const + template <typename Instancer> + bool evaluate (const int *coords, unsigned int coord_len, + Instancer *instancer) const { switch (u.format) { - case 1: return u.format1.evaluate (coords, coord_len); + case 1: hb_barrier (); return u.format1.evaluate (coords, coord_len, instancer); + case 2: hb_barrier (); return u.format2.evaluate (coords, coord_len, instancer); + case 3: hb_barrier (); return u.format3.evaluate (coords, coord_len, instancer); + case 4: hb_barrier (); return u.format4.evaluate (coords, coord_len, instancer); + case 5: hb_barrier (); return u.format5.evaluate (coords, coord_len, instancer); default:return false; } } @@ -3436,7 +4124,8 @@ struct Condition hb_map_t *condition_map /* OUT */) const { switch (u.format) { - case 1: return u.format1.keep_with_variations (c, condition_map); + case 1: hb_barrier (); return u.format1.keep_with_variations (c, condition_map); + // TODO(subset) default: c->apply = false; return KEEP_COND_WITH_VAR; } } @@ -3447,7 +4136,11 @@ struct Condition if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); TRACE_DISPATCH (this, u.format); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -3458,7 +4151,11 @@ struct Condition if (!u.format.sanitize (c)) return_trace (false); hb_barrier (); switch (u.format) { - case 1: return_trace (u.format1.sanitize (c)); + case 1: hb_barrier (); return_trace (u.format1.sanitize (c)); + case 2: hb_barrier (); return_trace (u.format2.sanitize (c)); + case 3: hb_barrier (); return_trace (u.format3.sanitize (c)); + case 4: hb_barrier (); return_trace (u.format4.sanitize (c)); + case 5: hb_barrier (); return_trace (u.format5.sanitize (c)); default:return_trace (true); } } @@ -3466,19 +4163,51 @@ struct Condition protected: union { HBUINT16 format; /* Format identifier */ - ConditionFormat1 format1; + ConditionAxisRange format1; + ConditionValue format2; + ConditionAnd format3; + ConditionOr format4; + ConditionNegate format5; } u; public: DEFINE_SIZE_UNION (2, format); }; +template <typename Instancer> +bool +_hb_recurse_condition_evaluate (const struct Condition &condition, + const int *coords, + unsigned int coord_len, + Instancer *instancer) +{ + return condition.evaluate (coords, coord_len, instancer); +} + +struct ConditionList +{ + const Condition& operator[] (unsigned i) const + { return this+conditions[i]; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, this)); + } + + protected: + Array32OfOffset32To<Condition> conditions; + public: + DEFINE_SIZE_ARRAY (4, conditions); +}; + struct ConditionSet { - bool evaluate (const int *coords, unsigned int coord_len) const + bool evaluate (const int *coords, unsigned int coord_len, + ItemVarStoreInstancer *instancer) const { unsigned int count = conditions.len; for (unsigned int i = 0; i < count; i++) - if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len)) + if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len, instancer)) return false; return true; } @@ -3812,13 +4541,14 @@ struct FeatureVariations static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu; bool find_index (const int *coords, unsigned int coord_len, - unsigned int *index) const + unsigned int *index, + ItemVarStoreInstancer *instancer) const { unsigned int count = varRecords.len; for (unsigned int i = 0; i < count; i++) { const FeatureVariationRecord &record = varRecords.arrayZ[i]; - if ((this+record.conditions).evaluate (coords, coord_len)) + if ((this+record.conditions).evaluate (coords, coord_len, instancer)) { *index = i; return true; @@ -4079,7 +4809,7 @@ struct VariationDevice } protected: - VarIdx varIdx; + VarIdx varIdx; /* Variation index */ HBUINT16 deltaFormat; /* Format identifier for this table: 0x0x8000 */ public: DEFINE_SIZE_STATIC (6); diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index 6b760b1108..2c9056c705 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -406,6 +406,7 @@ struct hb_ot_apply_context_t : void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } + void set_ignore_hidden (bool ignore_hidden_) { ignore_hidden = ignore_hidden_; } void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } void set_mask (hb_mask_t mask_) { mask = mask_; } void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; } @@ -451,9 +452,10 @@ struct hb_ot_apply_context_t : if (!c->check_glyph_property (&info, lookup_props)) return SKIP_YES; - if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) && + if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && - (ignore_zwj || !_hb_glyph_info_is_zwj (&info)))) + (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && + (ignore_hidden || !_hb_glyph_info_is_hidden (&info)))) return SKIP_MAYBE; return SKIP_NO; @@ -464,6 +466,7 @@ struct hb_ot_apply_context_t : hb_mask_t mask = -1; bool ignore_zwnj = false; bool ignore_zwj = false; + bool ignore_hidden = false; bool per_syllable = false; uint8_t syllable = 0; match_func_t match_func = nullptr; @@ -486,6 +489,8 @@ struct hb_ot_apply_context_t : matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj)); /* Ignore ZWJ if we are matching context, or asked to. */ matcher.set_ignore_zwj (context_match || c->auto_zwj); + /* Ignore hidden glyphs (like CGJ) during GPOS. */ + matcher.set_ignore_hidden (c->table_index == 1); matcher.set_mask (context_match ? -1 : c->lookup_mask); /* Per syllable matching is only for GSUB. */ matcher.set_per_syllable (c->table_index == 0 && c->per_syllable); @@ -2901,12 +2906,12 @@ struct Context if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); TRACE_DISPATCH (this, u.format); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); #ifndef HB_NO_BEYOND_64K - case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); - case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...)); + case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); } @@ -3390,6 +3395,15 @@ struct ChainRuleSet * * Replicated from LigatureSet::apply(). */ + /* If the input skippy has non-auto joiners behavior (as in Indic shapers), + * skip this fast path, as we don't distinguish between input & lookahead + * matching in the fast path. + * + * https://github.com/harfbuzz/harfbuzz/issues/4813 + */ + if (!c->auto_zwnj || !c->auto_zwj) + goto slow; + hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (c->buffer->idx); skippy_iter.set_match_func (match_always, nullptr); @@ -3429,10 +3443,10 @@ struct ChainRuleSet } matched = skippy_iter.next (); if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))) - { + { second = &c->buffer->info[skippy_iter.idx]; unsafe_to2 = skippy_iter.idx + 1; - } + } auto match_input = lookup_context.funcs.match[1]; auto match_lookahead = lookup_context.funcs.match[2]; @@ -4225,12 +4239,12 @@ struct ChainContext if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); TRACE_DISPATCH (this, u.format); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); #ifndef HB_NO_BEYOND_64K - case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); - case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...)); + case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...)); #endif default:return_trace (c->default_return_value ()); } @@ -4314,7 +4328,7 @@ struct Extension unsigned int get_type () const { switch (u.format) { - case 1: return u.format1.get_type (); + case 1: hb_barrier (); return u.format1.get_type (); default:return 0; } } @@ -4322,7 +4336,7 @@ struct Extension const X& get_subtable () const { switch (u.format) { - case 1: return u.format1.template get_subtable<typename T::SubTable> (); + case 1: hb_barrier (); return u.format1.template get_subtable<typename T::SubTable> (); default:return Null (typename T::SubTable); } } @@ -4334,7 +4348,7 @@ struct Extension 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); + case 1: hb_barrier (); return u.format1.subset (c); default: return c->default_return_value (); } } @@ -4345,7 +4359,7 @@ struct Extension if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); TRACE_DISPATCH (this, u.format); switch (u.format) { - case 1: return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...)); + case 1: hb_barrier (); return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -4560,9 +4574,9 @@ struct GSUBGPOS unsigned int get_size () const { switch (u.version.major) { - case 1: return u.version1.get_size (); + case 1: hb_barrier (); return u.version1.get_size (); #ifndef HB_NO_BEYOND_64K - case 2: return u.version2.get_size (); + case 2: hb_barrier (); return u.version2.get_size (); #endif default: return u.version.static_size; } @@ -4575,9 +4589,9 @@ struct GSUBGPOS if (unlikely (!u.version.sanitize (c))) return_trace (false); hb_barrier (); switch (u.version.major) { - case 1: return_trace (u.version1.sanitize<TLookup> (c)); + case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c)); #ifndef HB_NO_BEYOND_64K - case 2: return_trace (u.version2.sanitize<TLookup> (c)); + case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c)); #endif default: return_trace (true); } @@ -4587,9 +4601,9 @@ struct GSUBGPOS bool subset (hb_subset_layout_context_t *c) const { switch (u.version.major) { - case 1: return u.version1.subset<TLookup> (c); + case 1: hb_barrier (); return u.version1.subset<TLookup> (c); #ifndef HB_NO_BEYOND_64K - case 2: return u.version2.subset<TLookup> (c); + case 2: hb_barrier (); return u.version2.subset<TLookup> (c); #endif default: return false; } @@ -4598,9 +4612,9 @@ struct GSUBGPOS const ScriptList &get_script_list () const { switch (u.version.major) { - case 1: return this+u.version1.scriptList; + case 1: hb_barrier (); return this+u.version1.scriptList; #ifndef HB_NO_BEYOND_64K - case 2: return this+u.version2.scriptList; + case 2: hb_barrier (); return this+u.version2.scriptList; #endif default: return Null (ScriptList); } @@ -4608,9 +4622,9 @@ struct GSUBGPOS const FeatureList &get_feature_list () const { switch (u.version.major) { - case 1: return this+u.version1.featureList; + case 1: hb_barrier (); return this+u.version1.featureList; #ifndef HB_NO_BEYOND_64K - case 2: return this+u.version2.featureList; + case 2: hb_barrier (); return this+u.version2.featureList; #endif default: return Null (FeatureList); } @@ -4618,9 +4632,9 @@ struct GSUBGPOS unsigned int get_lookup_count () const { switch (u.version.major) { - case 1: return (this+u.version1.lookupList).len; + case 1: hb_barrier (); return (this+u.version1.lookupList).len; #ifndef HB_NO_BEYOND_64K - case 2: return (this+u.version2.lookupList).len; + case 2: hb_barrier (); return (this+u.version2.lookupList).len; #endif default: return 0; } @@ -4628,9 +4642,9 @@ struct GSUBGPOS const Lookup& get_lookup (unsigned int i) const { switch (u.version.major) { - case 1: return (this+u.version1.lookupList)[i]; + case 1: hb_barrier (); return (this+u.version1.lookupList)[i]; #ifndef HB_NO_BEYOND_64K - case 2: return (this+u.version2.lookupList)[i]; + case 2: hb_barrier (); return (this+u.version2.lookupList)[i]; #endif default: return Null (Lookup); } @@ -4638,9 +4652,9 @@ struct GSUBGPOS const FeatureVariations &get_feature_variations () const { switch (u.version.major) { - case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations)); + case 1: hb_barrier (); return (u.version.to_int () >= 0x00010001u && hb_barrier () ? this+u.version1.featureVars : Null (FeatureVariations)); #ifndef HB_NO_BEYOND_64K - case 2: return this+u.version2.featureVars; + case 2: hb_barrier (); return this+u.version2.featureVars; #endif default: return Null (FeatureVariations); } @@ -4674,13 +4688,14 @@ struct GSUBGPOS { return get_feature_list ().find_index (tag, index); } bool find_variations_index (const int *coords, unsigned int num_coords, - unsigned int *index) const + unsigned int *index, + ItemVarStoreInstancer *instancer) const { #ifdef HB_NO_VAR *index = FeatureVariations::NOT_FOUND_INDEX; return false; #endif - return get_feature_variations ().find_index (coords, num_coords, index); + return get_feature_variations ().find_index (coords, num_coords, index, instancer); } const Feature& get_feature_variation (unsigned int feature_index, unsigned int variations_index) const diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index 613c97fd9e..66c2eb4d8e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -1443,8 +1443,12 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face, unsigned int *variations_index /* out */) { const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::GDEF &gdef = *face->table.GDEF->table; - return g.find_variations_index (coords, num_coords, variations_index); + auto instancer = OT::ItemVarStoreInstancer(&gdef.get_var_store(), nullptr, + hb_array (coords, num_coords)); + + return g.find_variations_index (coords, num_coords, variations_index, &instancer); } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh index d71889331d..3a8d36ac49 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh @@ -173,12 +173,12 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start) /* Design: * unicode_props() is a two-byte number. The low byte includes: - * - General_Category: 5 bits. + * - Extended General_Category: 5 bits. * - A bit each for: * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). * * Whether it's one of the four Mongolian Free Variation Selectors, * CGJ, or other characters that are hidden but should not be ignored - * like most other Default_Ignorable()s do during matching. + * like most other Default_Ignorable()s do during GSUB matching. * * Whether it's a grapheme continuation. * * The high-byte has different meanings, switched by the Gen-Cat: @@ -311,12 +311,15 @@ _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && !_hb_glyph_info_substituted (info); } +static inline void +_hb_glyph_info_clear_default_ignorable (hb_glyph_info_t *info) +{ + info->unicode_props() &= ~ UPROPS_MASK_IGNORABLE; +} static inline bool -_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) +_hb_glyph_info_is_hidden (const hb_glyph_info_t *info) { - return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN)) - == UPROPS_MASK_IGNORABLE) && - !_hb_glyph_info_substituted (info); + return info->unicode_props() & UPROPS_MASK_HIDDEN; } static inline void _hb_glyph_info_unhide (hb_glyph_info_t *info) diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh index d44233610a..67d1b6aa71 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh @@ -84,9 +84,9 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const old_gid_new_index_map.alloc (num_glyphs); glyph_name_to_new_index.alloc (num_glyphs); - for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) + for (auto _ : c->plan->new_to_old_gid_list) { - hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); + hb_codepoint_t old_gid = _.second; unsigned old_index = glyphNameIndex[old_gid]; unsigned new_index; @@ -125,13 +125,22 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const old_gid_new_index_map.set (old_gid, new_index); } + if (old_gid_new_index_map.in_error()) + return_trace (false); + auto index_iter = + hb_range (num_glyphs) - | hb_map (reverse_glyph_map) - | hb_map_retains_sorting ([&](hb_codepoint_t old_gid) + | hb_map_retains_sorting ([&](hb_codepoint_t new_gid) { - unsigned new_index = old_gid_new_index_map.get (old_gid); - return hb_pair_t<unsigned, unsigned> (old_gid, new_index); + hb_codepoint_t *old_gid; + /* use 0 for retain-gid holes, which refers to the name .notdef, + * as the glyphNameIndex entry for that glyph ID."*/ + unsigned new_index = 0; + if (reverse_glyph_map.has (new_gid, &old_gid)) { + new_index = old_gid_new_index_map.get (*old_gid); + return hb_pair_t<unsigned, unsigned> (*old_gid, new_index); + } + return hb_pair_t<unsigned, unsigned> (new_gid, new_index); }) ; diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh index 4191879037..18ecea1825 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh @@ -301,7 +301,7 @@ struct post return_trace (c->check_struct (this) && hb_barrier () && (version.to_int () == 0x00010000 || - (version.to_int () == 0x00020000 && v2X.sanitize (c)) || + (version.to_int () == 0x00020000 && hb_barrier () && v2X.sanitize (c)) || version.to_int () == 0x00030000)); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc index 69dbec0783..b86649d778 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc @@ -74,23 +74,6 @@ * Indic shaper may want to disallow recomposing of two matras. */ -static bool -decompose_unicode (const hb_ot_shape_normalize_context_t *c, - hb_codepoint_t ab, - hb_codepoint_t *a, - hb_codepoint_t *b) -{ - return (bool) c->unicode->decompose (ab, a, b); -} - -static bool -compose_unicode (const hb_ot_shape_normalize_context_t *c, - hb_codepoint_t a, - hb_codepoint_t b, - hb_codepoint_t *ab) -{ - return (bool) c->unicode->compose (a, b, ab); -} static inline void set_glyph (hb_glyph_info_t &info, hb_font_t *font) @@ -170,7 +153,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor hb_codepoint_t u = buffer->cur().codepoint; hb_codepoint_t glyph = 0; - if (shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found)) + if (shortest && c->font->get_nominal_glyph (u, &glyph, buffer->not_found)) { next_char (buffer, glyph); return; @@ -182,7 +165,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor return; } - if (!shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found)) + if (!shortest && c->font->get_nominal_glyph (u, &glyph, buffer->not_found)) { next_char (buffer, glyph); return; @@ -237,6 +220,13 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, /* Just pass on the two characters separately, let GSUB do its magic. */ set_glyph (buffer->cur(), font); (void) buffer->next_glyph (); + + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK; + _hb_glyph_info_set_general_category (&buffer->cur(), + _HB_UNICODE_GENERAL_CATEGORY_VARIATION_SELECTOR); + if (buffer->not_found_variation_selector != HB_CODEPOINT_INVALID) + _hb_glyph_info_clear_default_ignorable (&buffer->cur()); + set_glyph (buffer->cur(), font); (void) buffer->next_glyph (); } @@ -307,15 +297,15 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; } - const hb_ot_shape_normalize_context_t c = { + hb_ot_shape_normalize_context_t c = { plan, buffer, font, buffer->unicode, - buffer->not_found, - plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode, - plan->shaper->compose ? plan->shaper->compose : compose_unicode + plan->shaper->decompose ? plan->shaper->decompose : hb_ot_shape_normalize_context_t::decompose_unicode, + plan->shaper->compose ? plan->shaper->compose : hb_ot_shape_normalize_context_t::compose_unicode }; + c.override_decompose_and_compose (plan->shaper->decompose, plan->shaper->compose); bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE; bool might_short_circuit = always_short_circuit || diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh index 12c78a2352..f12cb35c0f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh @@ -28,6 +28,7 @@ #define HB_OT_SHAPE_NORMALIZE_HH #include "hb.hh" +#include "hb-unicode.hh" /* buffer var allocations, used during the normalization process */ @@ -52,11 +53,42 @@ HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper, struct hb_ot_shape_normalize_context_t { + static bool + decompose_unicode (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t ab, + hb_codepoint_t *a, + hb_codepoint_t *b) + { + return (bool) c->unicode->decompose (ab, a, b); + } + + static bool + compose_unicode (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab) + { + return (bool) c->unicode->compose (a, b, ab); + } + + void + override_decompose_and_compose (bool (*decompose) (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t ab, + hb_codepoint_t *a, + hb_codepoint_t *b), + bool (*compose) (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab)) + { + this->decompose = decompose ? decompose : decompose_unicode; + this->compose = compose ? compose : compose_unicode; + } + const hb_ot_shape_plan_t *plan; hb_buffer_t *buffer; hb_font_t *font; hb_unicode_funcs_t *unicode; - const hb_codepoint_t not_found; bool (*decompose) (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, hb_codepoint_t *a, diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 148830022e..1aca39101e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -85,7 +85,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac , apply_morx (_hb_apply_morx (face, props)) #endif { - shaper = hb_ot_shaper_categorize (this); + shaper = hb_ot_shaper_categorize (props.script, props.direction, map.chosen_script[0]); script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE; script_fallback_mark_positioning = shaper->fallback_position; @@ -838,6 +838,29 @@ hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer) } static void +hb_ot_deal_with_variation_selectors (hb_buffer_t *buffer) +{ + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK) || + buffer->not_found_variation_selector == HB_CODEPOINT_INVALID) + return; + + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; + + for (unsigned int i = 0; i < count; i++) + { + if (_hb_glyph_info_get_general_category (&info[i]) == + _HB_UNICODE_GENERAL_CATEGORY_VARIATION_SELECTOR) + { + info[i].codepoint = buffer->not_found_variation_selector; + pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0; + _hb_glyph_info_set_general_category (&info[i], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK); + } + } +} + +static void hb_ot_hide_default_ignorables (hb_buffer_t *buffer, hb_font_t *font) { @@ -966,6 +989,7 @@ hb_ot_substitute_post (const hb_ot_shape_context_t *c) hb_aat_layout_remove_deleted_glyphs (c->buffer); #endif + hb_ot_deal_with_variation_selectors (c->buffer); hb_ot_hide_default_ignorables (c->buffer, c->font); if (c->plan->shaper->postprocess_glyphs && diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh index a5a7b84af4..e38686e3eb 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh @@ -6,10 +6,10 @@ * * on files with these headers: * - * # ArabicShaping-15.1.0.txt - * # Date: 2023-01-05 - * # Scripts-15.1.0.txt - * # Date: 2023-07-28, 16:01:07 GMT + * # ArabicShaping-16.0.0.txt + * # Date: 2024-07-30 + * # Scripts-16.0.0.txt + * # Date: 2024-04-30, 21:48:40 GMT */ #ifndef HB_OT_SHAPER_ARABIC_JOINING_LIST_HH diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh index 336a1391e9..d9917a1587 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh @@ -6,10 +6,10 @@ * * on files with these headers: * - * # ArabicShaping-15.1.0.txt - * # Date: 2023-01-05 - * # Blocks-15.1.0.txt - * # Date: 2023-07-28, 15:47:20 GMT + * # ArabicShaping-16.0.0.txt + * # Date: 2024-07-30 + * # Blocks-16.0.0.txt + * # Date: 2024-02-02 * UnicodeData.txt does not have a header. */ @@ -136,7 +136,13 @@ static const uint8_t joining_table[] = /* 10D00 */ L,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* 10D20 */ D,D,R,D, -#define joining_offset_0x10f30u 1182 +#define joining_offset_0x10ec2u 1182 + + /* Arabic Extended-C */ + + /* 10EC0 */ R,D,D, + +#define joining_offset_0x10f30u 1185 /* Sogdian */ @@ -155,14 +161,14 @@ static const uint8_t joining_table[] = /* 10FA0 */ D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D, /* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L, -#define joining_offset_0x110bdu 1338 +#define joining_offset_0x110bdu 1341 /* Kaithi */ /* 110A0 */ U,X,X, /* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U, -#define joining_offset_0x1e900u 1355 +#define joining_offset_0x1e900u 1358 /* Adlam */ @@ -170,7 +176,7 @@ static const uint8_t joining_table[] = /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T, -}; /* Table items: 1431; occupancy: 57% */ +}; /* Table items: 1434; occupancy: 57% */ static unsigned int @@ -198,6 +204,7 @@ joining_type (hb_codepoint_t u) if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u]; if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u]; if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u]; + if (hb_in_range<hb_codepoint_t> (u, 0x10EC2u, 0x10EC4u)) return joining_table[u - 0x10EC2u + joining_offset_0x10ec2u]; if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u]; break; diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc index d70746ed2b..4e3b512b48 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc @@ -233,10 +233,7 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ); /* https://github.com/harfbuzz/harfbuzz/issues/1573 */ if (!map->has_feature (HB_TAG('r','c','l','t'))) - { map->add_gsub_pause (nullptr); - map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ); - } map->enable_feature (HB_TAG('l','i','g','a'), F_MANUAL_ZWJ); map->enable_feature (HB_TAG('c','l','i','g'), F_MANUAL_ZWJ); diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc index e18edd6b3f..7e5482a96c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc @@ -78,7 +78,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, return found; #endif - if (!found && !c->plan->has_gpos_mark) + if (!found && (c->plan && !c->plan->has_gpos_mark)) { /* Special-case Hebrew presentation forms that are excluded from * standard normalization, but wanted for old fonts. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc index d9899a633c..adea32efda 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc @@ -6,12 +6,12 @@ * * on files with these headers: * - * # IndicSyllabicCategory-15.1.0.txt - * # Date: 2023-01-05 - * # IndicPositionalCategory-15.1.0.txt - * # Date: 2023-01-05 - * # Blocks-15.1.0.txt - * # Date: 2023-07-28, 15:47:20 GMT + * # IndicSyllabicCategory-16.0.0.txt + * # Date: 2024-04-30, 21:48:21 GMT + * # IndicPositionalCategory-16.0.0.txt + * # Date: 2024-04-30, 21:48:21 GMT + * # Blocks-16.0.0.txt + * # Date: 2024-02-02 */ #include "hb.hh" @@ -89,7 +89,7 @@ static_assert (OT_VPst == M_Cat(VPst), ""); #define _OT_MW OT_MW /* 2 chars; MW */ #define _OT_MY OT_MY /* 3 chars; MY */ #define _OT_N OT_N /* 17 chars; N */ -#define _OT_GB OT_PLACEHOLDER /* 165 chars; PLACEHOLDER */ +#define _OT_GB OT_PLACEHOLDER /* 185 chars; PLACEHOLDER */ #define _OT_PT OT_PT /* 8 chars; PT */ #define _OT_R OT_Ra /* 14 chars; Ra */ #define _OT_Rf OT_Repha /* 1 chars; Repha */ @@ -112,7 +112,7 @@ static_assert (OT_VPst == M_Cat(VPst), ""); #define _POS_A POS_AFTER_MAIN /* 3 chars; AFTER_MAIN */ #define _POS_AP POS_AFTER_POST /* 50 chars; AFTER_POST */ #define _POS_AS POS_AFTER_SUB /* 51 chars; AFTER_SUB */ -#define _POS_C POS_BASE_C /* 833 chars; BASE_C */ +#define _POS_C POS_BASE_C /* 853 chars; BASE_C */ #define _POS_BS POS_BEFORE_SUB /* 25 chars; BEFORE_SUB */ #define _POS_B POS_BELOW_C /* 13 chars; BELOW_C */ #define _POS_X POS_END /* 71 chars; END */ @@ -458,7 +458,16 @@ static const uint16_t indic_table[] = { /* 11338 */ _(X,X), _(X,X), _(X,X), _(N,X), _(N,X), _(X,X), _(X,X), _(X,X), -}; /* Table items: 1728; occupancy: 71% */ +#define indic_offset_0x116d0u 1728 + + + /* Myanmar Extended-C */ + + /* 116D0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), + /* 116D8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), + /* 116E0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), + +}; /* Table items: 1752; occupancy: 71% */ uint16_t hb_indic_get_categories (hb_codepoint_t u) @@ -498,6 +507,7 @@ hb_indic_get_categories (hb_codepoint_t u) case 0x11u: if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x11307u)) return indic_table[u - 0x11300u + indic_offset_0x11300u]; if (hb_in_range<hb_codepoint_t> (u, 0x11338u, 0x1133Fu)) return indic_table[u - 0x11338u + indic_offset_0x11338u]; + if (hb_in_range<hb_codepoint_t> (u, 0x116D0u, 0x116E7u)) return indic_table[u - 0x116D0u + indic_offset_0x116d0u]; break; default: diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh index d581b65c07..e8218834e7 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh @@ -6,18 +6,18 @@ * * on files with these headers: * - * # IndicSyllabicCategory-15.1.0.txt - * # Date: 2023-01-05 - * # IndicPositionalCategory-15.1.0.txt - * # Date: 2023-01-05 - * # ArabicShaping-15.1.0.txt - * # Date: 2023-01-05 - * # DerivedCoreProperties-15.1.0.txt - * # Date: 2023-08-07, 15:21:24 GMT - * # Blocks-15.1.0.txt - * # Date: 2023-07-28, 15:47:20 GMT - * # Scripts-15.1.0.txt - * # Date: 2023-07-28, 16:01:07 GMT + * # IndicSyllabicCategory-16.0.0.txt + * # Date: 2024-04-30, 21:48:21 GMT + * # IndicPositionalCategory-16.0.0.txt + * # Date: 2024-04-30, 21:48:21 GMT + * # ArabicShaping-16.0.0.txt + * # Date: 2024-07-30 + * # DerivedCoreProperties-16.0.0.txt + * # Date: 2024-05-31, 18:09:32 GMT + * # Blocks-16.0.0.txt + * # Date: 2024-02-02 + * # Scripts-16.0.0.txt + * # Date: 2024-04-30, 21:48:40 GMT * # Override values For Indic_Syllabic_Category * # Not derivable * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17 @@ -27,6 +27,7 @@ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25 * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16 * # Updated for Unicode 15.1 by Andrew Glass 2023-09-14 + * # Updated for Unicode 16.0 by Andrew Glass 2024-09-11 * # Override values For Indic_Positional_Category * # Not derivable * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17 @@ -38,6 +39,7 @@ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28 * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16 * # Updated for Unicode 15.1 by Andrew Glass 2023-09-14 + * # Updated for Unicode 16.0 by Andrew Glass 2024-09-11 * UnicodeData.txt does not have a header. */ @@ -99,16 +101,16 @@ #ifndef HB_OPTIMIZE_SIZE static const uint8_t -hb_use_u8[3187] = +hb_use_u8[3343] = { - 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61, + 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 57, 58, 59, 195, 211, 62, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 14, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2, + 15, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2, 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 17, 18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 33, 2, 2, 2, @@ -121,24 +123,26 @@ hb_use_u8[3187] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 48, 2, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 51, 2, 2, 2, - 2, 2, 2, 2, 2, 52, 53, 2, 54, 2, 2, 55, 2, 2, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 2, 66, 67, 2, 68, 69, 70, 71, - 2, 72, 2, 73, 74, 75, 76, 2, 2, 77, 78, 79, 80, 2, 81, 82, - 2, 83, 83, 83, 83, 83, 83, 83, 83, 84, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 52, 53, 2, 54, 2, 2, 55, 56, 2, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 2, 70, 71, 72, 73, + 2, 74, 2, 75, 76, 77, 78, 2, 2, 79, 80, 81, 82, 2, 83, 84, + 2, 85, 85, 85, 85, 85, 85, 85, 85, 86, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 87, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 88, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 89, 90, 2, 2, 2, 91, 2, 2, 2, 92, + 93, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 94, 94, 94, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 85, 86, 2, 2, 2, 2, 2, 2, 2, 87, - 88, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 89, 89, 89, 90, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 97, 2, 2, 2, 2, 2, + 2, 2, 2, 98, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 92, 2, 2, 2, 2, 2, - 2, 2, 2, 93, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 94, 2, 2, 95, 2, 2, 2, 96, 2, 2, 2, 2, 2, - 2, 2, 2, 97, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 98, 98, 99, 100, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 2, 2, 2, 99, 2, 2, 100, 2, 2, 2, 101, 2, 102, 2, 2, 2, + 2, 2, 2, 103, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 104, 104, 105, 106, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -167,7 +171,7 @@ hb_use_u8[3187] = 0, 0, 0, 27, 31, 2, 9, 0, 0, 10, 29, 30, 2, 2, 2, 9, 2, 2, 2, 30, 2, 2, 0, 17, 45, 0, 0, 35, 47, 0, 0, 0, 9, 50, 51, 0, 0, 0, 0, 0, 0, 11, 29, 2, 2, 2, 2, 9, - 2, 2, 2, 2, 2, 2, 52, 53, 23, 23, 19, 31, 48, 33, 48, 34, + 2, 2, 2, 2, 2, 2, 52, 53, 23, 19, 20, 31, 48, 33, 48, 34, 54, 0, 0, 0, 35, 0, 0, 0, 30, 12, 29, 30, 2, 2, 2, 2, 2, 2, 2, 2, 9, 0, 2, 2, 2, 2, 30, 2, 2, 2, 2, 30, 0, 2, 2, 2, 9, 0, 55, 0, 35, 23, 22, 31, 31, 18, 48, 48, @@ -195,88 +199,95 @@ hb_use_u8[3187] = 0, 2, 2, 100, 101, 102, 103, 61, 63, 104, 16, 45, 22, 59, 21, 80, 48, 48, 76, 11, 11, 11, 105, 46, 40, 11, 106, 74, 2, 2, 2, 2, 2, 2, 2, 107, 22, 20, 20, 22, 48, 48, 22, 108, 2, 2, 2, 9, - 0, 0, 0, 0, 0, 0, 109, 110, 111, 111, 111, 0, 0, 0, 0, 0, - 0, 106, 74, 2, 2, 2, 2, 2, 2, 60, 61, 59, 25, 22, 112, 61, + 0, 0, 0, 0, 0, 0, 109, 110, 110, 110, 110, 0, 0, 0, 0, 0, + 0, 106, 74, 2, 2, 2, 2, 2, 2, 60, 61, 59, 25, 22, 111, 61, 2, 2, 2, 2, 107, 22, 23, 45, 45, 102, 14, 0, 0, 0, 0, 0, - 0, 2, 2, 61, 18, 48, 23, 113, 102, 102, 102, 114, 115, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 0, 30, 2, 11, 46, 116, 116, 116, 11, 116, - 116, 15, 116, 116, 116, 26, 0, 40, 0, 0, 0, 117, 51, 11, 5, 0, - 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 6, 119, - 120, 42, 42, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 120, - 121, 120, 120, 120, 120, 120, 120, 120, 120, 0, 0, 122, 0, 0, 0, 0, - 0, 0, 7, 122, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 123, 123, 0, 0, + 0, 2, 2, 61, 18, 48, 23, 112, 102, 102, 102, 113, 114, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 0, 30, 2, 11, 46, 115, 115, 115, 11, 115, + 115, 15, 115, 115, 115, 26, 0, 40, 0, 0, 0, 116, 51, 11, 5, 0, + 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, 6, 118, + 119, 42, 42, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 119, + 120, 119, 119, 119, 119, 119, 119, 119, 119, 0, 0, 121, 0, 0, 0, 0, + 0, 0, 7, 121, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 122, 122, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, - 124, 0, 123, 123, 0, 0, 0, 0, 0, 2, 53, 2, 108, 2, 10, 2, + 123, 0, 122, 122, 0, 0, 0, 0, 0, 2, 53, 2, 108, 2, 10, 2, 2, 2, 65, 19, 16, 0, 0, 31, 0, 2, 2, 0, 0, 0, 0, 0, - 0, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 23, 23, 23, 23, - 23, 23, 23, 126, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 2, 0, 0, 0, 0, 0, 52, 2, 2, 2, 22, 22, 127, 116, - 0, 2, 2, 2, 128, 20, 59, 20, 113, 102, 129, 0, 0, 0, 0, 0, - 0, 11, 130, 2, 2, 2, 2, 2, 2, 2, 131, 23, 22, 20, 48, 132, - 133, 134, 0, 0, 0, 0, 0, 0, 0, 2, 2, 52, 30, 2, 2, 2, - 2, 2, 2, 2, 2, 10, 22, 59, 99, 76, 135, 136, 137, 0, 0, 0, - 0, 2, 138, 2, 2, 2, 2, 139, 0, 30, 2, 42, 5, 0, 79, 15, - 2, 53, 22, 140, 52, 53, 2, 2, 105, 10, 9, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 141, 21, 25, 0, 0, 142, 143, 0, 0, 0, - 0, 2, 65, 45, 23, 80, 47, 144, 0, 81, 81, 81, 81, 81, 81, 81, - 81, 0, 0, 0, 0, 0, 0, 0, 6, 120, 120, 120, 120, 121, 0, 0, + 0, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 124, 23, 23, 23, 23, + 23, 23, 23, 125, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 2, 0, 0, 0, 0, 0, 52, 2, 2, 2, 22, 22, 126, 115, + 0, 2, 2, 2, 127, 20, 59, 20, 112, 102, 128, 0, 0, 0, 0, 0, + 0, 11, 129, 2, 2, 2, 2, 2, 2, 2, 130, 23, 22, 20, 48, 131, + 132, 133, 0, 0, 0, 0, 0, 0, 0, 2, 2, 52, 30, 2, 2, 2, + 2, 2, 2, 2, 2, 10, 22, 59, 99, 76, 134, 135, 136, 0, 0, 0, + 0, 2, 137, 2, 2, 2, 2, 138, 0, 30, 2, 42, 5, 0, 79, 15, + 2, 53, 22, 139, 52, 53, 2, 2, 105, 10, 9, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 140, 21, 25, 0, 0, 141, 142, 0, 0, 0, + 0, 2, 65, 45, 23, 80, 47, 143, 0, 81, 81, 81, 81, 81, 81, 81, + 81, 0, 0, 0, 0, 0, 0, 0, 6, 119, 119, 119, 119, 120, 0, 0, 0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 30, 2, 2, 2, - 2, 2, 30, 2, 2, 2, 30, 9, 0, 128, 20, 27, 31, 0, 0, 145, - 146, 2, 2, 30, 2, 30, 2, 2, 2, 2, 2, 2, 0, 14, 37, 0, - 147, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 2, 2, 30, 2, 2, 2, 30, 9, 0, 127, 20, 27, 31, 0, 0, 144, + 145, 2, 2, 30, 2, 30, 2, 2, 2, 2, 2, 2, 0, 14, 37, 0, + 146, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 2, 2, 9, 2, 2, 11, 41, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 27, 38, 0, 2, 2, 2, 116, 116, 116, 116, - 116, 148, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 27, 22, 22, 30, 2, 2, 2, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 27, 38, 0, 2, 2, 2, 115, 115, 115, 115, + 115, 147, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0, 0, 9, 2, 2, 9, 2, 2, 2, 2, 30, 2, 9, 0, 30, 2, 0, - 0, 149, 150, 151, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 20, - 20, 20, 22, 22, 134, 0, 0, 0, 0, 0, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 152, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0, - 153, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0, + 0, 148, 149, 150, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 20, + 20, 20, 22, 22, 133, 0, 0, 0, 0, 0, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0, + 152, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 11, 49, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 128, 20, 22, 154, 22, 21, 155, 156, 2, 2, 2, 2, - 2, 0, 0, 65, 157, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0, - 0, 2, 65, 25, 20, 20, 20, 22, 22, 108, 158, 0, 0, 56, 159, 31, - 160, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23, - 19, 22, 22, 161, 44, 0, 0, 0, 49, 128, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 127, 20, 22, 153, 22, 21, 154, 155, 2, 2, 2, 2, + 2, 0, 0, 65, 156, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0, + 0, 2, 65, 25, 20, 20, 20, 22, 22, 108, 157, 0, 0, 56, 158, 31, + 159, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23, + 19, 22, 22, 160, 44, 0, 0, 0, 49, 127, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 9, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, - 30, 2, 2, 2, 2, 2, 2, 2, 10, 18, 19, 21, 22, 162, 31, 0, + 30, 2, 2, 2, 2, 2, 2, 2, 10, 18, 19, 21, 22, 161, 31, 0, 0, 11, 11, 30, 2, 2, 2, 9, 30, 9, 2, 30, 2, 2, 58, 17, 23, 16, 23, 47, 32, 33, 32, 34, 0, 0, 0, 0, 35, 0, 0, 0, 2, 2, 23, 0, 11, 11, 11, 46, 0, 11, 11, 46, 0, 0, 0, 0, - 0, 2, 2, 65, 25, 20, 20, 20, 22, 23, 126, 15, 17, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 0, 0, 163, 164, 0, 0, 0, 0, 0, 0, - 0, 18, 19, 20, 20, 66, 99, 25, 160, 11, 165, 9, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 2, 2, 65, 25, 20, 20, 0, 48, 48, 11, - 166, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 20, - 0, 23, 19, 20, 20, 21, 16, 82, 166, 38, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 10, 167, 25, 20, 22, 22, 165, 9, 0, 0, - 0, 2, 2, 2, 2, 2, 9, 43, 136, 23, 22, 20, 76, 21, 22, 0, - 0, 2, 2, 2, 9, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 18, - 19, 20, 21, 22, 105, 166, 37, 0, 0, 2, 2, 2, 9, 30, 0, 2, - 2, 2, 2, 30, 9, 2, 2, 2, 2, 23, 23, 18, 32, 33, 12, 168, - 169, 170, 171, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, - 2, 65, 25, 20, 20, 0, 22, 23, 29, 108, 0, 33, 0, 0, 0, 0, - 0, 52, 20, 22, 22, 22, 140, 2, 2, 2, 172, 173, 11, 15, 174, 72, - 175, 0, 0, 1, 147, 0, 0, 0, 0, 52, 20, 22, 16, 19, 20, 2, - 2, 2, 2, 158, 158, 158, 176, 176, 176, 176, 176, 176, 15, 177, 0, 30, - 0, 22, 20, 20, 31, 22, 22, 11, 166, 0, 61, 61, 61, 61, 61, 61, - 61, 66, 21, 82, 46, 0, 0, 0, 0, 2, 2, 2, 9, 2, 30, 2, - 2, 52, 22, 22, 31, 0, 38, 22, 27, 11, 159, 178, 174, 0, 0, 0, - 0, 2, 2, 2, 30, 9, 2, 2, 2, 2, 2, 2, 2, 2, 23, 23, - 47, 22, 35, 82, 68, 0, 0, 0, 0, 2, 179, 66, 47, 0, 0, 0, - 0, 11, 180, 2, 2, 2, 2, 2, 2, 2, 2, 23, 22, 20, 31, 0, - 48, 16, 143, 0, 0, 0, 0, 0, 0, 181, 181, 181, 181, 181, 181, 181, - 181, 182, 182, 182, 183, 184, 182, 181, 181, 185, 181, 181, 186, 187, 187, 187, - 187, 187, 187, 187, 0, 0, 0, 0, 0, 11, 11, 11, 46, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 9, 0, 58, 188, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, - 40, 116, 26, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 58, - 37, 0, 6, 120, 120, 120, 121, 0, 0, 11, 11, 11, 49, 2, 2, 2, - 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 46, 2, 2, 2, 2, 2, 2, 11, 11, 2, 2, 2, 2, 2, 2, 22, - 22, 2, 2, 44, 44, 44, 92, 0, 0, O, O, O, GB, B, B, O, + 0, 2, 2, 2, 2, 2, 30, 0, 9, 2, 2, 2, 30, 45, 59, 20, + 20, 31, 33, 32, 32, 25, 162, 29, 163, 164, 37, 0, 0, 0, 0, 0, + 0, 12, 26, 0, 0, 0, 0, 0, 0, 2, 2, 65, 25, 20, 20, 20, + 22, 23, 125, 15, 17, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, + 165, 166, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25, + 159, 11, 167, 9, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 65, 25, 20, 20, 0, 48, 48, 11, 168, 37, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 20, 0, 23, 19, 20, 20, 21, 16, 82, + 168, 38, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 10, 169, + 25, 20, 22, 22, 167, 9, 0, 0, 0, 2, 2, 2, 2, 2, 9, 43, + 135, 23, 22, 20, 76, 21, 22, 0, 0, 2, 2, 2, 9, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 18, 19, 20, 21, 22, 105, 168, 37, 0, + 0, 2, 2, 2, 9, 30, 0, 2, 2, 2, 2, 30, 9, 2, 2, 2, + 2, 23, 23, 18, 32, 33, 12, 170, 164, 171, 172, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 0, 2, 2, 2, 65, 25, 20, 20, 0, 22, 23, + 29, 108, 0, 33, 0, 0, 0, 0, 0, 52, 20, 22, 22, 22, 139, 2, + 2, 2, 173, 174, 11, 15, 175, 61, 176, 0, 0, 1, 146, 0, 0, 0, + 0, 52, 20, 22, 16, 19, 20, 2, 2, 2, 2, 157, 157, 157, 177, 177, + 177, 177, 177, 177, 15, 178, 0, 30, 0, 22, 20, 20, 31, 22, 22, 11, + 168, 0, 61, 61, 61, 61, 61, 61, 61, 66, 21, 82, 46, 0, 0, 0, + 0, 2, 2, 2, 9, 2, 30, 2, 2, 52, 22, 22, 31, 0, 38, 22, + 27, 11, 158, 179, 180, 0, 0, 0, 0, 2, 2, 2, 30, 9, 2, 2, + 2, 2, 2, 2, 2, 2, 23, 23, 47, 22, 35, 82, 68, 0, 0, 0, + 0, 2, 181, 66, 47, 0, 0, 0, 0, 11, 182, 2, 2, 2, 2, 2, + 2, 2, 2, 23, 22, 20, 31, 0, 48, 16, 142, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 155, 0, 0, 183, 183, 183, 183, 183, 183, 183, + 183, 184, 184, 184, 185, 186, 184, 183, 183, 187, 183, 183, 188, 189, 189, 189, + 189, 189, 189, 189, 0, 0, 0, 0, 0, 183, 183, 183, 183, 183, 190, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 191, 192, + 193, 11, 11, 11, 46, 0, 0, 0, 0, 29, 74, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 65, 47, 0, 2, 2, 2, 2, 2, 9, 0, + 58, 194, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 0, 0, 0, 40, 115, 26, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 30, 2, 2, 2, 2, 2, 0, 58, 37, 0, 6, 119, 119, 119, 120, 0, + 0, 11, 11, 11, 49, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 46, 2, 2, 2, 2, 2, 2, 11, + 11, 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, + 20, 2, 2, 44, 44, 44, 92, 0, 0, O, O, O, GB, B, B, O, SB, O, SE, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B, O, B,VMAbv,VMAbv, VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, VPst,VMBlw, O, O, @@ -290,20 +301,20 @@ hb_use_u8[3187] = FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB, CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, - VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv, - CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, SB, - SE, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B, - CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, - FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, - IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, - IS,CMAbv, O, VPst, B, R, R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, - B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, IS, R, MPst, R, MPst, - CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, - VAbv, R,VMPst, G, G, J, J, J, SB, SE, J, HR, G, G, HM, HM, - HM, O, VBlw, + VPst, H, B, O,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw, + VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, SB, SE, O, + H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, + MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, + B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, + B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, + O, VPst, B, R, R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,VMPst, O,VMAbv, + CMBlw, IS, R,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, MPst, + R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv, IS, VBlw, + IS, R, MBlw, GB, VAbv, R,VMPst, G, G, J, J, J, SB, SE, J, HR, + G, G, HM, HM, HM, G, O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O, VBlw, }; static const uint16_t -hb_use_u16[808] = +hb_use_u16[856] = { 0, 0, 1, 2, 0, 3, 0, 3, 0, 0, 4, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, @@ -332,28 +343,31 @@ hb_use_u16[808] = 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0,166,166,167, 34,168, 0, 0, 0, 0, 169,170, 10,171, 95, 0, 0, 0, 0, 0, 0, 0, 70, 10,172, 0, - 10,173,174, 0, 0, 0, 0, 0, 10, 10,175, 2, 0, 0, 0, 0, - 10, 10,176,173, 0, 0, 0, 0, 0, 0, 0, 10,177,178, 0, 10, - 179, 0, 0,180,181, 0, 0, 0,182, 10, 10,183,184,185,186,187, - 188, 10, 10,189,190, 0, 0, 0,191, 10,192,193,194, 10, 10,195, - 188, 10, 10,196,197,106,198,103, 10, 34,199,200,201, 0, 0, 0, - 202,203, 95, 10, 10,204,205, 2,206, 21, 22,207,208,209,210,211, - 10, 10, 10,212,213,214,215, 0,198, 10, 10,216,217, 2, 0, 0, - 10, 10,218,219,220,221, 0, 0, 10, 10, 10,222,223, 2, 0, 0, - 10, 10,224,225, 2, 0, 0, 0, 10,226,227,104,228, 0, 0, 0, - 10, 10,229,230, 0, 0, 0, 0,231,232, 10,233,234, 2, 0, 0, - 0, 0,235, 10, 10,236,237, 0,238, 10, 10,239,240,241, 10, 10, - 242,243, 0, 0, 0, 0, 0, 0, 22, 10,218,244, 8, 10, 71, 19, - 10,245, 74,246, 0, 0, 0, 0,247, 10, 10,248,249, 2,250, 10, - 251,252, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,253, - 254, 49, 10,255,256, 2, 0, 0,257,257,257,257,257,257,257,257, - 257,257,257,258,259,260, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 10, 10, 10,261, 0, 0, 0, 0, 10, 10, 10, 10,262,263,264,264, - 265,266, 0, 0, 0, 0,267, 0, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10,268, 0, 0, 10, 10, 10, 10, 10, 10,106, 71, - 95,269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,270, - 10, 10, 71,271,272, 0, 0, 0, 0, 10,273, 0, 10, 10,274, 2, - 0, 0, 0, 0, 0, 10,275, 2, 10, 10, 10, 10,276, 2, 0, 0, + 10,173,174, 0, 0, 0, 0, 0, 10, 10,175, 2, 9, 10,176, 10, + 177, 0, 0, 0, 0, 0, 0, 0, 10, 10,178,173, 0, 0, 0, 0, + 0, 0, 0, 10,179,180, 0, 10,181, 0, 0,182,183, 0, 0, 0, + 184, 10, 10,185,186,187,188,189,190, 10, 10,191,192, 0, 0, 0, + 193, 10,194,195,196, 10, 10,197,190, 10, 10,198,199,106,200,103, + 10, 34,201,202,203, 0, 0, 0,204,205, 95, 10, 10,206,207, 2, + 208, 21, 22,209,210,211,212,213,214, 10, 10,215,216,217,218, 0, + 10, 10, 10,219,220,221,222, 0,200, 10, 10,223,224, 2, 0, 0, + 10, 10,225,226,227,228, 0, 0, 10, 10, 10,229,230, 2, 0, 0, + 10, 10,231,232, 2, 10,141, 0, 10,233,234,104,235, 0, 0, 0, + 10, 10,236,237, 0, 0, 0, 0,238,239, 10,240,241, 2, 0, 0, + 0, 0,242, 10, 10,243,244, 0,245, 10, 10,246,247,248, 10, 10, + 249,250, 0, 0, 0, 0, 0, 0, 22, 10,225,251, 8, 10, 71, 19, + 10,252, 74,253, 0, 0, 0, 0,254, 10, 10,255,256, 2,257, 10, + 258,259, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,260, + 261, 49, 10,262,263,264, 0, 0,265,265,265,265,265,265,265,265, + 265,265,265,266,267,268,265,265,265,265,265,265,265,265,265,269, + 10,270,271, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 10, 10, 10,272, 0, 0, 0, 0, 0, 0, 0, 0,273, 10,274, 2, + 10, 10, 10, 10,275,276,277,277,278,279, 0, 0, 0, 0,280, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,177, 0,281, + 10, 10, 10, 10, 10, 10,106, 71, 95,282, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,283, 10, 10, 71,284,285, 0, 0, 0, + 0, 10,286, 0, 10, 10,287, 2, 0, 0, 0, 0, 0, 10,288, 2, + 0, 0, 0, 0, 0, 10,289,106, 10, 10, 10, 10,290, 2, 0, 0, 130,130,130,130,130,130,130,130,163,163,163,163,163,163,163,163, 163,163,163,163,163,163,163,130, }; @@ -366,23 +380,23 @@ hb_use_b4 (const uint8_t* a, unsigned i) static inline uint_fast8_t hb_use_get_category (unsigned u) { - return u<921600u?hb_use_u8[2809+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; + return u<921600u?hb_use_u8[2953+(((hb_use_u8[625+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; } #else static const uint8_t -hb_use_u8[3483] = +hb_use_u8[3655] = { - 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61, + 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 57, 58, 59, 195, 211, 62, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 14, 0, 1, 1, 2, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 1, + 15, 0, 1, 1, 2, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 1, 11, 12, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, 19, 1, 1, 20, 1, 1, 1, 1, 21, 1, 22, 1, 1, 1, 1, 1, 23, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -390,14 +404,15 @@ hb_use_u8[3483] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 30, 1, 1, 1, 1, 1, 31, 1, 1, 1, 1, 32, 33, 1, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 1, 48, 49, 50, - 51, 52, 52, 52, 52, 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 54, 55, 1, 1, 1, - 56, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 57, 58, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 59, 1, 1, - 1, 1, 60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 61, 62, 1, 63, 1, 1, 1, 1, 64, 1, 1, 1, 1, 1, - 1, 65, 66, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 0, 1, 2, 2, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 51, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 55, 1, 1, 1, 1, 1, 1, 1, 1, 56, 57, 1, 58, 1, + 59, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 60, 61, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 1, + 1, 1, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 64, 65, 1, 66, 67, 1, 1, 1, 68, 1, 1, 1, 1, 1, + 1, 69, 70, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 0, 1, 2, 2, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 9, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, @@ -414,23 +429,25 @@ hb_use_u8[3483] = 122, 0, 0, 0, 0, 0, 0, 56, 123, 124, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 127, 128, 129, 0, 0, 130, 131, 132, 0, 0, 0, 51, 133, 0, 0, 0, 0, 134, 135, 0, - 0, 56, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 137, 0, - 0, 0, 101, 138, 101, 139, 140, 141, 0, 142, 143, 144, 145, 146, 147, 148, - 0, 149, 150, 151, 152, 146, 153, 154, 155, 156, 157, 158, 0, 159, 160, 161, - 162, 163, 164, 165, 166, 0, 0, 0, 0, 56, 167, 168, 169, 170, 171, 172, - 0, 0, 0, 0, 0, 56, 173, 174, 0, 56, 175, 176, 0, 56, 177, 67, - 0, 178, 179, 180, 0, 0, 0, 0, 0, 56, 181, 0, 0, 0, 0, 0, - 0, 182, 183, 184, 0, 0, 185, 186, 187, 188, 189, 190, 56, 191, 0, 0, - 0, 192, 193, 194, 195, 196, 197, 0, 0, 198, 199, 200, 201, 202, 67, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 203, 204, 205, 206, 0, 0, 0, 0, - 0, 207, 207, 207, 207, 207, 207, 207, 207, 207, 208, 209, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 67, 0, 56, 210, 0, 0, 0, 0, 0, - 0, 56, 56, 211, 212, 213, 0, 0, 214, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 215, 0, 56, 56, 56, 216, 217, 0, 0, - 0, 0, 0, 0, 218, 0, 0, 0, 0, 56, 219, 220, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 101, 221, 56, 222, 0, 0, 0, 0, 0, 0, 101, - 223, 56, 56, 224, 0, 0, 0, 0, 0, 225, 225, 225, 225, 225, 225, 225, - 225, 226, 226, 226, 226, 226, 226, 226, 227, 0, 0, 0, 0, 0, 0, 0, + 0, 56, 136, 7, 137, 138, 0, 0, 0, 0, 0, 0, 0, 56, 139, 0, + 0, 0, 101, 140, 101, 141, 142, 143, 0, 144, 145, 146, 147, 148, 149, 150, + 0, 151, 152, 153, 154, 148, 155, 156, 157, 158, 159, 160, 0, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 56, 173, 174, 175, 176, 177, 178, + 0, 0, 0, 0, 0, 56, 179, 180, 0, 56, 181, 182, 0, 56, 183, 184, + 185, 186, 187, 188, 0, 0, 0, 0, 0, 56, 189, 0, 0, 0, 0, 0, + 0, 190, 191, 192, 0, 0, 193, 194, 195, 196, 197, 198, 56, 199, 0, 0, + 0, 200, 201, 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, 210, 67, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 211, 212, 213, 214, 0, 0, 0, 0, + 0, 215, 215, 215, 215, 215, 215, 215, 215, 215, 216, 217, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 218, 219, 220, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 67, 0, 56, 221, 0, 0, 0, 0, 0, + 0, 0, 0, 222, 223, 0, 0, 0, 0, 56, 56, 224, 225, 226, 0, 0, + 227, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 228, + 229, 56, 56, 56, 230, 231, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, + 0, 56, 233, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 235, 56, + 236, 0, 0, 0, 0, 0, 0, 101, 237, 0, 0, 0, 0, 0, 0, 101, + 238, 56, 56, 239, 0, 0, 0, 0, 0, 240, 240, 240, 240, 240, 240, 240, + 240, 241, 241, 241, 241, 241, 241, 241, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -460,7 +477,7 @@ hb_use_u8[3483] = 0, 10, 29, 30, 2, 2, 2, 9, 2, 2, 2, 30, 2, 2, 0, 17, 45, 0, 0, 35, 47, 0, 0, 0, 9, 50, 51, 0, 0, 0, 0, 0, 0, 11, 29, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 52, 53, - 23, 23, 19, 31, 48, 33, 48, 34, 54, 0, 0, 0, 35, 0, 0, 0, + 23, 19, 20, 31, 48, 33, 48, 34, 54, 0, 0, 0, 35, 0, 0, 0, 30, 12, 29, 30, 2, 2, 2, 2, 2, 2, 2, 2, 9, 0, 2, 2, 2, 2, 30, 2, 2, 2, 2, 30, 0, 2, 2, 2, 9, 0, 55, 0, 35, 23, 22, 31, 31, 18, 48, 48, 25, 0, 23, 0, 0, 0, 0, 0, @@ -488,87 +505,94 @@ hb_use_u8[3483] = 63, 104, 16, 45, 22, 59, 21, 80, 48, 48, 76, 11, 11, 11, 105, 46, 40, 11, 106, 74, 2, 2, 2, 2, 2, 2, 2, 107, 22, 20, 20, 22, 48, 48, 22, 108, 2, 2, 2, 9, 0, 0, 0, 0, 0, 0, 109, 110, - 111, 111, 111, 0, 0, 0, 0, 0, 0, 106, 74, 2, 2, 2, 2, 2, - 2, 60, 61, 59, 25, 22, 112, 61, 2, 2, 2, 2, 107, 22, 23, 45, - 45, 102, 14, 0, 0, 0, 0, 0, 0, 2, 2, 61, 18, 48, 23, 113, - 102, 102, 102, 114, 115, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 30, - 2, 11, 46, 116, 116, 116, 11, 116, 116, 15, 116, 116, 116, 26, 0, 40, - 0, 0, 0, 117, 51, 11, 5, 0, 0, 0, 0, 0, 0, 0, 118, 0, - 0, 0, 0, 0, 0, 0, 6, 119, 120, 42, 42, 5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 120, 120, 121, 120, 120, 120, 120, 120, 120, 120, - 120, 0, 0, 122, 0, 0, 0, 0, 0, 0, 7, 122, 0, 0, 0, 0, + 110, 110, 110, 0, 0, 0, 0, 0, 0, 106, 74, 2, 2, 2, 2, 2, + 2, 60, 61, 59, 25, 22, 111, 61, 2, 2, 2, 2, 107, 22, 23, 45, + 45, 102, 14, 0, 0, 0, 0, 0, 0, 2, 2, 61, 18, 48, 23, 112, + 102, 102, 102, 113, 114, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 30, + 2, 11, 46, 115, 115, 115, 11, 115, 115, 15, 115, 115, 115, 26, 0, 40, + 0, 0, 0, 116, 51, 11, 5, 0, 0, 0, 0, 0, 0, 0, 117, 0, + 0, 0, 0, 0, 0, 0, 6, 118, 119, 42, 42, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 119, 120, 119, 119, 119, 119, 119, 119, 119, + 119, 0, 0, 121, 0, 0, 0, 0, 0, 0, 7, 121, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, - 0, 0, 0, 0, 123, 123, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, - 30, 0, 0, 0, 0, 0, 0, 0, 124, 0, 123, 123, 0, 0, 0, 0, + 0, 0, 0, 0, 122, 122, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, + 30, 0, 0, 0, 0, 0, 0, 0, 123, 0, 122, 122, 0, 0, 0, 0, 0, 2, 53, 2, 108, 2, 10, 2, 2, 2, 65, 19, 16, 0, 0, 31, 0, 2, 2, 0, 0, 0, 0, 0, 0, 29, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 125, 23, 23, 23, 23, 23, 23, 23, 126, 0, 0, 0, 0, + 2, 2, 2, 124, 23, 23, 23, 23, 23, 23, 23, 125, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 0, 0, 0, 0, 0, - 52, 2, 2, 2, 22, 22, 127, 116, 0, 2, 2, 2, 128, 20, 59, 20, - 113, 102, 129, 0, 0, 0, 0, 0, 0, 11, 130, 2, 2, 2, 2, 2, - 2, 2, 131, 23, 22, 20, 48, 132, 133, 134, 0, 0, 0, 0, 0, 0, + 52, 2, 2, 2, 22, 22, 126, 115, 0, 2, 2, 2, 127, 20, 59, 20, + 112, 102, 128, 0, 0, 0, 0, 0, 0, 11, 129, 2, 2, 2, 2, 2, + 2, 2, 130, 23, 22, 20, 48, 131, 132, 133, 0, 0, 0, 0, 0, 0, 0, 2, 2, 52, 30, 2, 2, 2, 2, 2, 2, 2, 2, 10, 22, 59, - 99, 76, 135, 136, 137, 0, 0, 0, 0, 2, 138, 2, 2, 2, 2, 139, - 0, 30, 2, 42, 5, 0, 79, 15, 2, 53, 22, 140, 52, 53, 2, 2, - 105, 10, 9, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 141, 21, - 25, 0, 0, 142, 143, 0, 0, 0, 0, 2, 65, 45, 23, 80, 47, 144, + 99, 76, 134, 135, 136, 0, 0, 0, 0, 2, 137, 2, 2, 2, 2, 138, + 0, 30, 2, 42, 5, 0, 79, 15, 2, 53, 22, 139, 52, 53, 2, 2, + 105, 10, 9, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 140, 21, + 25, 0, 0, 141, 142, 0, 0, 0, 0, 2, 65, 45, 23, 80, 47, 143, 0, 81, 81, 81, 81, 81, 81, 81, 81, 0, 0, 0, 0, 0, 0, 0, - 6, 120, 120, 120, 120, 121, 0, 0, 0, 2, 2, 2, 2, 2, 9, 2, + 6, 119, 119, 119, 119, 120, 0, 0, 0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 30, 2, 2, 2, 2, 2, 30, 2, 2, 2, 30, 9, - 0, 128, 20, 27, 31, 0, 0, 145, 146, 2, 2, 30, 2, 30, 2, 2, - 2, 2, 2, 2, 0, 14, 37, 0, 147, 2, 2, 13, 37, 0, 30, 2, + 0, 127, 20, 27, 31, 0, 0, 144, 145, 2, 2, 30, 2, 30, 2, 2, + 2, 2, 2, 2, 0, 14, 37, 0, 146, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 2, 2, - 9, 2, 2, 11, 41, 0, 0, 0, 0, 2, 2, 2, 2, 2, 27, 38, - 0, 2, 2, 2, 116, 116, 116, 116, 116, 148, 2, 9, 0, 0, 0, 0, + 9, 2, 2, 11, 41, 0, 0, 0, 0, 2, 2, 2, 0, 27, 22, 22, + 30, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 27, 38, + 0, 2, 2, 2, 115, 115, 115, 115, 115, 147, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0, 0, 9, 2, 2, 9, 2, 2, 2, - 2, 30, 2, 9, 0, 30, 2, 0, 0, 149, 150, 151, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 22, 22, 20, 20, 20, 22, 22, 134, 0, 0, 0, - 0, 0, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 2, 2, 2, 2, - 2, 53, 52, 53, 0, 0, 0, 0, 153, 11, 74, 2, 2, 2, 2, 2, + 2, 30, 2, 9, 0, 30, 2, 0, 0, 148, 149, 150, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 22, 22, 20, 20, 20, 22, 22, 133, 0, 0, 0, + 0, 0, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 2, 2, 2, 2, + 2, 53, 52, 53, 0, 0, 0, 0, 152, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0, 0, 0, 31, 0, 0, 0, 0, 0, - 0, 11, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 20, 22, 154, - 22, 21, 155, 156, 2, 2, 2, 2, 2, 0, 0, 65, 157, 0, 0, 0, + 0, 11, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 127, 20, 22, 153, + 22, 21, 154, 155, 2, 2, 2, 2, 2, 0, 0, 65, 156, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0, 0, 2, 65, 25, 20, 20, 20, 22, - 22, 108, 158, 0, 0, 56, 159, 31, 160, 30, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 23, 19, 22, 22, 161, 44, 0, 0, 0, - 49, 128, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 9, 2, 2, + 22, 108, 157, 0, 0, 56, 158, 31, 159, 30, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 23, 19, 22, 22, 160, 44, 0, 0, 0, + 49, 127, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 9, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, - 10, 18, 19, 21, 22, 162, 31, 0, 0, 11, 11, 30, 2, 2, 2, 9, + 10, 18, 19, 21, 22, 161, 31, 0, 0, 11, 11, 30, 2, 2, 2, 9, 30, 9, 2, 30, 2, 2, 58, 17, 23, 16, 23, 47, 32, 33, 32, 34, 0, 0, 0, 0, 35, 0, 0, 0, 2, 2, 23, 0, 11, 11, 11, 46, - 0, 11, 11, 46, 0, 0, 0, 0, 0, 2, 2, 65, 25, 20, 20, 20, - 22, 23, 126, 15, 17, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, - 163, 164, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25, - 160, 11, 165, 9, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, - 65, 25, 20, 20, 0, 48, 48, 11, 166, 37, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2, 2, 20, 0, 23, 19, 20, 20, 21, 16, 82, - 166, 38, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 10, 167, - 25, 20, 22, 22, 165, 9, 0, 0, 0, 2, 2, 2, 2, 2, 9, 43, - 136, 23, 22, 20, 76, 21, 22, 0, 0, 2, 2, 2, 9, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 2, 18, 19, 20, 21, 22, 105, 166, 37, 0, - 0, 2, 2, 2, 9, 30, 0, 2, 2, 2, 2, 30, 9, 2, 2, 2, - 2, 23, 23, 18, 32, 33, 12, 168, 169, 170, 171, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 0, 2, 2, 2, 65, 25, 20, 20, 0, 22, 23, - 29, 108, 0, 33, 0, 0, 0, 0, 0, 52, 20, 22, 22, 22, 140, 2, - 2, 2, 172, 173, 11, 15, 174, 72, 175, 0, 0, 1, 147, 0, 0, 0, - 0, 52, 20, 22, 16, 19, 20, 2, 2, 2, 2, 158, 158, 158, 176, 176, - 176, 176, 176, 176, 15, 177, 0, 30, 0, 22, 20, 20, 31, 22, 22, 11, - 166, 0, 61, 61, 61, 61, 61, 61, 61, 66, 21, 82, 46, 0, 0, 0, - 0, 2, 2, 2, 9, 2, 30, 2, 2, 52, 22, 22, 31, 0, 38, 22, - 27, 11, 159, 178, 174, 0, 0, 0, 0, 2, 2, 2, 30, 9, 2, 2, - 2, 2, 2, 2, 2, 2, 23, 23, 47, 22, 35, 82, 68, 0, 0, 0, - 0, 2, 179, 66, 47, 0, 0, 0, 0, 11, 180, 2, 2, 2, 2, 2, - 2, 2, 2, 23, 22, 20, 31, 0, 48, 16, 143, 0, 0, 0, 0, 0, - 0, 181, 181, 181, 181, 181, 181, 181, 181, 182, 182, 182, 183, 184, 182, 181, - 181, 185, 181, 181, 186, 187, 187, 187, 187, 187, 187, 187, 0, 0, 0, 0, - 0, 11, 11, 11, 46, 0, 0, 0, 0, 2, 2, 2, 2, 2, 9, 0, - 58, 188, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 0, 0, 0, 40, 116, 26, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 0, 58, 37, 0, 6, 120, 120, 120, 121, 0, - 0, 11, 11, 11, 49, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 46, 2, 2, 2, 2, 2, 2, 11, - 11, 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 44, 44, 44, 92, 0, + 0, 11, 11, 46, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 30, 0, + 9, 2, 2, 2, 30, 45, 59, 20, 20, 31, 33, 32, 32, 25, 162, 29, + 163, 164, 37, 0, 0, 0, 0, 0, 0, 12, 26, 0, 0, 0, 0, 0, + 0, 2, 2, 65, 25, 20, 20, 20, 22, 23, 125, 15, 17, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 0, 0, 165, 166, 0, 0, 0, 0, 0, 0, + 0, 18, 19, 20, 20, 66, 99, 25, 159, 11, 167, 9, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 65, 25, 20, 20, 0, 48, 48, 11, + 168, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 20, + 0, 23, 19, 20, 20, 21, 16, 82, 168, 38, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 10, 169, 25, 20, 22, 22, 167, 9, 0, 0, + 0, 2, 2, 2, 2, 2, 9, 43, 135, 23, 22, 20, 76, 21, 22, 0, + 0, 2, 2, 2, 9, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 18, + 19, 20, 21, 22, 105, 168, 37, 0, 0, 2, 2, 2, 9, 30, 0, 2, + 2, 2, 2, 30, 9, 2, 2, 2, 2, 23, 23, 18, 32, 33, 12, 170, + 164, 171, 172, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, + 2, 65, 25, 20, 20, 0, 22, 23, 29, 108, 0, 33, 0, 0, 0, 0, + 0, 52, 20, 22, 22, 22, 139, 2, 2, 2, 173, 174, 11, 15, 175, 61, + 176, 0, 0, 1, 146, 0, 0, 0, 0, 52, 20, 22, 16, 19, 20, 2, + 2, 2, 2, 157, 157, 157, 177, 177, 177, 177, 177, 177, 15, 178, 0, 30, + 0, 22, 20, 20, 31, 22, 22, 11, 168, 0, 61, 61, 61, 61, 61, 61, + 61, 66, 21, 82, 46, 0, 0, 0, 0, 2, 2, 2, 9, 2, 30, 2, + 2, 52, 22, 22, 31, 0, 38, 22, 27, 11, 158, 179, 180, 0, 0, 0, + 0, 2, 2, 2, 30, 9, 2, 2, 2, 2, 2, 2, 2, 2, 23, 23, + 47, 22, 35, 82, 68, 0, 0, 0, 0, 2, 181, 66, 47, 0, 0, 0, + 0, 11, 182, 2, 2, 2, 2, 2, 2, 2, 2, 23, 22, 20, 31, 0, + 48, 16, 142, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 155, 0, + 0, 183, 183, 183, 183, 183, 183, 183, 183, 184, 184, 184, 185, 186, 184, 183, + 183, 187, 183, 183, 188, 189, 189, 189, 189, 189, 189, 189, 0, 0, 0, 0, + 0, 183, 183, 183, 183, 183, 190, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 22, 22, 22, 22, 22, 22, 191, 192, 193, 11, 11, 11, 46, 0, 0, 0, + 0, 29, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 65, 47, + 0, 2, 2, 2, 2, 2, 9, 0, 58, 194, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, + 40, 115, 26, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 2, 2, 2, 2, 2, 0, 58, + 37, 0, 6, 119, 119, 119, 120, 0, 0, 11, 11, 11, 49, 2, 2, 2, + 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 46, 2, 2, 2, 2, 2, 2, 11, 11, 2, 2, 2, 2, 2, 2, 22, + 22, 2, 2, 2, 2, 2, 2, 2, 20, 2, 2, 44, 44, 44, 92, 0, 0, O, O, O, GB, B, B, O, SB, O, SE, GB, O, O, WJ,FMPst, FMPst, O, CGJ, B, O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv, VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, @@ -582,20 +606,21 @@ hb_use_u8[3483] = VMPst, VBlw, VPst, CGJ, CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS, FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, - SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv, - SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, - CGJ, WJ, WJ, WJ, O,FMPst, O, SB, SE, O, H, MPst, VPst, H,VMAbv, VAbv, - VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, - MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, - O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, - B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R,CMBlw, - VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, - VAbv,VMAbv, VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, - GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, R,VMPst, G, G, J, J, J, - SB, SE, J, HR, G, G, HM, HM, HM, O, VBlw, + SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMAbv,SMAbv, VPst, + IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, + WJ, WJ, O,FMPst, O, SB, SE, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, + VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, + MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, + VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, + N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R,CMBlw, VAbv, VPre, + VMAbv,VMAbv, H, VAbv,CMBlw,VMPst, O,VMAbv,CMBlw, IS, R,FMAbv, B, CS, CS, H, + CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, CS, + SUB, SUB, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, R, MBlw, GB, VAbv, R,VMPst, G, + G, J, J, J, SB, SE, J, HR, G, G, HM, HM, HM, G, O, MPre, + MPre, MPst,VMAbv, MBlw, VBlw, O, VBlw, }; static const uint16_t -hb_use_u16[456] = +hb_use_u16[486] = { 0, 0, 1, 2, 0, 3, 4, 5, 0, 6, 7, 0, 8, 0, 9, 10, 11, 12, 10, 13, 14, 10, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23, @@ -614,18 +639,20 @@ hb_use_u16[456] = 148,149,150, 10, 10,151,152, 2,153, 99,154,155,156, 2, 10,157, 10,158,159, 0,160,161,162, 2,163, 0, 0,164, 0,165, 0,166, 166,167, 34,168,169,170, 10,171, 95, 0,172, 0, 10,173,174, 0, - 175, 2,176,173,177,178,179, 0, 0,180,181, 0,182, 10, 10,183, - 184,185,186,187,188, 10, 10,189,190, 0,191, 10,192,193,194, 10, - 10,195, 10,196,197,106,198,103, 10, 34,199,200,201, 0,202,203, - 95, 10, 10,204,205, 2,206, 21, 22,207,208,209,210,211, 10,212, - 213,214,215, 0,198, 10, 10,216,217, 2,218,219,220,221, 10,222, - 223, 2,224,225, 10,226,227,104,228, 0,229,230,231,232, 10,233, - 234, 2,235, 10, 10,236,237, 0,238, 10, 10,239,240,241,242,243, - 22, 10,218,244, 8, 10, 71, 19, 10,245, 74,246,247, 10, 10,248, - 249, 2,250, 10,251,252, 10,253,254, 49, 10,255,256, 2,257,257, - 257,258,259,260, 10,261,262,263,264,264,265,266,267, 0, 10,268, - 106, 71, 95,269, 0,270, 71,271,272, 0,273, 0,274, 2,275, 2, - 276, 2,130,130,163,163,163,130, + 175, 2,176, 10,177, 0,178,173,179,180,181, 0, 0,182,183, 0, + 184, 10, 10,185,186,187,188,189,190, 10, 10,191,192, 0,193, 10, + 194,195,196, 10, 10,197, 10,198,199,106,200,103, 10, 34,201,202, + 203, 0,204,205, 95, 10, 10,206,207, 2,208, 21, 22,209,210,211, + 212,213,214, 10, 10,215,216,217,218, 0, 10,219,220,221,222, 0, + 200, 10, 10,223,224, 2,225,226,227,228, 10,229,230, 2,231,232, + 2, 10,141, 0, 10,233,234,104,235, 0,236,237,238,239, 10,240, + 241, 2,242, 10, 10,243,244, 0,245, 10, 10,246,247,248,249,250, + 22, 10,225,251, 8, 10, 71, 19, 10,252, 74,253,254, 10, 10,255, + 256, 2,257, 10,258,259, 10,260,261, 49, 10,262,263,264,265,265, + 265,266,267,268,265,269, 10,270,271, 2, 10,272,273, 10,274, 2, + 275,276,277,277,278,279,280, 0, 10,177, 0,281,106, 71, 95,282, + 0,283, 71,284,285, 0,286, 0,287, 2,288, 2,289,106,290, 2, + 130,130,163,163,163,130, }; static inline unsigned @@ -636,7 +663,7 @@ hb_use_b4 (const uint8_t* a, unsigned i) static inline uint_fast8_t hb_use_get_category (unsigned u) { - return u<921600u?hb_use_u8[3105+(((hb_use_u8[889+(((hb_use_u16[((hb_use_u8[353+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; + return u<921600u?hb_use_u8[3265+(((hb_use_u8[937+(((hb_use_u16[((hb_use_u8[369+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O; } #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc index d1ed894596..dbe781e562 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc @@ -10,8 +10,8 @@ * # Date: 2015-03-12, 21:17:00 GMT [AG] * # Date: 2019-11-08, 23:22:00 GMT [AG] * - * # Scripts-15.1.0.txt - * # Date: 2023-07-28, 16:01:07 GMT + * # Scripts-16.0.0.txt + * # Date: 2024-04-30, 21:48:40 GMT */ #include "hb.hh" diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper.hh b/thirdparty/harfbuzz/src/hb-ot-shaper.hh index 0207b2bbe3..8a094739cb 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shaper.hh @@ -174,9 +174,11 @@ HB_OT_SHAPERS_IMPLEMENT_SHAPERS static inline const hb_ot_shaper_t * -hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner) +hb_ot_shaper_categorize (hb_script_t script, + hb_direction_t direction, + hb_tag_t gsub_script) { - switch ((hb_tag_t) planner->props.script) + switch ((hb_tag_t) script) { default: return &_hb_ot_shaper_default; @@ -192,9 +194,8 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner) * 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 * vertical text, just use the generic shaper instead. */ - if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT || - planner->props.script == HB_SCRIPT_ARABIC) && - HB_DIRECTION_IS_HORIZONTAL(planner->props.direction)) + if ((gsub_script != HB_OT_TAG_DEFAULT_SCRIPT || script == HB_SCRIPT_ARABIC) && + HB_DIRECTION_IS_HORIZONTAL (direction)) return &_hb_ot_shaper_arabic; else return &_hb_ot_shaper_default; @@ -235,10 +236,10 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner) * Otherwise, use the specific shaper. * * If it's indy3 tag, send to USE. */ - if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') || - planner->map.chosen_script[0] == HB_TAG ('l','a','t','n')) + if (gsub_script == HB_TAG ('D','F','L','T') || + gsub_script == HB_TAG ('l','a','t','n')) return &_hb_ot_shaper_default; - else if ((planner->map.chosen_script[0] & 0x000000FF) == '3') + else if ((gsub_script & 0x000000FF) == '3') return &_hb_ot_shaper_use; else return &_hb_ot_shaper_indic; @@ -254,9 +255,9 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner) * If designer designed for 'mymr' tag, also send to default * shaper. That's tag used from before Myanmar shaping spec * was developed. The shaping spec uses 'mym2' tag. */ - if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') || - planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') || - planner->map.chosen_script[0] == HB_TAG ('m','y','m','r')) + if (gsub_script == HB_TAG ('D','F','L','T') || + gsub_script == HB_TAG ('l','a','t','n') || + gsub_script == HB_TAG ('m','y','m','r')) return &_hb_ot_shaper_default; else return &_hb_ot_shaper_myanmar; @@ -386,13 +387,22 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_KAWI: case HB_SCRIPT_NAG_MUNDARI: + /* Unicode-16.0 additions */ + case HB_SCRIPT_GARAY: + case HB_SCRIPT_GURUNG_KHEMA: + case HB_SCRIPT_KIRAT_RAI: + case HB_SCRIPT_OL_ONAL: + case HB_SCRIPT_SUNUWAR: + case HB_SCRIPT_TODHRI: + case HB_SCRIPT_TULU_TIGALARI: + /* If the designer designed the font for the 'DFLT' script, * (or we ended up arbitrarily pick 'latn'), use the default shaper. * Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* * GSUB/GPOS needed, so there may be no scripts found! */ - if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') || - planner->map.chosen_script[0] == HB_TAG ('l','a','t','n')) + if (gsub_script == HB_TAG ('D','F','L','T') || + gsub_script == HB_TAG ('l','a','t','n')) return &_hb_ot_shaper_default; else return &_hb_ot_shaper_use; diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh index ea5459ef4e..7a46be1fff 100644 --- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh @@ -354,10 +354,10 @@ struct AxisValue { switch (u.format) { - case 1: return u.format1.get_value (); - case 2: return u.format2.get_value (); - case 3: return u.format3.get_value (); - case 4: return u.format4.get_axis_record (axis_index).get_value (); + case 1: hb_barrier (); return u.format1.get_value (); + case 2: hb_barrier (); return u.format2.get_value (); + case 3: hb_barrier (); return u.format3.get_value (); + case 4: hb_barrier (); return u.format4.get_axis_record (axis_index).get_value (); default:return 0.f; } } @@ -366,9 +366,9 @@ struct AxisValue { switch (u.format) { - case 1: return u.format1.get_axis_index (); - case 2: return u.format2.get_axis_index (); - case 3: return u.format3.get_axis_index (); + case 1: hb_barrier (); return u.format1.get_axis_index (); + case 2: hb_barrier (); return u.format2.get_axis_index (); + case 3: hb_barrier (); return u.format3.get_axis_index (); /* case 4: Makes more sense for variable fonts which are handled by fvar in hb-style */ default:return -1; } @@ -378,10 +378,10 @@ struct AxisValue { switch (u.format) { - case 1: return u.format1.get_value_name_id (); - case 2: return u.format2.get_value_name_id (); - case 3: return u.format3.get_value_name_id (); - case 4: return u.format4.get_value_name_id (); + case 1: hb_barrier (); return u.format1.get_value_name_id (); + case 2: hb_barrier (); return u.format2.get_value_name_id (); + case 3: hb_barrier (); return u.format3.get_value_name_id (); + case 4: hb_barrier (); return u.format4.get_value_name_id (); default:return HB_OT_NAME_ID_INVALID; } } @@ -392,10 +392,10 @@ struct AxisValue if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); TRACE_DISPATCH (this, u.format); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); - case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -405,10 +405,10 @@ struct AxisValue { switch (u.format) { - case 1: return u.format1.keep_axis_value (axis_records, user_axes_location); - case 2: return u.format2.keep_axis_value (axis_records, user_axes_location); - case 3: return u.format3.keep_axis_value (axis_records, user_axes_location); - case 4: return u.format4.keep_axis_value (axis_records, user_axes_location); + case 1: hb_barrier (); return u.format1.keep_axis_value (axis_records, user_axes_location); + case 2: hb_barrier (); return u.format2.keep_axis_value (axis_records, user_axes_location); + case 3: hb_barrier (); return u.format3.keep_axis_value (axis_records, user_axes_location); + case 4: hb_barrier (); return u.format4.keep_axis_value (axis_records, user_axes_location); default:return false; } } @@ -422,10 +422,10 @@ struct AxisValue switch (u.format) { - case 1: return_trace (u.format1.sanitize (c)); - case 2: return_trace (u.format2.sanitize (c)); - case 3: return_trace (u.format3.sanitize (c)); - case 4: return_trace (u.format4.sanitize (c)); + case 1: hb_barrier (); return_trace (u.format1.sanitize (c)); + case 2: hb_barrier (); return_trace (u.format2.sanitize (c)); + case 3: hb_barrier (); return_trace (u.format3.sanitize (c)); + case 4: hb_barrier (); return_trace (u.format4.sanitize (c)); default:return_trace (true); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh index 920b06b9c9..326e019127 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh @@ -6,8 +6,8 @@ * * on files with these headers: * - * <meta name="updated_at" content="2023-09-30 01:21 AM" /> - * File-Date: 2024-03-07 + * <meta name="updated_at" content="2024-05-31 05:41 PM" /> + * File-Date: 2024-05-16 */ #ifndef HB_OT_TAG_TABLE_HH @@ -26,7 +26,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('a','y',' ',' '), HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */ {HB_TAG('a','z',' ',' '), HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */ {HB_TAG('b','a',' ',' '), HB_TAG('B','S','H',' ')}, /* Bashkir */ - {HB_TAG('b','e',' ',' '), HB_TAG('B','E','L',' ')}, /* Belarusian -> Belarussian */ + {HB_TAG('b','e',' ',' '), HB_TAG('B','E','L',' ')}, /* Belarusian */ {HB_TAG('b','g',' ',' '), HB_TAG('B','G','R',' ')}, /* Bulgarian */ {HB_TAG('b','i',' ',' '), HB_TAG('B','I','S',' ')}, /* Bislama */ {HB_TAG('b','i',' ',' '), HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */ @@ -64,6 +64,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('f','r',' ',' '), HB_TAG('F','R','A',' ')}, /* French */ {HB_TAG('f','y',' ',' '), HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */ {HB_TAG('g','a',' ',' '), HB_TAG('I','R','I',' ')}, /* Irish */ + {HB_TAG('g','a',' ',' '), HB_TAG('I','R','T',' ')}, /* Irish -> Irish Traditional */ {HB_TAG('g','d',' ',' '), HB_TAG('G','A','E',' ')}, /* Scottish Gaelic */ {HB_TAG('g','l',' ',' '), HB_TAG('G','A','L',' ')}, /* Galician */ {HB_TAG('g','n',' ',' '), HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ @@ -132,7 +133,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('m','l',' ',' '), HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */ {HB_TAG('m','l',' ',' '), HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */ {HB_TAG('m','n',' ',' '), HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */ - {HB_TAG('m','o',' ',' '), HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) -> Romanian (Moldova) */ + {HB_TAG('m','o',' ',' '), HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */ {HB_TAG('m','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */ {HB_TAG('m','r',' ',' '), HB_TAG('M','A','R',' ')}, /* Marathi */ {HB_TAG('m','s',' ',' '), HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ @@ -223,6 +224,7 @@ static const LangTag ot_languages2[] = { static const LangTag ot_languages3[] = { {HB_TAG('a','a','e',' '), HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */ {HB_TAG('a','a','o',' '), HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */ +/*{HB_TAG('a','a','q',' '), HB_TAG('A','A','Q',' ')},*/ /* Eastern Abnaki -> Eastern Abenaki */ {HB_TAG('a','a','t',' '), HB_TAG('S','Q','I',' ')}, /* Arvanitika Albanian -> Albanian */ {HB_TAG('a','b','a',' '), HB_TAG_NONE }, /* Abé != Abaza */ {HB_TAG('a','b','h',' '), HB_TAG('A','R','A',' ')}, /* Tajiki Arabic -> Arabic */ @@ -238,6 +240,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('a','c','r',' '), HB_TAG('M','Y','N',' ')}, /* Achi -> Mayan */ {HB_TAG('a','c','w',' '), HB_TAG('A','R','A',' ')}, /* Hijazi Arabic -> Arabic */ {HB_TAG('a','c','x',' '), HB_TAG('A','R','A',' ')}, /* Omani Arabic -> Arabic */ + {HB_TAG('a','c','y',' '), HB_TAG('A','C','Y',' ')}, /* Cypriot Arabic */ {HB_TAG('a','c','y',' '), HB_TAG('A','R','A',' ')}, /* Cypriot Arabic -> Arabic */ {HB_TAG('a','d','a',' '), HB_TAG('D','N','G',' ')}, /* Adangme -> Dangme */ {HB_TAG('a','d','f',' '), HB_TAG('A','R','A',' ')}, /* Dhofari Arabic -> Arabic */ @@ -288,6 +291,7 @@ static const LangTag ot_languages3[] = { /*{HB_TAG('a','s','t',' '), HB_TAG('A','S','T',' ')},*/ /* Asturian */ /*{HB_TAG('a','t','h',' '), HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */ {HB_TAG('a','t','j',' '), HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */ +/*{HB_TAG('a','t','s',' '), HB_TAG('A','T','S',' ')},*/ /* Gros Ventre (Atsina) */ {HB_TAG('a','t','v',' '), HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */ {HB_TAG('a','u','j',' '), HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */ {HB_TAG('a','u','z',' '), HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */ @@ -326,6 +330,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('b','c','l',' '), HB_TAG('B','I','K',' ')}, /* Central Bikol -> Bikol */ {HB_TAG('b','c','q',' '), HB_TAG('B','C','H',' ')}, /* Bench */ {HB_TAG('b','c','r',' '), HB_TAG('A','T','H',' ')}, /* Babine -> Athapaskan */ +/*{HB_TAG('b','d','c',' '), HB_TAG('B','D','C',' ')},*/ /* Emberá-Baudó */ /*{HB_TAG('b','d','y',' '), HB_TAG('B','D','Y',' ')},*/ /* Bandjalang */ {HB_TAG('b','e','a',' '), HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */ {HB_TAG('b','e','b',' '), HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */ @@ -421,6 +426,8 @@ static const LangTag ot_languages3[] = { {HB_TAG('c','a','f',' '), HB_TAG('A','T','H',' ')}, /* Southern Carrier -> Athapaskan */ {HB_TAG('c','a','k',' '), HB_TAG('C','A','K',' ')}, /* Kaqchikel */ {HB_TAG('c','a','k',' '), HB_TAG('M','Y','N',' ')}, /* Kaqchikel -> Mayan */ +/*{HB_TAG('c','a','y',' '), HB_TAG('C','A','Y',' ')},*/ /* Cayuga */ +/*{HB_TAG('c','b','g',' '), HB_TAG('C','B','G',' ')},*/ /* Chimila */ {HB_TAG('c','b','k',' '), HB_TAG('C','B','K',' ')}, /* Chavacano -> Zamboanga Chavacano */ {HB_TAG('c','b','k',' '), HB_TAG('C','P','P',' ')}, /* Chavacano -> Creoles */ {HB_TAG('c','b','l',' '), HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin -> Chin */ @@ -467,6 +474,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('c','l','j',' '), HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */ {HB_TAG('c','l','s',' '), HB_TAG('S','A','N',' ')}, /* Classical Sanskrit -> Sanskrit */ {HB_TAG('c','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */ +/*{HB_TAG('c','m','i',' '), HB_TAG('C','M','I',' ')},*/ /* Emberá-Chamí */ {HB_TAG('c','m','n',' '), HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */ {HB_TAG('c','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */ {HB_TAG('c','n','b',' '), HB_TAG('Q','I','N',' ')}, /* Chinbon Chin -> Chin */ @@ -480,6 +488,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('c','n','w',' '), HB_TAG('Q','I','N',' ')}, /* Ngawn Chin -> Chin */ {HB_TAG('c','o','a',' '), HB_TAG('M','L','Y',' ')}, /* Cocos Islands Malay -> Malay */ {HB_TAG('c','o','b',' '), HB_TAG('M','Y','N',' ')}, /* Chicomuceltec -> Mayan */ +/*{HB_TAG('c','o','o',' '), HB_TAG('C','O','O',' ')},*/ /* Comox */ /*{HB_TAG('c','o','p',' '), HB_TAG('C','O','P',' ')},*/ /* Coptic */ {HB_TAG('c','o','q',' '), HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */ {HB_TAG('c','p','a',' '), HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */ @@ -529,6 +538,7 @@ static const LangTag ot_languages3[] = { /*{HB_TAG('c','t','g',' '), HB_TAG('C','T','G',' ')},*/ /* Chittagonian */ {HB_TAG('c','t','h',' '), HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */ {HB_TAG('c','t','l',' '), HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */ +/*{HB_TAG('c','t','o',' '), HB_TAG('C','T','O',' ')},*/ /* Emberá-Catío */ {HB_TAG('c','t','s',' '), HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */ /*{HB_TAG('c','t','t',' '), HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */ {HB_TAG('c','t','u',' '), HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */ @@ -552,7 +562,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('d','e','p',' '), HB_TAG('C','P','P',' ')}, /* Pidgin Delaware -> Creoles */ {HB_TAG('d','g','o',' '), HB_TAG('D','G','O',' ')}, /* Dogri (individual language) */ {HB_TAG('d','g','o',' '), HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) */ - {HB_TAG('d','g','r',' '), HB_TAG('A','T','H',' ')}, /* Dogrib -> Athapaskan */ + {HB_TAG('d','g','r',' '), HB_TAG('A','T','H',' ')}, /* Tlicho -> Athapaskan */ {HB_TAG('d','h','d',' '), HB_TAG('M','A','W',' ')}, /* Dhundari -> Marwari */ /*{HB_TAG('d','h','g',' '), HB_TAG('D','H','G',' ')},*/ /* Dhangu */ {HB_TAG('d','h','v',' '), HB_TAG_NONE }, /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */ @@ -591,6 +601,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('e','k','y',' '), HB_TAG('K','R','N',' ')}, /* Eastern Kayah -> Karen */ {HB_TAG('e','m','k',' '), HB_TAG('E','M','K',' ')}, /* Eastern Maninkakan */ {HB_TAG('e','m','k',' '), HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan -> Maninka */ +/*{HB_TAG('e','m','p',' '), HB_TAG('E','M','P',' ')},*/ /* Northern Emberá */ {HB_TAG('e','m','y',' '), HB_TAG('M','Y','N',' ')}, /* Epigraphic Mayan -> Mayan */ {HB_TAG('e','n','b',' '), HB_TAG('K','A','L',' ')}, /* Markweeta -> Kalenjin */ {HB_TAG('e','n','f',' '), HB_TAG('F','N','E',' ')}, /* Forest Enets */ @@ -655,6 +666,7 @@ static const LangTag ot_languages3[] = { /*{HB_TAG('g','e','z',' '), HB_TAG('G','E','Z',' ')},*/ /* Geez */ {HB_TAG('g','g','o',' '), HB_TAG('G','O','N',' ')}, /* Southern Gondi (retired code) -> Gondi */ {HB_TAG('g','h','a',' '), HB_TAG('B','B','R',' ')}, /* Ghadamès -> Berber */ + {HB_TAG('g','h','c',' '), HB_TAG('I','R','T',' ')}, /* Hiberno-Scottish Gaelic -> Irish Traditional */ {HB_TAG('g','h','k',' '), HB_TAG('K','R','N',' ')}, /* Geko Karen -> Karen */ {HB_TAG('g','h','o',' '), HB_TAG('B','B','R',' ')}, /* Ghomara -> Berber */ {HB_TAG('g','i','b',' '), HB_TAG('C','P','P',' ')}, /* Gibanawa -> Creoles */ @@ -744,6 +756,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('h','s','n',' '), HB_TAG('Z','H','S',' ')}, /* Xiang Chinese -> Chinese, Simplified */ {HB_TAG('h','u','j',' '), HB_TAG('H','M','N',' ')}, /* Northern Guiyang Hmong -> Hmong */ {HB_TAG('h','u','p',' '), HB_TAG('A','T','H',' ')}, /* Hupa -> Athapaskan */ +/*{HB_TAG('h','u','r',' '), HB_TAG('H','U','R',' ')},*/ /* Halkomelem */ {HB_TAG('h','u','s',' '), HB_TAG('M','Y','N',' ')}, /* Huastec -> Mayan */ {HB_TAG('h','w','c',' '), HB_TAG('C','P','P',' ')}, /* Hawai'i Creole English -> Creoles */ {HB_TAG('h','y','w',' '), HB_TAG('H','Y','E',' ')}, /* Western Armenian -> Armenian */ @@ -781,6 +794,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('j','b','n',' '), HB_TAG('B','B','R',' ')}, /* Nafusi -> Berber */ /*{HB_TAG('j','b','o',' '), HB_TAG('J','B','O',' ')},*/ /* Lojban */ /*{HB_TAG('j','c','t',' '), HB_TAG('J','C','T',' ')},*/ /* Krymchak */ +/*{HB_TAG('j','d','t',' '), HB_TAG('J','D','T',' ')},*/ /* Judeo-Tat */ {HB_TAG('j','g','o',' '), HB_TAG('B','M','L',' ')}, /* Ngomba -> Bamileke */ {HB_TAG('j','i','i',' '), HB_TAG_NONE }, /* Jiiddu != Yiddish */ {HB_TAG('j','k','m',' '), HB_TAG('K','R','N',' ')}, /* Mobwa Karen -> Karen */ @@ -795,6 +809,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('k','a','m',' '), HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */ {HB_TAG('k','a','r',' '), HB_TAG('K','R','N',' ')}, /* Karen [collection] */ /*{HB_TAG('k','a','w',' '), HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */ +/*{HB_TAG('k','b','c',' '), HB_TAG('K','B','C',' ')},*/ /* Kadiwéu */ {HB_TAG('k','b','d',' '), HB_TAG('K','A','B',' ')}, /* Kabardian */ {HB_TAG('k','b','y',' '), HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */ {HB_TAG('k','c','a',' '), HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */ @@ -830,6 +845,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('k','j','b',' '), HB_TAG('M','Y','N',' ')}, /* Q'anjob'al -> Mayan */ /*{HB_TAG('k','j','d',' '), HB_TAG('K','J','D',' ')},*/ /* Southern Kiwai */ {HB_TAG('k','j','h',' '), HB_TAG('K','H','A',' ')}, /* Khakas -> Khakass */ +/*{HB_TAG('k','j','j',' '), HB_TAG('K','J','J',' ')},*/ /* Khinalugh -> Khinalug */ {HB_TAG('k','j','p',' '), HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen -> Eastern Pwo Karen */ {HB_TAG('k','j','p',' '), HB_TAG('K','R','N',' ')}, /* Pwo Eastern Karen -> Karen */ {HB_TAG('k','j','t',' '), HB_TAG('K','R','N',' ')}, /* Phrae Pwo Karen -> Karen */ @@ -931,6 +947,7 @@ static const LangTag ot_languages3[] = { /*{HB_TAG('l','i','j',' '), HB_TAG('L','I','J',' ')},*/ /* Ligurian */ {HB_TAG('l','i','r',' '), HB_TAG('C','P','P',' ')}, /* Liberian English -> Creoles */ /*{HB_TAG('l','i','s',' '), HB_TAG('L','I','S',' ')},*/ /* Lisu */ +/*{HB_TAG('l','i','v',' '), HB_TAG('L','I','V',' ')},*/ /* Liv */ {HB_TAG('l','i','w',' '), HB_TAG('M','L','Y',' ')}, /* Col -> Malay */ {HB_TAG('l','i','y',' '), HB_TAG('B','A','D','0')}, /* Banda-Bambari -> Banda */ /*{HB_TAG('l','j','p',' '), HB_TAG('L','J','P',' ')},*/ /* Lampung Api -> Lampung */ @@ -996,12 +1013,14 @@ static const LangTag ot_languages3[] = { {HB_TAG('m','e','n',' '), HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */ {HB_TAG('m','e','o',' '), HB_TAG('M','L','Y',' ')}, /* Kedah Malay -> Malay */ /*{HB_TAG('m','e','r',' '), HB_TAG('M','E','R',' ')},*/ /* Meru */ +/*{HB_TAG('m','e','v',' '), HB_TAG('M','E','V',' ')},*/ /* Mano */ {HB_TAG('m','f','a',' '), HB_TAG('M','F','A',' ')}, /* Pattani Malay */ {HB_TAG('m','f','a',' '), HB_TAG('M','L','Y',' ')}, /* Pattani Malay -> Malay */ {HB_TAG('m','f','b',' '), HB_TAG('M','L','Y',' ')}, /* Bangka -> Malay */ {HB_TAG('m','f','e',' '), HB_TAG('M','F','E',' ')}, /* Morisyen */ {HB_TAG('m','f','e',' '), HB_TAG('C','P','P',' ')}, /* Morisyen -> Creoles */ {HB_TAG('m','f','p',' '), HB_TAG('C','P','P',' ')}, /* Makassar Malay -> Creoles */ + {HB_TAG('m','g','a',' '), HB_TAG('S','G','A',' ')}, /* Middle Irish (900-1200) -> Old Irish */ {HB_TAG('m','h','c',' '), HB_TAG('M','Y','N',' ')}, /* Mocho -> Mayan */ {HB_TAG('m','h','r',' '), HB_TAG('L','M','A',' ')}, /* Eastern Mari -> Low Mari */ {HB_TAG('m','h','v',' '), HB_TAG('A','R','K',' ')}, /* Arakanese (retired code) -> Rakhine */ @@ -1154,6 +1173,8 @@ static const LangTag ot_languages3[] = { {HB_TAG('o','k','i',' '), HB_TAG('K','A','L',' ')}, /* Okiek -> Kalenjin */ {HB_TAG('o','k','m',' '), HB_TAG('K','O','H',' ')}, /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */ {HB_TAG('o','k','r',' '), HB_TAG('I','J','O',' ')}, /* Kirike -> Ijo */ +/*{HB_TAG('o','n','e',' '), HB_TAG('O','N','E',' ')},*/ /* Oneida */ +/*{HB_TAG('o','n','o',' '), HB_TAG('O','N','O',' ')},*/ /* Onondaga */ {HB_TAG('o','n','x',' '), HB_TAG('C','P','P',' ')}, /* Onin Based Pidgin -> Creoles */ {HB_TAG('o','o','r',' '), HB_TAG('C','P','P',' ')}, /* Oorlams -> Creoles */ {HB_TAG('o','r','c',' '), HB_TAG('O','R','O',' ')}, /* Orma -> Oromo */ @@ -1194,7 +1215,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('p','i','s',' '), HB_TAG('C','P','P',' ')}, /* Pijin -> Creoles */ {HB_TAG('p','k','h',' '), HB_TAG('Q','I','N',' ')}, /* Pankhu -> Chin */ {HB_TAG('p','k','o',' '), HB_TAG('K','A','L',' ')}, /* Pökoot -> Kalenjin */ - {HB_TAG('p','l','g',' '), HB_TAG_NONE }, /* Pilagá != Palaung */ + {HB_TAG('p','l','g',' '), HB_TAG('P','L','G','0')}, /* Pilagá */ {HB_TAG('p','l','k',' '), HB_TAG_NONE }, /* Kohistani Shina != Polish */ {HB_TAG('p','l','l',' '), HB_TAG('P','L','G',' ')}, /* Shwe Palaung -> Palaung */ {HB_TAG('p','l','n',' '), HB_TAG('C','P','P',' ')}, /* Palenquero -> Creoles */ @@ -1354,6 +1375,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('s','d','h',' '), HB_TAG('K','U','R',' ')}, /* Southern Kurdish -> Kurdish */ {HB_TAG('s','d','n',' '), HB_TAG('S','R','D',' ')}, /* Gallurese Sardinian -> Sardinian */ {HB_TAG('s','d','s',' '), HB_TAG('B','B','R',' ')}, /* Sened -> Berber */ +/*{HB_TAG('s','e','e',' '), HB_TAG('S','E','E',' ')},*/ /* Seneca */ {HB_TAG('s','e','h',' '), HB_TAG('S','N','A',' ')}, /* Sena */ {HB_TAG('s','e','k',' '), HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */ /*{HB_TAG('s','e','l',' '), HB_TAG('S','E','L',' ')},*/ /* Selkup */ @@ -1375,6 +1397,7 @@ static const LangTag ot_languages3[] = { /*{HB_TAG('s','i','d',' '), HB_TAG('S','I','D',' ')},*/ /* Sidamo */ {HB_TAG('s','i','g',' '), HB_TAG_NONE }, /* Paasaal != Silte Gurage */ {HB_TAG('s','i','z',' '), HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */ +/*{HB_TAG('s','j','a',' '), HB_TAG('S','J','A',' ')},*/ /* Epena */ {HB_TAG('s','j','d',' '), HB_TAG('K','S','M',' ')}, /* Kildin Sami */ {HB_TAG('s','j','o',' '), HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */ {HB_TAG('s','j','s',' '), HB_TAG('B','B','R',' ')}, /* Senhaja De Srair -> Berber */ @@ -1411,6 +1434,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('s','s','m',' '), HB_TAG_NONE }, /* Semnam != Southern Sami */ {HB_TAG('s','t','a',' '), HB_TAG('C','P','P',' ')}, /* Settla -> Creoles */ /*{HB_TAG('s','t','q',' '), HB_TAG('S','T','Q',' ')},*/ /* Saterfriesisch -> Saterland Frisian */ +/*{HB_TAG('s','t','r',' '), HB_TAG('S','T','R',' ')},*/ /* Straits Salish */ {HB_TAG('s','t','v',' '), HB_TAG('S','I','G',' ')}, /* Silt'e -> Silte Gurage */ /*{HB_TAG('s','u','k',' '), HB_TAG('S','U','K',' ')},*/ /* Sukuma */ {HB_TAG('s','u','q',' '), HB_TAG('S','U','R',' ')}, /* Suri */ @@ -1432,6 +1456,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('t','a','a',' '), HB_TAG('A','T','H',' ')}, /* Lower Tanana -> Athapaskan */ /*{HB_TAG('t','a','b',' '), HB_TAG('T','A','B',' ')},*/ /* Tabassaran -> Tabasaran */ {HB_TAG('t','a','j',' '), HB_TAG_NONE }, /* Eastern Tamang != Tajiki */ + {HB_TAG('t','a','q',' '), HB_TAG('T','A','Q',' ')}, /* Tamasheq */ {HB_TAG('t','a','q',' '), HB_TAG('T','M','H',' ')}, /* Tamasheq -> Tamashek */ {HB_TAG('t','a','q',' '), HB_TAG('B','B','R',' ')}, /* Tamasheq -> Berber */ {HB_TAG('t','a','s',' '), HB_TAG('C','P','P',' ')}, /* Tay Boi -> Creoles */ @@ -1443,6 +1468,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('t','c','s',' '), HB_TAG('C','P','P',' ')}, /* Torres Strait Creole -> Creoles */ {HB_TAG('t','c','y',' '), HB_TAG('T','U','L',' ')}, /* Tulu */ {HB_TAG('t','c','z',' '), HB_TAG('Q','I','N',' ')}, /* Thado Chin -> Chin */ +/*{HB_TAG('t','d','c',' '), HB_TAG('T','D','C',' ')},*/ /* Emberá-Tadó */ /*{HB_TAG('t','d','d',' '), HB_TAG('T','D','D',' ')},*/ /* Tai Nüa -> Dehong Dai */ {HB_TAG('t','d','x',' '), HB_TAG('M','L','G',' ')}, /* Tandroy-Mahafaly Malagasy -> Malagasy */ {HB_TAG('t','e','c',' '), HB_TAG('K','A','L',' ')}, /* Terik -> Kalenjin */ @@ -1456,9 +1482,12 @@ static const LangTag ot_languages3[] = { {HB_TAG('t','g','r',' '), HB_TAG_NONE }, /* Tareng != Tigre */ {HB_TAG('t','g','x',' '), HB_TAG('A','T','H',' ')}, /* Tagish -> Athapaskan */ {HB_TAG('t','g','y',' '), HB_TAG_NONE }, /* Togoyo != Tigrinya */ +/*{HB_TAG('t','h','p',' '), HB_TAG('T','H','P',' ')},*/ /* Thompson */ {HB_TAG('t','h','t',' '), HB_TAG('A','T','H',' ')}, /* Tahltan -> Athapaskan */ + {HB_TAG('t','h','v',' '), HB_TAG('T','H','V',' ')}, /* Tahaggart Tamahaq */ {HB_TAG('t','h','v',' '), HB_TAG('T','M','H',' ')}, /* Tahaggart Tamahaq -> Tamashek */ {HB_TAG('t','h','v',' '), HB_TAG('B','B','R',' ')}, /* Tahaggart Tamahaq -> Berber */ + {HB_TAG('t','h','z',' '), HB_TAG('T','H','Z',' ')}, /* Tayart Tamajeq */ {HB_TAG('t','h','z',' '), HB_TAG('T','M','H',' ')}, /* Tayart Tamajeq -> Tamashek */ {HB_TAG('t','h','z',' '), HB_TAG('B','B','R',' ')}, /* Tayart Tamajeq -> Berber */ {HB_TAG('t','i','a',' '), HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */ @@ -1469,6 +1498,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('t','k','g',' '), HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */ {HB_TAG('t','k','m',' '), HB_TAG_NONE }, /* Takelma != Turkmen */ /*{HB_TAG('t','l','i',' '), HB_TAG('T','L','I',' ')},*/ /* Tlingit */ +/*{HB_TAG('t','l','y',' '), HB_TAG('T','L','Y',' ')},*/ /* Talysh */ {HB_TAG('t','m','g',' '), HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */ {HB_TAG('t','m','h',' '), HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */ {HB_TAG('t','m','h',' '), HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */ @@ -1494,11 +1524,13 @@ static const LangTag ot_languages3[] = { /*{HB_TAG('t','s','j',' '), HB_TAG('T','S','J',' ')},*/ /* Tshangla */ {HB_TAG('t','t','c',' '), HB_TAG('M','Y','N',' ')}, /* Tektiteko -> Mayan */ {HB_TAG('t','t','m',' '), HB_TAG('A','T','H',' ')}, /* Northern Tutchone -> Athapaskan */ + {HB_TAG('t','t','q',' '), HB_TAG('T','T','Q',' ')}, /* Tawallammat Tamajaq */ {HB_TAG('t','t','q',' '), HB_TAG('T','M','H',' ')}, /* Tawallammat Tamajaq -> Tamashek */ {HB_TAG('t','t','q',' '), HB_TAG('B','B','R',' ')}, /* Tawallammat Tamajaq -> Berber */ {HB_TAG('t','u','a',' '), HB_TAG_NONE }, /* Wiarumus != Turoyo Aramaic */ {HB_TAG('t','u','l',' '), HB_TAG_NONE }, /* Tula != Tulu */ /*{HB_TAG('t','u','m',' '), HB_TAG('T','U','M',' ')},*/ /* Tumbuka */ +/*{HB_TAG('t','u','s',' '), HB_TAG('T','U','S',' ')},*/ /* Tuscarora */ {HB_TAG('t','u','u',' '), HB_TAG('A','T','H',' ')}, /* Tututni -> Athapaskan */ {HB_TAG('t','u','v',' '), HB_TAG_NONE }, /* Turkana != Tuvin */ {HB_TAG('t','u','y',' '), HB_TAG('K','A','L',' ')}, /* Tugen -> Kalenjin */ @@ -1515,6 +1547,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('t','z','o',' '), HB_TAG('T','Z','O',' ')}, /* Tzotzil */ {HB_TAG('t','z','o',' '), HB_TAG('M','Y','N',' ')}, /* Tzotzil -> Mayan */ {HB_TAG('u','b','l',' '), HB_TAG('B','I','K',' ')}, /* Buhi'non Bikol -> Bikol */ +/*{HB_TAG('u','d','i',' '), HB_TAG('U','D','I',' ')},*/ /* Udi */ /*{HB_TAG('u','d','m',' '), HB_TAG('U','D','M',' ')},*/ /* Udmurt */ {HB_TAG('u','k','i',' '), HB_TAG('K','U','I',' ')}, /* Kui (India) */ {HB_TAG('u','l','n',' '), HB_TAG('C','P','P',' ')}, /* Unserdeutsch -> Creoles */ @@ -1533,14 +1566,17 @@ static const LangTag ot_languages3[] = { {HB_TAG('v','k','t',' '), HB_TAG('M','L','Y',' ')}, /* Tenggarong Kutai Malay -> Malay */ {HB_TAG('v','l','s',' '), HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */ {HB_TAG('v','m','w',' '), HB_TAG('M','A','K',' ')}, /* Makhuwa */ -/*{HB_TAG('v','r','o',' '), HB_TAG('V','R','O',' ')},*/ /* Võro */ + {HB_TAG('v','r','o',' '), HB_TAG('V','R','O',' ')}, /* Võro */ + {HB_TAG('v','r','o',' '), HB_TAG('E','T','I',' ')}, /* Võro -> Estonian */ {HB_TAG('v','s','n',' '), HB_TAG('S','A','N',' ')}, /* Vedic Sanskrit -> Sanskrit */ {HB_TAG('w','a','g',' '), HB_TAG_NONE }, /* Wa'ema != Wagdi */ /*{HB_TAG('w','a','r',' '), HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */ +/*{HB_TAG('w','b','l',' '), HB_TAG('W','B','L',' ')},*/ /* Wakhi */ {HB_TAG('w','b','m',' '), HB_TAG('W','A',' ',' ')}, /* Wa */ {HB_TAG('w','b','r',' '), HB_TAG('W','A','G',' ')}, /* Wagdi */ {HB_TAG('w','b','r',' '), HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */ /*{HB_TAG('w','c','i',' '), HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */ +/*{HB_TAG('w','d','t',' '), HB_TAG('W','D','T',' ')},*/ /* Wendat */ {HB_TAG('w','e','a',' '), HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */ {HB_TAG('w','e','s',' '), HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */ {HB_TAG('w','e','u',' '), HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */ @@ -1552,6 +1588,9 @@ static const LangTag ot_languages3[] = { {HB_TAG('w','s','g',' '), HB_TAG('G','O','N',' ')}, /* Adilabad Gondi -> Gondi */ /*{HB_TAG('w','t','m',' '), HB_TAG('W','T','M',' ')},*/ /* Mewati */ {HB_TAG('w','u','u',' '), HB_TAG('Z','H','S',' ')}, /* Wu Chinese -> Chinese, Simplified */ + {HB_TAG('w','y','a',' '), HB_TAG('W','D','T',' ')}, /* Wyandot (retired code) -> Wendat */ + {HB_TAG('w','y','a',' '), HB_TAG('W','Y','N',' ')}, /* Wyandot (retired code) */ +/*{HB_TAG('w','y','n',' '), HB_TAG('W','Y','N',' ')},*/ /* Wyandot */ {HB_TAG('x','a','l',' '), HB_TAG('K','L','M',' ')}, /* Kalmyk */ {HB_TAG('x','a','l',' '), HB_TAG('T','O','D',' ')}, /* Kalmyk -> Todo */ {HB_TAG('x','a','n',' '), HB_TAG('S','E','K',' ')}, /* Xamtanga -> Sekota */ @@ -1593,6 +1632,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('y','o','s',' '), HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */ {HB_TAG('y','u','a',' '), HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */ {HB_TAG('y','u','e',' '), HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */ +/*{HB_TAG('y','u','f',' '), HB_TAG('Y','U','F',' ')},*/ /* Havasupai-Walapai-Yavapai */ /*{HB_TAG('y','w','q',' '), HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */ {HB_TAG('z','c','h',' '), HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */ {HB_TAG('z','d','j',' '), HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */ @@ -2645,7 +2685,7 @@ out: /* Romanian; Moldova */ unsigned int i; hb_tag_t possible_tags[] = { - HB_TAG('M','O','L',' '), /* Romanian (Moldova) */ + HB_TAG('M','O','L',' '), /* Moldavian */ HB_TAG('R','O','M',' '), /* Romanian */ }; for (i = 0; i < 2 && i < *count; i++) @@ -2872,7 +2912,7 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ return hb_language_from_string ("und-fonipa", -1); /* Undetermined; International Phonetic Alphabet */ case HB_TAG('I','R','T',' '): /* Irish Traditional */ - return hb_language_from_string ("ga-Latg", -1); /* Irish; Latin (Gaelic variant) */ + return hb_language_from_string ("ghc", -1); /* Hiberno-Scottish Gaelic */ case HB_TAG('J','I','I',' '): /* Yiddish */ return hb_language_from_string ("yi", -1); /* Yiddish [macrolanguage] */ case HB_TAG('K','A','L',' '): /* Kalenjin */ @@ -2899,7 +2939,7 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("ms", -1); /* Malay [macrolanguage] */ case HB_TAG('M','N','K',' '): /* Maninka */ return hb_language_from_string ("man", -1); /* Mandingo [macrolanguage] */ - case HB_TAG('M','O','L',' '): /* Romanian (Moldova) */ + case HB_TAG('M','O','L',' '): /* Moldavian */ return hb_language_from_string ("ro-MD", -1); /* Romanian; Moldova */ case HB_TAG('M','O','N','T'): /* Thailand Mon */ return hb_language_from_string ("mnw-TH", -1); /* Mon; Thailand */ @@ -2927,6 +2967,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("ro", -1); /* Romanian */ case HB_TAG('R','O','Y',' '): /* Romany */ return hb_language_from_string ("rom", -1); /* Romany [macrolanguage] */ + case HB_TAG('S','G','A',' '): /* Old Irish */ + return hb_language_from_string ("sga", -1); /* Old Irish (to 900) */ case HB_TAG('S','R','B',' '): /* Serbian */ return hb_language_from_string ("sr", -1); /* Serbian */ case HB_TAG('S','X','T',' '): /* Sutu */ @@ -2943,6 +2985,10 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("tmh", -1); /* Tamashek [macrolanguage] */ case HB_TAG('T','O','D',' '): /* Todo */ return hb_language_from_string ("xwo", -1); /* Written Oirat */ + case HB_TAG('W','D','T',' '): /* Wendat */ + return hb_language_from_string ("wdt", -1); /* Wendat */ + case HB_TAG('W','Y','N',' '): /* Wyandot */ + return hb_language_from_string ("wyn", -1); /* Wyandot */ case HB_TAG('Z','H','H',' '): /* Chinese, Traditional, Hong Kong SAR */ return hb_language_from_string ("zh-HK", -1); /* Chinese [macrolanguage]; Hong Kong */ case HB_TAG('Z','H','S',' '): /* Chinese, Simplified */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh index 08227aa1df..efbbfb25d7 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh @@ -33,213 +33,6 @@ namespace OT { -template <typename MapCountT> -struct DeltaSetIndexMapFormat01 -{ - friend struct DeltaSetIndexMap; - - unsigned get_size () const - { return min_size + mapCount * get_width (); } - - private: - DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - return_trace (c->embed (this)); - } - - template <typename T> - bool serialize (hb_serialize_context_t *c, const T &plan) - { - unsigned int width = plan.get_width (); - unsigned int inner_bit_count = plan.get_inner_bit_count (); - const hb_array_t<const uint32_t> output_map = plan.get_output_map (); - - TRACE_SERIALIZE (this); - if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0)))) - return_trace (false); - if (unlikely (!c->extend_min (this))) return_trace (false); - - entryFormat = ((width-1)<<4)|(inner_bit_count-1); - mapCount = output_map.length; - HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length); - if (unlikely (!p)) return_trace (false); - for (unsigned int i = 0; i < output_map.length; i++) - { - unsigned int v = output_map.arrayZ[i]; - if (v) - { - unsigned int outer = v >> 16; - unsigned int inner = v & 0xFFFF; - unsigned int u = (outer << inner_bit_count) | inner; - for (unsigned int w = width; w > 0;) - { - p[--w] = u; - u >>= 8; - } - } - p += width; - } - return_trace (true); - } - - uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */ - { - /* If count is zero, pass value unchanged. This takes - * care of direct mapping for advance map. */ - if (!mapCount) - return v; - - if (v >= mapCount) - v = mapCount - 1; - - unsigned int u = 0; - { /* Fetch it. */ - unsigned int w = get_width (); - const HBUINT8 *p = mapDataZ.arrayZ + w * v; - for (; w; w--) - u = (u << 8) + *p++; - } - - { /* Repack it. */ - unsigned int n = get_inner_bit_count (); - unsigned int outer = u >> n; - unsigned int inner = u & ((1 << n) - 1); - u = (outer<<16) | inner; - } - - return u; - } - - unsigned get_map_count () const { return mapCount; } - unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; } - unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; } - - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - hb_barrier () && - c->check_range (mapDataZ.arrayZ, - mapCount, - get_width ())); - } - - protected: - HBUINT8 format; /* Format identifier--format = 0 */ - HBUINT8 entryFormat; /* A packed field that describes the compressed - * representation of delta-set indices. */ - MapCountT mapCount; /* The number of mapping entries. */ - UnsizedArrayOf<HBUINT8> - mapDataZ; /* The delta-set index mapping data. */ - - public: - DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ); -}; - -struct DeltaSetIndexMap -{ - template <typename T> - bool serialize (hb_serialize_context_t *c, const T &plan) - { - TRACE_SERIALIZE (this); - unsigned length = plan.get_output_map ().length; - u.format = length <= 0xFFFF ? 0 : 1; - switch (u.format) { - case 0: return_trace (u.format0.serialize (c, plan)); - case 1: return_trace (u.format1.serialize (c, plan)); - default:return_trace (false); - } - } - - uint32_t map (unsigned v) const - { - switch (u.format) { - case 0: return (u.format0.map (v)); - case 1: return (u.format1.map (v)); - default:return v; - } - } - - unsigned get_map_count () const - { - switch (u.format) { - case 0: return u.format0.get_map_count (); - case 1: return u.format1.get_map_count (); - default:return 0; - } - } - - unsigned get_width () const - { - switch (u.format) { - case 0: return u.format0.get_width (); - case 1: return u.format1.get_width (); - default:return 0; - } - } - - unsigned get_inner_bit_count () const - { - switch (u.format) { - case 0: return u.format0.get_inner_bit_count (); - case 1: return u.format1.get_inner_bit_count (); - default:return 0; - } - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (!u.format.sanitize (c)) return_trace (false); - hb_barrier (); - switch (u.format) { - case 0: return_trace (u.format0.sanitize (c)); - case 1: return_trace (u.format1.sanitize (c)); - default:return_trace (true); - } - } - - DeltaSetIndexMap* copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - switch (u.format) { - case 0: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c))); - case 1: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c))); - default:return_trace (nullptr); - } - } - - protected: - union { - HBUINT8 format; /* Format identifier */ - DeltaSetIndexMapFormat01<HBUINT16> format0; - DeltaSetIndexMapFormat01<HBUINT32> format1; - } u; - public: - DEFINE_SIZE_UNION (1, format); -}; - - -struct ItemVarStoreInstancer -{ - ItemVarStoreInstancer (const ItemVariationStore *varStore, - const DeltaSetIndexMap *varIdxMap, - hb_array_t<int> coords) : - varStore (varStore), varIdxMap (varIdxMap), coords (coords) {} - - operator bool () const { return varStore && bool (coords); } - - /* according to the spec, if colr table has varStore but does not have - * varIdxMap, then an implicit identity mapping is used */ - float operator() (uint32_t varIdx, unsigned short offset = 0) const - { return coords ? varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords) : 0; } - - const ItemVariationStore *varStore; - const DeltaSetIndexMap *varIdxMap; - hb_array_t<int> coords; -}; /* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */ struct TupleVariationHeader @@ -305,9 +98,9 @@ struct TupleVariationHeader return true; } - double calculate_scalar (hb_array_t<int> coords, unsigned int coord_count, - const hb_array_t<const F2DOT14> shared_tuples, - const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const + double calculate_scalar (hb_array_t<const int> coords, unsigned int coord_count, + const hb_array_t<const F2DOT14> shared_tuples, + const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const { const F2DOT14 *peak_tuple; @@ -428,13 +221,6 @@ struct TupleVariationHeader DEFINE_SIZE_MIN (4); }; -enum packed_delta_flag_t -{ - DELTAS_ARE_ZERO = 0x80, - DELTAS_ARE_WORDS = 0x40, - DELTA_RUN_COUNT_MASK = 0x3F -}; - struct tuple_delta_t { static constexpr bool realloc_move = true; // Watch out when adding new members! @@ -452,8 +238,8 @@ struct tuple_delta_t /* compiled data: header and deltas * compiled point data is saved in a hashmap within tuple_variations_t cause * some point sets might be reused by different tuple variations */ - hb_vector_t<char> compiled_tuple_header; - hb_vector_t<char> compiled_deltas; + hb_vector_t<unsigned char> compiled_tuple_header; + hb_vector_t<unsigned char> compiled_deltas; /* compiled peak coords, empty for non-gvar tuples */ hb_vector_t<char> compiled_peak_coords; @@ -728,10 +514,10 @@ struct tuple_delta_t bool compile_deltas () { return compile_deltas (indices, deltas_x, deltas_y, compiled_deltas); } - bool compile_deltas (const hb_vector_t<bool> &point_indices, - const hb_vector_t<double> &x_deltas, - const hb_vector_t<double> &y_deltas, - hb_vector_t<char> &compiled_deltas /* OUT */) + static bool compile_deltas (const hb_vector_t<bool> &point_indices, + const hb_vector_t<double> &x_deltas, + const hb_vector_t<double> &y_deltas, + hb_vector_t<unsigned char> &compiled_deltas /* OUT */) { hb_vector_t<int> rounded_deltas; if (unlikely (!rounded_deltas.alloc (point_indices.length))) @@ -745,15 +531,14 @@ struct tuple_delta_t } if (!rounded_deltas) return true; - /* allocate enough memories 3 * num_deltas */ - unsigned alloc_len = 3 * rounded_deltas.length; + /* allocate enough memories 5 * num_deltas */ + unsigned alloc_len = 5 * rounded_deltas.length; if (y_deltas) alloc_len *= 2; if (unlikely (!compiled_deltas.resize (alloc_len))) return false; - unsigned i = 0; - unsigned encoded_len = encode_delta_run (i, compiled_deltas.as_array (), rounded_deltas); + unsigned encoded_len = compile_deltas (compiled_deltas, rounded_deltas); if (y_deltas) { @@ -770,174 +555,15 @@ struct tuple_delta_t } if (j != rounded_deltas.length) return false; - /* reset i because we reuse rounded_deltas for y_deltas */ - i = 0; - encoded_len += encode_delta_run (i, compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas); + encoded_len += compile_deltas (compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas); } return compiled_deltas.resize (encoded_len); } - unsigned encode_delta_run (unsigned& i, - hb_array_t<char> encoded_bytes, - const hb_vector_t<int>& deltas) const - { - unsigned num_deltas = deltas.length; - unsigned encoded_len = 0; - while (i < num_deltas) - { - int val = deltas.arrayZ[i]; - if (val == 0) - encoded_len += encode_delta_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), deltas); - else if (val >= -128 && val <= 127) - encoded_len += encode_delta_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), deltas); - else - encoded_len += encode_delta_run_as_words (i, encoded_bytes.sub_array (encoded_len), deltas); - } - return encoded_len; - } - - unsigned encode_delta_run_as_zeroes (unsigned& i, - hb_array_t<char> encoded_bytes, - const hb_vector_t<int>& deltas) const - { - unsigned num_deltas = deltas.length; - unsigned run_length = 0; - auto it = encoded_bytes.iter (); - unsigned encoded_len = 0; - while (i < num_deltas && deltas.arrayZ[i] == 0) - { - i++; - run_length++; - } - - while (run_length >= 64) - { - *it++ = char (DELTAS_ARE_ZERO | 63); - run_length -= 64; - encoded_len++; - } - - if (run_length) - { - *it++ = char (DELTAS_ARE_ZERO | (run_length - 1)); - encoded_len++; - } - return encoded_len; - } - - unsigned encode_delta_run_as_bytes (unsigned &i, - hb_array_t<char> encoded_bytes, - const hb_vector_t<int>& deltas) const - { - unsigned start = i; - unsigned num_deltas = deltas.length; - while (i < num_deltas) - { - int val = deltas.arrayZ[i]; - if (val > 127 || val < -128) - break; - - /* from fonttools: if there're 2 or more zeros in a sequence, - * it is better to start a new run to save bytes. */ - if (val == 0 && i + 1 < num_deltas && deltas.arrayZ[i+1] == 0) - break; - - i++; - } - unsigned run_length = i - start; - - unsigned encoded_len = 0; - auto it = encoded_bytes.iter (); - - while (run_length >= 64) - { - *it++ = 63; - encoded_len++; - - for (unsigned j = 0; j < 64; j++) - { - *it++ = static_cast<char> (deltas.arrayZ[start + j]); - encoded_len++; - } - - start += 64; - run_length -= 64; - } - - if (run_length) - { - *it++ = run_length - 1; - encoded_len++; - - while (start < i) - { - *it++ = static_cast<char> (deltas.arrayZ[start++]); - encoded_len++; - } - } - - return encoded_len; - } - - unsigned encode_delta_run_as_words (unsigned &i, - hb_array_t<char> encoded_bytes, - const hb_vector_t<int>& deltas) const + static unsigned compile_deltas (hb_array_t<unsigned char> encoded_bytes, + hb_array_t<const int> deltas) { - unsigned start = i; - unsigned num_deltas = deltas.length; - while (i < num_deltas) - { - int val = deltas.arrayZ[i]; - - /* start a new run for a single zero value*/ - if (val == 0) break; - - /* from fonttools: continue word-encoded run if there's only one - * single value in the range [-128, 127] because it is more compact. - * Only start a new run when there're 2 continuous such values. */ - if (val >= -128 && val <= 127 && - i + 1 < num_deltas && - deltas.arrayZ[i+1] >= -128 && deltas.arrayZ[i+1] <= 127) - break; - - i++; - } - - unsigned run_length = i - start; - auto it = encoded_bytes.iter (); - unsigned encoded_len = 0; - while (run_length >= 64) - { - *it++ = (DELTAS_ARE_WORDS | 63); - encoded_len++; - - for (unsigned j = 0; j < 64; j++) - { - int16_t delta_val = deltas.arrayZ[start + j]; - *it++ = static_cast<char> (delta_val >> 8); - *it++ = static_cast<char> (delta_val & 0xFF); - - encoded_len += 2; - } - - start += 64; - run_length -= 64; - } - - if (run_length) - { - *it++ = (DELTAS_ARE_WORDS | (run_length - 1)); - encoded_len++; - while (start < i) - { - int16_t delta_val = deltas.arrayZ[start++]; - *it++ = static_cast<char> (delta_val >> 8); - *it++ = static_cast<char> (delta_val & 0xFF); - - encoded_len += 2; - } - } - return encoded_len; + return TupleValues::compile (deltas, encoded_bytes); } bool calc_inferred_deltas (const contour_point_vector_t& orig_points) @@ -1079,20 +705,20 @@ struct tuple_delta_t opt_indices.arrayZ[i] = false; } - hb_vector_t<char> opt_point_data; + hb_vector_t<unsigned char> opt_point_data; if (!compile_point_set (opt_indices, opt_point_data)) return false; - hb_vector_t<char> opt_deltas_data; + hb_vector_t<unsigned char> opt_deltas_data; if (!compile_deltas (opt_indices, is_comp_glyph_wo_deltas ? opt_deltas_x : deltas_x, is_comp_glyph_wo_deltas ? opt_deltas_y : deltas_y, opt_deltas_data)) return false; - hb_vector_t<char> point_data; + hb_vector_t<unsigned char> point_data; if (!compile_point_set (indices, point_data)) return false; - hb_vector_t<char> deltas_data; + hb_vector_t<unsigned char> deltas_data; if (!compile_deltas (indices, deltas_x, deltas_y, deltas_data)) return false; @@ -1114,7 +740,7 @@ struct tuple_delta_t } static bool compile_point_set (const hb_vector_t<bool> &point_indices, - hb_vector_t<char>& compiled_points /* OUT */) + hb_vector_t<unsigned char>& compiled_points /* OUT */) { unsigned num_points = 0; for (bool i : point_indices) @@ -1316,7 +942,7 @@ struct TupleVariationData bool has_private_points = iterator.current_tuple->has_private_points (); const HBUINT8 *end = p + length; if (has_private_points && - !TupleVariationData::unpack_points (p, private_indices, end)) + !TupleVariationData::decompile_points (p, private_indices, end)) return false; const hb_vector_t<unsigned> &indices = has_private_points ? private_indices : shared_indices; @@ -1326,14 +952,14 @@ struct TupleVariationData hb_vector_t<int> deltas_x; if (unlikely (!deltas_x.resize (num_deltas, false) || - !TupleVariationData::unpack_deltas (p, deltas_x, end))) + !TupleVariationData::decompile_deltas (p, deltas_x, end))) return false; hb_vector_t<int> deltas_y; if (is_gvar) { if (unlikely (!deltas_y.resize (num_deltas, false) || - !TupleVariationData::unpack_deltas (p, deltas_y, end))) + !TupleVariationData::decompile_deltas (p, deltas_y, end))) return false; } @@ -1508,7 +1134,7 @@ struct TupleVariationData continue; } - hb_vector_t<char> compiled_point_data; + hb_vector_t<unsigned char> compiled_point_data; if (!tuple_delta_t::compile_point_set (*points_set, compiled_point_data)) return false; @@ -1700,7 +1326,7 @@ struct TupleVariationData { const HBUINT8 *base = &(table_base+var_data->data); const HBUINT8 *p = base; - if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false; + if (!decompile_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false; data_offset = p - base; } return true; @@ -1750,9 +1376,9 @@ struct TupleVariationData bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); } - static bool unpack_points (const HBUINT8 *&p /* IN/OUT */, - hb_vector_t<unsigned int> &points /* OUT */, - const HBUINT8 *end) + static bool decompile_points (const HBUINT8 *&p /* IN/OUT */, + hb_vector_t<unsigned int> &points /* OUT */, + const HBUINT8 *end) { enum packed_point_flag_t { @@ -1802,43 +1428,13 @@ struct TupleVariationData return true; } - static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */, - hb_vector_t<int> &deltas /* IN/OUT */, - const HBUINT8 *end) + template <typename T> + static bool decompile_deltas (const HBUINT8 *&p /* IN/OUT */, + hb_vector_t<T> &deltas /* IN/OUT */, + const HBUINT8 *end, + bool consume_all = false) { - unsigned i = 0; - unsigned count = deltas.length; - while (i < count) - { - if (unlikely (p + 1 > end)) return false; - unsigned control = *p++; - unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1; - unsigned stop = i + run_count; - if (unlikely (stop > count)) return false; - if (control & DELTAS_ARE_ZERO) - { - for (; i < stop; i++) - deltas.arrayZ[i] = 0; - } - else if (control & DELTAS_ARE_WORDS) - { - if (unlikely (p + run_count * HBUINT16::static_size > end)) return false; - for (; i < stop; i++) - { - deltas.arrayZ[i] = * (const HBINT16 *) p; - p += HBUINT16::static_size; - } - } - else - { - if (unlikely (p + run_count > end)) return false; - for (; i < stop; i++) - { - deltas.arrayZ[i] = * (const HBINT8 *) p++; - } - } - } - return true; + return TupleValues::decompile (p, deltas, end, consume_all); } bool has_data () const { return tupleVarCount; } @@ -2067,7 +1663,9 @@ struct item_variations_t } } - if (!all_regions || !all_unique_regions) return false; + /* regions are empty means no variation data, return true */ + if (!all_regions || !all_unique_regions) return true; + if (!region_list.alloc (all_regions.get_population ())) return false; @@ -2132,7 +1730,8 @@ struct item_variations_t bool as_item_varstore (bool optimize=true, bool use_no_variation_idx=true) { - if (!region_list) return false; + /* return true if no variation data */ + if (!region_list) return true; unsigned num_cols = region_list.length; /* pre-alloc a 2D vector for all sub_table's VarData rows */ unsigned total_rows = 0; @@ -2382,6 +1981,7 @@ struct item_variations_t } }; + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var-cvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-cvar-table.hh index 3798ad3e3e..3931382f13 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-cvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-cvar-table.hh @@ -107,14 +107,14 @@ struct cvar bool has_private_points = iterator.current_tuple->has_private_points (); if (has_private_points && - !TupleVariationData::unpack_points (p, private_indices, end)) + !TupleVariationData::decompile_points (p, private_indices, end)) return false; const hb_vector_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices; bool apply_to_all = (indices.length == 0); unsigned num_deltas = apply_to_all ? num_cvt_item : indices.length; if (unlikely (!unpacked_deltas.resize (num_deltas, false))) return false; - if (unlikely (!TupleVariationData::unpack_deltas (p, unpacked_deltas, end))) return false; + if (unlikely (!TupleVariationData::decompile_deltas (p, unpacked_deltas, end))) return false; for (unsigned int i = 0; i < num_deltas; i++) { diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh index d713084faf..b021a00f66 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh @@ -359,7 +359,10 @@ struct gvar out->glyphCountX = hb_min (0xFFFFu, num_glyphs); unsigned glyph_var_data_size = glyph_vars.compiled_byte_size (); - bool long_offset = glyph_var_data_size & ~0xFFFFu || force_long_offsets; + /* According to the spec: If the short format (Offset16) is used for offsets, + * the value stored is the offset divided by 2, so the maximum data size should + * be 2 * 0xFFFFu, which is 0x1FFFEu */ + bool long_offset = glyph_var_data_size > 0x1FFFEu || force_long_offsets; out->flags = long_offset ? 1 : 0; HBUINT8 *glyph_var_data_offsets = c->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false); @@ -440,7 +443,10 @@ struct gvar subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length; } - bool long_offset = (subset_data_size & ~0xFFFFu); + /* According to the spec: If the short format (Offset16) is used for offsets, + * the value stored is the offset divided by 2, so the maximum data size should + * be 2 * 0xFFFFu, which is 0x1FFFEu */ + bool long_offset = subset_data_size > 0x1FFFEu; #ifdef HB_EXPERIMENTAL_API long_offset = long_offset || (c->plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS); #endif @@ -540,7 +546,7 @@ struct gvar unsigned get_offset (unsigned glyph_count, unsigned i) const { if (unlikely (i > glyph_count)) return 0; - _hb_compiler_memory_r_barrier (); + hb_barrier (); return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2; } @@ -618,7 +624,7 @@ struct gvar public: bool apply_deltas_to_points (hb_codepoint_t glyph, - hb_array_t<int> coords, + hb_array_t<const int> coords, const hb_array_t<contour_point_t> points, bool phantom_only = false) const { @@ -673,16 +679,16 @@ struct gvar bool has_private_points = iterator.current_tuple->has_private_points (); if (has_private_points && - !GlyphVariationData::unpack_points (p, private_indices, end)) + !GlyphVariationData::decompile_points (p, private_indices, end)) return false; const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices; bool apply_to_all = (indices.length == 0); unsigned int num_deltas = apply_to_all ? points.length : indices.length; if (unlikely (!x_deltas.resize (num_deltas, false))) return false; - if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false; + if (unlikely (!GlyphVariationData::decompile_deltas (p, x_deltas, end))) return false; if (unlikely (!y_deltas.resize (num_deltas, false))) return false; - if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false; + if (unlikely (!GlyphVariationData::decompile_deltas (p, y_deltas, end))) return false; if (!apply_to_all) { diff --git a/thirdparty/harfbuzz/src/hb-ot-var-varc-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-varc-table.hh new file mode 100644 index 0000000000..603aeb258c --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-ot-var-varc-table.hh @@ -0,0 +1,32 @@ +/* + * Copyright © 2024 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_VAR_VARC_TABLE_HH +#define HB_OT_VAR_VARC_TABLE_HH + +#include "OT/Var/VARC/VARC.hh" + +#endif /* HB_OT_VAR_VARC_TABLE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-paint-extents.hh b/thirdparty/harfbuzz/src/hb-paint-extents.hh index f172bd42f9..2d4491e071 100644 --- a/thirdparty/harfbuzz/src/hb-paint-extents.hh +++ b/thirdparty/harfbuzz/src/hb-paint-extents.hh @@ -28,169 +28,8 @@ #include "hb.hh" #include "hb-paint.h" +#include "hb-geometry.hh" -typedef struct hb_extents_t -{ - hb_extents_t () {} - hb_extents_t (float xmin, float ymin, float xmax, float ymax) : - xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {} - - bool is_empty () const { return xmin >= xmax || ymin >= ymax; } - bool is_void () const { return xmin > xmax; } - - void union_ (const hb_extents_t &o) - { - xmin = hb_min (xmin, o.xmin); - ymin = hb_min (ymin, o.ymin); - xmax = hb_max (xmax, o.xmax); - ymax = hb_max (ymax, o.ymax); - } - - void intersect (const hb_extents_t &o) - { - xmin = hb_max (xmin, o.xmin); - ymin = hb_max (ymin, o.ymin); - xmax = hb_min (xmax, o.xmax); - ymax = hb_min (ymax, o.ymax); - } - - void - add_point (float x, float y) - { - if (unlikely (is_void ())) - { - xmin = xmax = x; - ymin = ymax = y; - } - else - { - xmin = hb_min (xmin, x); - ymin = hb_min (ymin, y); - xmax = hb_max (xmax, x); - ymax = hb_max (ymax, y); - } - } - - float xmin = 0.f; - float ymin = 0.f; - float xmax = -1.f; - float ymax = -1.f; -} hb_extents_t; - -typedef struct hb_transform_t -{ - hb_transform_t () {} - hb_transform_t (float xx, float yx, - float xy, float yy, - float x0, float y0) : - xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {} - - void multiply (const hb_transform_t &o) - { - /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */ - hb_transform_t r; - - r.xx = o.xx * xx + o.yx * xy; - r.yx = o.xx * yx + o.yx * yy; - - r.xy = o.xy * xx + o.yy * xy; - r.yy = o.xy * yx + o.yy * yy; - - r.x0 = o.x0 * xx + o.y0 * xy + x0; - r.y0 = o.x0 * yx + o.y0 * yy + y0; - - *this = r; - } - - void transform_distance (float &dx, float &dy) const - { - float new_x = xx * dx + xy * dy; - float new_y = yx * dx + yy * dy; - dx = new_x; - dy = new_y; - } - - void transform_point (float &x, float &y) const - { - transform_distance (x, y); - x += x0; - y += y0; - } - - void transform_extents (hb_extents_t &extents) const - { - float quad_x[4], quad_y[4]; - - quad_x[0] = extents.xmin; - quad_y[0] = extents.ymin; - quad_x[1] = extents.xmin; - quad_y[1] = extents.ymax; - quad_x[2] = extents.xmax; - quad_y[2] = extents.ymin; - quad_x[3] = extents.xmax; - quad_y[3] = extents.ymax; - - extents = hb_extents_t {}; - for (unsigned i = 0; i < 4; i++) - { - transform_point (quad_x[i], quad_y[i]); - extents.add_point (quad_x[i], quad_y[i]); - } - } - - float xx = 1.f; - float yx = 0.f; - float xy = 0.f; - float yy = 1.f; - float x0 = 0.f; - float y0 = 0.f; -} hb_transform_t; - -typedef struct hb_bounds_t -{ - enum status_t { - UNBOUNDED, - BOUNDED, - EMPTY, - }; - - hb_bounds_t (status_t status) : status (status) {} - hb_bounds_t (const hb_extents_t &extents) : - status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {} - - void union_ (const hb_bounds_t &o) - { - if (o.status == UNBOUNDED) - status = UNBOUNDED; - else if (o.status == BOUNDED) - { - if (status == EMPTY) - *this = o; - else if (status == BOUNDED) - extents.union_ (o.extents); - } - } - - void intersect (const hb_bounds_t &o) - { - if (o.status == EMPTY) - status = EMPTY; - else if (o.status == BOUNDED) - { - if (status == UNBOUNDED) - *this = o; - else if (status == BOUNDED) - { - extents.intersect (o.extents); - if (extents.is_empty ()) - status = EMPTY; - } - } - } - - status_t status; - hb_extents_t extents; -} hb_bounds_t; typedef struct hb_paint_extents_context_t hb_paint_extents_context_t; @@ -231,7 +70,10 @@ struct hb_paint_extents_context_t const hb_transform_t &t = transforms.tail (); t.transform_extents (extents); - clips.push (hb_bounds_t {extents}); + auto bounds = hb_bounds_t {extents}; + bounds.intersect (clips.tail ()); + + clips.push (bounds); } void pop_clip () diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc index bd5cb5c6be..fbab091e8c 100644 --- a/thirdparty/harfbuzz/src/hb-style.cc +++ b/thirdparty/harfbuzz/src/hb-style.cc @@ -61,8 +61,8 @@ _hb_ratio_to_angle (float r) * @style_tag: a style tag. * * Searches variation axes of a #hb_font_t object for a specific axis first, - * if not set, then tries to get default style values from different - * tables of the font. + * if not set, first tries to get default style values in `STAT` table + * then tries to polyfill from different tables of the font. * * Returns: Corresponding axis or default value to a style tag. * diff --git a/thirdparty/harfbuzz/src/hb-subset-cff2.cc b/thirdparty/harfbuzz/src/hb-subset-cff2.cc index 9c9117d52f..eb5cb0c625 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff2.cc +++ b/thirdparty/harfbuzz/src/hb-subset-cff2.cc @@ -666,9 +666,6 @@ OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c, bool OT::cff2::accelerator_subset_t::subset (hb_subset_context_t *c) const { - if (c->plan->normalized_coords && !c->plan->all_axes_pinned) - fprintf (stdout, "warning: CFF partial instancing is not supported.\n"); - cff2_subset_plan cff2_plan; if (unlikely (!cff2_plan.create (*this, c->plan))) return false; diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc index 8974755a75..b874949df0 100644 --- a/thirdparty/harfbuzz/src/hb-subset-input.cc +++ b/thirdparty/harfbuzz/src/hb-subset-input.cc @@ -412,6 +412,7 @@ hb_subset_input_keep_everything (hb_subset_input_t *input) hb_subset_input_set_flags (input, HB_SUBSET_FLAGS_NOTDEF_OUTLINE | HB_SUBSET_FLAGS_GLYPH_NAMES | + HB_SUBSET_FLAGS_NAME_LEGACY | HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES | HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED); } @@ -730,7 +731,7 @@ hb_subset_input_override_name_table (hb_subset_input_t *input, src = hb_utf8_t::next (src, src_end, &unicode, replacement); if (unicode >= 0x0080u) { - printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n"); + printf ("Non-ascii character detected, ignored...This API supports ascii characters only for mac platform\n"); return false; } } diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc index ca903e2707..ec01575990 100644 --- a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc +++ b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc @@ -376,7 +376,7 @@ double renormalizeValue (double v, const Triple &triple, assert (lower <= def && def <= upper); if (!extrapolate) - v = hb_max (hb_min (v, upper), lower); + v = hb_clamp (v, lower, upper); if (v == def) return 0.0; diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index d657790d54..59020dbe87 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -491,7 +491,7 @@ _collect_base_variation_indices (hb_subset_plan_t* plan) base->collect_variation_indices (plan, varidx_set); const OT::ItemVariationStore &var_store = base->get_var_store (); unsigned subtable_count = var_store.get_sub_table_count (); - + _remap_variation_indices (var_store, varidx_set, plan->normalized_coords, @@ -515,6 +515,7 @@ _cmap_closure (hb_face_t *face, cmap.table->closure_glyphs (unicodes, glyphset); } +#ifndef HB_NO_VAR static void _remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map, const hb_set_t &delta_set_idxes, @@ -531,7 +532,7 @@ _remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map, unsigned var_idx = index_map.map (delta_set_idx); unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX; int delta = 0; - + if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX) { hb_pair_t<unsigned, int> *new_varidx_delta; @@ -547,6 +548,7 @@ _remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map, } variation_idx_delta_map = std::move (delta_set_idx_delta_map); } +#endif static void _colr_closure (hb_subset_plan_t* plan, hb_set_t *glyphs_colred) @@ -570,6 +572,7 @@ static void _colr_closure (hb_subset_plan_t* plan, _remap_indexes (&layer_indices, &plan->colrv1_layers); _remap_palette_indexes (&palette_indices, &plan->colr_palettes); +#ifndef HB_NO_VAR if (!colr.has_var_store () || !variation_indices) return; const OT::ItemVariationStore &var_store = colr.get_var_store (); @@ -600,6 +603,7 @@ static void _colr_closure (hb_subset_plan_t* plan, plan->colrv1_variation_idx_delta_map, plan->colrv1_new_deltaset_idx_varidx_map); } +#endif } static inline void @@ -638,6 +642,36 @@ _remove_invalid_gids (hb_set_t *glyphs, glyphs->del_range (num_glyphs, HB_SET_VALUE_INVALID); } +template<bool GID_ALWAYS_EXISTS = false, typename I, typename F, typename G, hb_requires (hb_is_iterator (I))> +static void +_fill_unicode_and_glyph_map(hb_subset_plan_t *plan, + I unicode_iterator, + F unicode_to_gid_for_iterator, + G unicode_to_gid_general) +{ + for (hb_codepoint_t cp : unicode_iterator) + { + hb_codepoint_t gid = unicode_to_gid_for_iterator(cp); + if (!GID_ALWAYS_EXISTS && gid == HB_MAP_VALUE_INVALID) + { + DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp); + continue; + } + + plan->codepoint_to_glyph->set (cp, gid); + plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); + } +} + +template<bool GID_ALWAYS_EXISTS = false, typename I, typename F, hb_requires (hb_is_iterator (I))> +static void +_fill_unicode_and_glyph_map(hb_subset_plan_t *plan, + I unicode_iterator, + F unicode_to_gid_for_iterator) +{ + _fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator); +} + static void _populate_unicodes_to_retain (const hb_set_t *unicodes, const hb_set_t *glyphs, @@ -657,35 +691,21 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, // not excessively large (eg. an inverted set). plan->unicode_to_new_gid_list.alloc (unicodes->get_population ()); if (!unicode_to_gid) { - for (hb_codepoint_t cp : *unicodes) - { + _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { hb_codepoint_t gid; - if (!cmap.get_nominal_glyph (cp, &gid)) - { - DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp); - continue; + if (!cmap.get_nominal_glyph (cp, &gid)) { + return HB_MAP_VALUE_INVALID; } - - plan->codepoint_to_glyph->set (cp, gid); - plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); - } + return gid; + }); } else { // Use in memory unicode to gid map it's faster then looking up from // the map. This code is mostly duplicated from above to avoid doing // conditionals on the presence of the unicode_to_gid map each // iteration. - for (hb_codepoint_t cp : *unicodes) - { - hb_codepoint_t gid = unicode_to_gid->get (cp); - if (gid == HB_MAP_VALUE_INVALID) - { - DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp); - continue; - } - - plan->codepoint_to_glyph->set (cp, gid); - plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); - } + _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + return unicode_to_gid->get (cp); + }); } } else @@ -715,29 +735,29 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ()); auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes; + for (hb_codepoint_t gid : *glyphs) { auto unicodes = gid_to_unicodes.get (gid); - - for (hb_codepoint_t cp : unicodes) - { - plan->codepoint_to_glyph->set (cp, gid); - plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); - } + _fill_unicode_and_glyph_map<true>(plan, unicodes, [&] (hb_codepoint_t cp) { + return gid; + }, + [&] (hb_codepoint_t cp) { + return unicode_glyphid_map->get(cp); + }); } - for (hb_codepoint_t cp : *unicodes) - { - /* Don't double-add entry. */ + + _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + /* Don't double-add entry. */ if (plan->codepoint_to_glyph->has (cp)) - continue; + return HB_MAP_VALUE_INVALID; - hb_codepoint_t *gid; - if (!unicode_glyphid_map->has(cp, &gid)) - continue; + return unicode_glyphid_map->get(cp); + }, + [&] (hb_codepoint_t cp) { + return unicode_glyphid_map->get(cp); + }); - plan->codepoint_to_glyph->set (cp, *gid); - plan->unicode_to_new_gid_list.push (hb_pair (cp, *gid)); - } plan->unicode_to_new_gid_list.qsort (); } else @@ -746,15 +766,15 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, hb_codepoint_t first = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID; for (; cmap_unicodes->next_range (&first, &last); ) { - for (unsigned cp = first; cp <= last; cp++) - { - hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; + _fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) { + hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; if (!unicodes->has (cp) && !glyphs->has (gid)) - continue; - - plan->codepoint_to_glyph->set (cp, gid); - plan->unicode_to_new_gid_list.push (hb_pair (cp, gid)); - } + return HB_MAP_VALUE_INVALID; + return gid; + }, + [&] (hb_codepoint_t cp) { + return unicode_glyphid_map->get(cp); + }); } } @@ -779,10 +799,6 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, } } -#ifndef HB_COMPOSITE_OPERATIONS_PER_GLYPH -#define HB_COMPOSITE_OPERATIONS_PER_GLYPH 64 -#endif - static unsigned _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, hb_codepoint_t gid, @@ -808,18 +824,6 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, operation_count, depth); -#ifndef HB_NO_VAR_COMPOSITES - for (auto &item : glyph.get_var_composite_iterator ()) - { - operation_count = - _glyf_add_gid_and_children (glyf, - item.get_gid (), - gids_to_retain, - operation_count, - depth); - } -#endif - return operation_count; } @@ -916,13 +920,15 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, plan->_glyphset_colred = cur_glyphset; + // XXX TODO VARC closure / subset + _nameid_closure (plan, drop_tables); /* Populate a full set of glyphs to retain by adding all referenced * composite glyphs. */ if (glyf.has_data ()) for (hb_codepoint_t gid : cur_glyphset) _glyf_add_gid_and_children (glyf, gid, &plan->_glyphset, - cur_glyphset.get_population () * HB_COMPOSITE_OPERATIONS_PER_GLYPH); + cur_glyphset.get_population () * HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH); else plan->_glyphset.union_ (cur_glyphset); #ifndef HB_NO_SUBSET_CFF diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc index f10ef54dbd..7cea9f1837 100644 --- a/thirdparty/harfbuzz/src/hb-subset.cc +++ b/thirdparty/harfbuzz/src/hb-subset.cc @@ -594,14 +594,20 @@ static void _attach_accelerator_data (hb_subset_plan_t* plan, * @input: input to use for the subsetting. * * Subsets a font according to provided input. Returns nullptr - * if the subset operation fails. + * if the subset operation fails or the face has no glyphs. * * Since: 2.9.0 **/ hb_face_t * hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input) { - if (unlikely (!input || !source)) return hb_face_get_empty (); + if (unlikely (!input || !source)) return nullptr; + + if (unlikely (!source->get_num_glyphs ())) + { + DEBUG_MSG (SUBSET, nullptr, "No glyphs in source font."); + return nullptr; + } hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input); if (unlikely (!plan)) { diff --git a/thirdparty/harfbuzz/src/hb-ucd-table.hh b/thirdparty/harfbuzz/src/hb-ucd-table.hh index 8d3807a80f..8731a0bcf8 100644 --- a/thirdparty/harfbuzz/src/hb-ucd-table.hh +++ b/thirdparty/harfbuzz/src/hb-ucd-table.hh @@ -4,7 +4,7 @@ * * ./gen-ucd-table.py ucd.nounihan.grouped.xml * - * on file with this description: Unicode 15.1.0 + * on file with this description: Unicode 16.0.0 */ #ifndef HB_UCD_TABLE_HH @@ -13,7 +13,7 @@ #include "hb.hh" static const hb_script_t -_hb_ucd_sc_map[165] = +_hb_ucd_sc_map[172] = { HB_SCRIPT_COMMON, HB_SCRIPT_INHERITED, HB_SCRIPT_UNKNOWN, HB_SCRIPT_ARABIC, @@ -97,7 +97,10 @@ _hb_ucd_sc_map[165] = HB_SCRIPT_OLD_UYGHUR, HB_SCRIPT_TANGSA, HB_SCRIPT_TOTO, HB_SCRIPT_VITHKUQI, HB_SCRIPT_MATH, HB_SCRIPT_KAWI, - HB_SCRIPT_NAG_MUNDARI, + HB_SCRIPT_NAG_MUNDARI, HB_SCRIPT_GARAY, + HB_SCRIPT_GURUNG_KHEMA, HB_SCRIPT_KIRAT_RAI, + HB_SCRIPT_OL_ONAL, HB_SCRIPT_SUNUWAR, + HB_SCRIPT_TODHRI, HB_SCRIPT_TULU_TIGALARI, }; static const uint16_t _hb_ucd_dm1_p0_map[825] = @@ -868,7 +871,7 @@ _hb_ucd_dm2_u32_map[638] = HB_CODEPOINT_ENCODE3_11_7_14 (0x04E9u, 0x0308u, 0x04EBu), }; static const uint64_t -_hb_ucd_dm2_u64_map[388] = +_hb_ucd_dm2_u64_map[408] = { HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u), @@ -1051,13 +1054,23 @@ _hb_ucd_dm2_u64_map[388] = HB_CODEPOINT_ENCODE3 (0x30F0u, 0x3099u, 0x30F8u), HB_CODEPOINT_ENCODE3 (0x30F1u, 0x3099u, 0x30F9u), HB_CODEPOINT_ENCODE3 (0x30F2u, 0x3099u, 0x30FAu), HB_CODEPOINT_ENCODE3 (0x30FDu, 0x3099u, 0x30FEu), HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C1u, 0x0000u), HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C2u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x105D2u, 0x0307u, 0x105C9u), HB_CODEPOINT_ENCODE3 (0x105DAu, 0x0307u, 0x105E4u), HB_CODEPOINT_ENCODE3 (0x11099u, 0x110BAu, 0x1109Au),HB_CODEPOINT_ENCODE3 (0x1109Bu, 0x110BAu, 0x1109Cu), HB_CODEPOINT_ENCODE3 (0x110A5u, 0x110BAu, 0x110ABu),HB_CODEPOINT_ENCODE3 (0x11131u, 0x11127u, 0x1112Eu), HB_CODEPOINT_ENCODE3 (0x11132u, 0x11127u, 0x1112Fu),HB_CODEPOINT_ENCODE3 (0x11347u, 0x1133Eu, 0x1134Bu), - HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu), - HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu), - HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu), - HB_CODEPOINT_ENCODE3 (0x11935u, 0x11930u, 0x11938u), HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x11382u, 0x113C9u, 0x11383u), + HB_CODEPOINT_ENCODE3 (0x11384u, 0x113BBu, 0x11385u),HB_CODEPOINT_ENCODE3 (0x1138Bu, 0x113C2u, 0x1138Eu), + HB_CODEPOINT_ENCODE3 (0x11390u, 0x113C9u, 0x11391u),HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113B8u, 0x113C7u), + HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113C2u, 0x113C5u),HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113C9u, 0x113C8u), + HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu), + HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu),HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu), + HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu),HB_CODEPOINT_ENCODE3 (0x11935u, 0x11930u, 0x11938u), + HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x1611Eu, 0x16121u),HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x1611Fu, 0x16123u), + HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x16120u, 0x16125u),HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x16129u, 0x16122u), + HB_CODEPOINT_ENCODE3 (0x16121u, 0x1611Fu, 0x16126u),HB_CODEPOINT_ENCODE3 (0x16121u, 0x16120u, 0x16128u), + HB_CODEPOINT_ENCODE3 (0x16122u, 0x1611Fu, 0x16127u),HB_CODEPOINT_ENCODE3 (0x16129u, 0x1611Fu, 0x16124u), + HB_CODEPOINT_ENCODE3 (0x16D63u, 0x16D67u, 0x16D69u),HB_CODEPOINT_ENCODE3 (0x16D67u, 0x16D67u, 0x16D68u), + HB_CODEPOINT_ENCODE3 (0x16D69u, 0x16D67u, 0x16D6Au), HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D158u, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Eu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D170u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D171u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D172u, 0x0000u), @@ -1069,90 +1082,59 @@ _hb_ucd_dm2_u64_map[388] = #ifndef HB_OPTIMIZE_SIZE static const uint8_t -_hb_ucd_u8[17884] = +_hb_ucd_u8[17612] = { - 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24, 7, 7, - 25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 22, 42, - 7, 7, 43, 7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47, + 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 5, 5, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 5, 17, 15, 18, 19, 20, 21, 22, 23, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 25, 26, 5, 27, 28, + 5, 29, 30, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 31, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 33, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73, - 69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83, - 84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34, - 91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96, - 97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105, - 106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, - 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, - 107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117, - 118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131, - 132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146, - 147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122, - 160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173, - 34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177, - 34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122, - 34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188, - 34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191, - 34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197, - 69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211, - 69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122, - 215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220, - 34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122, - 228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236, - 237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34, - 244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34, - 34, 34, 34, 34, 34, 34, 34,246, 34, 34, 34, 34,247,122,122,122, - 34, 34, 34, 34,248,122,122,122,122,122,122,122,122,122,122,122, - 34, 34, 34, 34, 34, 34,249, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34,250,122,122,122,122,122,122,122,122, - 251,122,252,253,122,122,122,122,122,122,122,122,122,122,122,122, - 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254, - 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,255, + 16, 17, 18, 19, 20, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 33, 41, 42, 43, 44, 45, + 46, 47, 48, 39, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 50, 17, 17, 17, 51, 17, 52, 53, 54, 55, 56, 57, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 58, 59, 59, 59, 59, 59, 59, 59, 59, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 17, 61, 62, 17, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 17, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 17, 17, 17, 97, 98, 99,100,100,100,100,100,100,100,100,100,101, + 17, 17, 17, 17,102, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17,103, 17, 17,104,100,100,100,100,100,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 100,105,100,100,100,100,100,100, 17, 17,106,107,100,108,109,110, + 17, 17, 17, 17, 17, 17, 17,111, 17, 17, 17, 17,112,113,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,114, + 17,115,116,100,100,100,100,100,100,100,100,100,117,100,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,118, 39,119,120, + 121,122,123,124,125,126,127,128, 39, 39,129,100,100,100,100,130, + 131,132,133,100,134,135,100,136,137,138,100,100,139,140,141,100, + 142,143,144,145, 39, 39,146,147,148, 39,149,150,100,100,100,100, + 17, 17, 17, 17, 17, 17,151, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17,152,153, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,154, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,155, 17, 17,156,100, + 100,100,100,100,100,100,100,100, 17, 17,157,100,100,100,100,100, + 17, 17, 17,158, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17,159,100,100,100,100,100,100,100,100,100,100,100,100, + 160,161,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,162, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,163, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2, 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, @@ -1189,7 +1171,7 @@ _hb_ucd_u8[17884] = 43, 43, 40, 21, 2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43, 43, 43, 75, 43, 75, 43, 43, 44, 2, 2, 2, 2, 2, 2, 2, 64, 36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44, - 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43, + 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 57, 43, 43, 43, 43, 36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43, 43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86, 87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36, @@ -1262,13 +1244,13 @@ _hb_ucd_u8[17884] = 85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57, 2, 2, 2, 88, 2, 2, 2, 44, 43, 43, 43, 43, 43, 43, 43,109, 43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36, - 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44, - 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64, + 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 2, + 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 2, 43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36, 36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44, 2, 2, 36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93, 2, 2, 7, 7, 7, 7, 7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40, 2, - 16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11, + 16, 16, 16, 16, 34,110, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11, 2, 2, 2, 2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43, 85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44, 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16, @@ -1296,33 +1278,33 @@ _hb_ucd_u8[17884] = 67, 67, 67, 67, 4, 4, 67, 67, 8, 67, 67, 67,145,146, 67, 67, 67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26, 8, 8, 8, 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, - 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, - 67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67, - 67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67, - 26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, 8, 8, - 67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67, 4, 4, 4, 4, - 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, - 8, 8,129,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, - 8,129,148,148,148,148,148,148,148,148,148,148,147, 8, 8, 8, - 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, - 8, 8,144, 26, 8, 8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67, - 67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11, - 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149, - 43, 32, 44, 44, 93, 2, 99, 2, 16, 16, 16,150, 44, 44,150, 44, - 36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57, - 36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61, - 2,121,121, 2,125,126,121, 2, 2, 2, 2, 6, 2,108,121, 2, - 121, 4, 4, 4, 4, 2, 2, 88, 2, 2, 2, 2, 2,120, 2, 2, - 108,151, 2, 2, 2, 2, 2, 2, 67, 2,152,148,148,148,153, 44, - 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44, - 67, 67, 67, 44, 44, 44, 44, 44, 1, 2,154,155, 4, 4, 4, 4, - 4, 67, 4, 4, 4, 4,156,157,158,105,105,105,105, 43, 43, 86, - 159, 40, 40, 67,105,160, 63, 67, 36, 36, 36, 61, 57,161,162, 69, - 36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36, - 67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 55, - 67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67, - 67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, - 36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164, 2, + 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, + 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, + 67, 67, 67, 26, 67, 67, 67, 67, 26, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 8, 8, 8, 8, 67, 67, 67, 67, 67, 67, 67, 26, + 67, 67, 67, 67, 4, 4, 4, 4, 4, 4, 4, 27, 27, 27, 27, 27, + 27, 27, 67, 67, 67, 67, 67, 67, 8, 8,129,147, 8, 8, 8, 8, + 8, 8, 8, 4, 4, 4, 4, 4, 8,129,148,148,148,148,148,148, + 148,148,148,148,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 8, 8, + 8, 8, 8, 8, 8, 8, 4, 8, 8, 8,144, 26, 8, 8,144, 67, + 67, 67, 44, 67, 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, + 32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11, + 32, 32,140, 67, 67,138, 34,149, 43, 32, 44, 44, 93, 2, 99, 2, + 16, 16, 16,150, 44, 44,150, 44, 36, 36, 36, 36, 44, 44, 44, 52, + 64, 44, 44, 44, 44, 44, 44, 57, 36, 36, 36, 61, 44, 44, 44, 44, + 36, 36, 36, 61, 36, 36, 36, 61, 2,121,121, 2,125,126,121, 2, + 2, 2, 2, 6, 2,108,121, 2,121, 4, 4, 4, 4, 2, 2, 88, + 2, 2, 2, 2, 2,120, 2, 2,108,151, 2, 2, 2, 2, 2, 2, + 67, 2,152,148,148,148,153, 44, 67, 67, 67, 67, 67, 55, 67, 67, + 67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44, + 1, 2,154,155, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4,156,157, + 158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67, + 36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69, + 44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67, + 67, 67, 67, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, 92, + 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, + 163, 27, 27, 27, 27, 27, 27, 27, 36, 36, 83, 36, 36, 36, 36, 36, + 67, 67, 67, 92, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,164, 2, 7, 7, 7, 7, 7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70, 51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36,105,105,105,105,105, 43, 2, 2, 2, 44, 44, 44, 44, @@ -1330,7 +1312,7 @@ _hb_ucd_u8[17884] = 16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32, - 32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44, + 32, 32, 11, 11, 34, 34, 32, 44, 32,150,150, 32, 32, 32, 47, 44, 44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36, 36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44, 36, 36, 2, 2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36, @@ -1391,8 +1373,10 @@ _hb_ucd_u8[17884] = 36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93, 2, 64, 44, 44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44, 16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44, - 27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44, - 36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43, + 7, 7, 7, 7, 7, 36, 36, 69, 11, 11, 11, 44, 57, 43, 43,159, + 16, 16, 16, 44, 44, 44, 44, 8, 27, 27, 27, 27, 27, 27, 27,100, + 36, 36, 36, 36, 36, 57,184, 44, 36, 44, 44, 44, 44, 44, 44, 44, + 44, 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30, 2, 2, 44, 44, 44, 36, 43, 43, 2, 2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44, 87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, @@ -1410,14 +1394,18 @@ _hb_ucd_u8[17884] = 86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44, 61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44, - 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43, - 86, 43, 85, 71, 36, 63, 2, 2, 7, 7, 7, 7, 7, 2, 93, 71, - 86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44, - 36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87, - 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 44, - 86, 87, 43, 43, 43, 85, 87, 87, 60, 2, 61, 44, 44, 44, 44, 44, - 2, 2, 2, 2, 2, 2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86, - 43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44, + 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 62, 44, 61, + 36, 36, 36, 62, 86, 87, 43, 43, 80, 90, 89, 89, 86, 90, 86, 85, + 71, 71, 2, 93, 64, 44, 44, 44, 57, 80, 44, 44, 44, 44, 44, 44, + 36, 36, 94, 86, 43, 43, 43, 43, 86, 43, 85, 71, 36, 63, 2, 2, + 7, 7, 7, 7, 7, 2, 93, 71, 86, 87, 43, 43, 85, 85, 86, 87, + 85, 43, 36, 72, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 94, + 86, 43, 43, 44, 86, 86, 43, 87, 60, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 36, 36, 43, 44, 86, 87, 43, 43, 43, 85, 87, 87, + 60, 2, 61, 44, 44, 44, 44, 44, 2, 2, 2, 2, 2, 2, 64, 44, + 36, 36, 36, 36, 36, 70, 87, 86, 43, 43, 43, 87, 63, 44, 44, 44, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 44, 44, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 61, 57, 87, 86, 43, 43, 87, 43, 43, 44, 44, 7, 7, 7, 7, 7, 27, 2, 97, 43, 43, 43, 43, 87, 60, 44, 44, 27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36, 36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71, @@ -1427,49 +1415,52 @@ _hb_ucd_u8[17884] = 2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43, 2, 72, 2, 2, 64, 44, 44, 44, 44, 44, 44, 2, 2, 2, 2, 2, 44, 44, 44, - 43, 43, 43, 80, 43, 43, 43, 87, 63, 2, 2, 44, 44, 44, 44, 44, - 2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44, - 36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57, - 43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36, - 36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44, - 36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36, - 36, 36, 86, 43, 43, 80, 44, 86, 85, 60, 2, 2, 2, 2, 2, 2, + 63, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87, + 63, 2, 2, 44, 44, 44, 44, 44, 2, 36, 36, 36, 36, 36, 36, 36, + 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43, + 85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36, + 70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44, + 36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90, + 43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44, + 43, 94, 36, 36, 36, 36, 36, 36, 36, 36, 86, 43, 43, 80, 44, 86, + 85, 60, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 80, 44, 44, 27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181, 2, 2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44, 65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43, - 43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44, + 43, 43, 43, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 43, + 43, 43, 43, 43, 43, 86, 87, 43, 43, 43, 60, 44, 44, 44, 44, 44, 43, 43, 43, 60, 2, 2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44, 7, 7, 7, 7, 7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30, 2, 64, 44, 44, + 36, 36, 36, 36, 44, 44, 62, 36, 40, 69, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 83,164, 2, 27, 27, 27, 30, 2, 64, 44, 44, 36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57, 43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44, - 86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81, - 36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44, - 36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, - 36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44, - 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44, - 67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86, - 86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67, - 67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44, - 27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16, - 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, - 16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11, - 11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16, - 16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16, - 16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11, - 47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11, - 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11, - 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, - 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, - 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, - 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 43, 43, 43, 76, 67, 50, 43, 43, + 86, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 62, + 40, 40, 52, 40, 40, 40, 52, 81, 36, 61, 44, 44, 44, 44, 44, 44, + 44, 61, 44, 44, 44, 44, 44, 44, 36, 61, 62, 44, 44, 44, 44, 44, + 44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60, + 65, 65, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44, + 43, 43, 43, 80, 44, 44, 44, 44, 67, 67, 67, 92, 55, 67, 67, 67, + 67, 67,186, 87, 43, 67,186, 86, 86,187, 65, 65, 65, 84, 43, 43, + 43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67, + 67, 43, 76, 44, 44, 44, 44, 44, 27, 27, 44, 44, 44, 44, 44, 44, + 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 16, 16, 16,110, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 47, 11, + 44, 47, 48, 47, 48, 11, 47, 11, 11, 11, 11, 16, 16,150,150, 16, + 16, 16,150, 16, 16, 16, 16, 16, 16, 16, 11, 48, 11, 47, 48, 11, + 11, 11, 47, 11, 11, 11, 47, 16, 16, 16, 16, 16, 11, 48, 11, 47, + 11, 11, 47, 47, 44, 11, 11, 11, 47, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, + 16, 16, 16, 44, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, + 11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, + 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, + 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, + 16, 33, 16, 16, 16, 32, 44, 7, 43, 43, 43, 76, 67, 50, 43, 43, 43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67, 67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43, 16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110, @@ -1479,22 +1470,23 @@ _hb_ucd_u8[17884] = 43, 43, 43, 74, 40, 40, 40, 44, 7, 7, 7, 7, 7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43, - 36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27, - 16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27, - 188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163, - 27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36, - 62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44, - 44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62, - 62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61, - 36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36, - 8, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44, - 55, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, 27, 27, 91, 67, - 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, - 67, 92, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 92, 44, 44, 44, - 67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41, - 67, 67, 67, 67, 44, 44, 67, 67, 67, 67, 67, 92, 44, 55, 67, 67, - 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 55, - 67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 67, 67, 67, 67, 67, 67, + 188, 7, 7, 7, 7,189, 44, 93, 36, 36, 36, 61, 36, 36, 62, 61, + 36, 36, 61,179, 27, 27, 27, 27, 16, 16, 43, 43, 43, 74, 44, 44, + 27, 27, 27, 27, 27, 27,163, 27,190, 27,100, 44, 44, 44, 44, 44, + 27, 27, 27, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, 44, + 36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36, + 36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36, + 62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36, + 36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36, + 62, 36, 62, 36, 36, 62, 36, 36, 8, 44, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, + 27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44, + 44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67, + 67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 92, 44, 44, 44, 67, + 67, 67, 67, 67, 67, 67, 92, 55, 67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,171,171,171,171,171,171,171, 44, 171,171,171,171,171,171,171, 0, 0, 0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9, @@ -1520,366 +1512,350 @@ _hb_ucd_u8[17884] = 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3, 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25, 2, 25, 24, 2, 15, 12, 15, 14, 2, 21, 14, 7, 15, 12, 17, 21, 1, 26, 10, 10, 1, - 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, - 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0, + 7, 13, 13, 2, 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 10, 11, 12, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 19, 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, 17, 18, 19, 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, 0, 0, 0, 20, - 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20, 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 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, 35, 0, 36, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 36, 0, 37, 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, - 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, - 0, 0, 40, 41, 42, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 5, - 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, 16, 18, - 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, 0, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, - 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, - 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, 0, 0, - 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, 62, 63, - 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, 0, 0, - 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, - 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0, - 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 75, 76, 0, 77, 78, 0, - 0, 79, 80, 0, 81, 62, 0, 82, 83, 0, 0, 84, 85, 86, 0, 0, - 0, 87, 0, 88, 0, 0, 51, 89, 51, 0, 90, 0, 91, 0, 0, 0, - 80, 0, 0, 0, 92, 93, 0, 94, 95, 96, 97, 0, 0, 0, 0, 0, - 51, 0, 0, 0, 0, 98, 99, 0, 0, 0, 0, 0, 0,100, 0, 0, - 0, 0, 0,101,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,103, - 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,106, 0, - 0,107, 0, 0, 0, 0, 0, 0,108, 0,109, 0,102, 0, 0, 0, - 0, 0,110,111, 0, 0, 0, 0, 0, 0, 0,112, 0, 0, 0, 0, - 0, 0, 0,113, 0,114, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, - 5, 6, 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, - 0, 13, 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, - 21, 0, 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, - 0, 27, 0, 0, 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, - 33, 0, 0, 35, 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, - 38, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, - 42, 0, 0, 0, 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, - 47, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, - 0, 51, 0, 52, 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, - 0, 56, 0, 0, 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, - 0, 0, 0, 61, 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, - 0, 0, 0, 67, 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, - 0, 0, 77, 78, 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, - 0, 81, 0, 0, 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, - 84, 0, 85, 0, 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, - 0, 0, 0, 88, 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, - 0, 0, 33, 0, 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, - 0, 0, 93, 0, 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, - 0, 0, 98, 0, 0, 0, 99, 0, 0, 0, 0,100,101, 93, 0, 0, - 102, 0, 0, 0, 84, 0, 0,103, 0, 0, 0,104,105, 0, 0,106, - 107, 0, 0, 0, 0, 0, 0,108, 0, 0,109, 0, 0, 0, 0,110, - 33, 0,111,112,113, 35, 0, 0,114, 0, 0, 0,115, 0, 0, 0, - 0, 0, 0,116, 0, 0,117, 0, 0, 0, 0,118, 88, 0, 0, 0, - 0, 0, 57, 0, 0, 0, 0, 52,119, 0, 0, 0, 0,120, 0, 0, - 121, 0, 0, 0, 0,119, 0, 0,122, 0, 0, 0, 0, 0, 0,123, - 0, 0, 0,124, 0, 0, 0,125, 0,126, 0, 0, 0, 0,127,128, - 129, 0,130, 0,131, 0, 0, 0,132,133,134, 0, 77, 0, 0, 0, - 0, 0, 35, 0, 0, 0,135, 0, 0, 0,136, 0, 0,137, 0, 0, - 138, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, - 5, 6, 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, - 18, 1, 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, - 25, 26, 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, - 34, 35, 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, - 42, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, - 21, 0, 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, - 0, 0, 52, 1, 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, - 54, 21, 35, 1, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, - 0, 0, 0, 59, 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, - 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, - 0, 0, 68, 0, 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, - 0, 77, 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, - 0, 80, 0, 0, 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, - 0, 0, 83, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, - 1, 52, 15, 86, 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, - 1, 0, 0, 0, 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, - 0, 78, 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, - 21, 1, 21, 92, 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, - 81, 99,100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, - 0, 0, 0, 61, 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50, - 0, 0, 0, 38, 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68, - 61, 0, 0, 0, 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, - 0, 0, 0,107, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, - 0, 0, 0,108, 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 40, + 0, 0, 0, 0, 0, 0, 41, 42, 43, 0, 44, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, + 0, 0, 4, 5, 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, + 16, 17, 16, 18, 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, + 21, 19, 0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 34, 0, 0, 35, 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, + 0, 0, 0, 0, 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, + 0, 0, 0, 0, 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, + 60, 61, 62, 63, 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, + 67, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 69, 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, + 0, 0, 0, 0, 0, 0, 0, 0, 74, 75, 0, 0, 0, 0, 76, 77, + 0, 78, 79, 0, 0, 80, 81, 0, 82, 62, 0, 83, 84, 0, 0, 85, + 86, 87, 0, 88, 0, 89, 0, 90, 0, 0, 51, 91, 51, 0, 92, 0, + 93, 0, 0, 0, 81, 0, 0, 0, 94, 95, 0, 96, 97, 98, 99, 0, + 0, 0, 0, 0, 51, 0, 0, 0, 0,100,101, 0, 0, 0, 0, 0, + 0,102, 0, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 0, 0,104, + 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,106, 0, 0,107, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,108,109, 0, 0,110, 0, 0, + 0, 0, 0, 0,111, 0,112, 0,105, 0, 0, 0, 0, 0,113,114, + 0, 0, 0, 0, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0,117, + 0,118, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, + 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, + 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, 0, 0, + 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, 0, 27, 0, 0, + 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, 33, 0, 0, 35, + 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, + 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, + 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, 47, 0, 0, 0, + 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, 0, 51, 0, 52, + 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, 0, 56, 0, 0, + 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, 0, 0, 0, 61, + 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, 0, 0, 0, 67, + 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, 0, 0, 77, 78, + 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, 0, 81, 0, 0, + 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, 84, 0, 85, 0, + 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, 0, 0, 0, 88, + 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, 0, 0, 33, 0, + 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, 0, 0, 93, 0, + 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, 0, 0, 98, 0, + 0, 0, 99, 0, 0, 0,100, 0, 0, 0, 0,101,102, 93, 0, 0, + 103, 0, 0, 0, 84, 0, 0,104, 0, 0, 0,105,106, 0, 0,107, + 108, 0, 0, 0, 0, 0, 0,109, 0, 0,110, 0, 0, 0, 0,111, + 33, 0,112,113,114, 57, 0, 0,115, 35, 0, 0,116, 0, 0, 0, + 117, 0, 0, 0, 0, 0, 0,118, 0, 0,119, 0, 0, 0, 0,120, + 88, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 52,121, 0, 0, 0, + 0,122, 0, 0,123, 0, 0, 0, 0,121, 0, 0,124, 0, 0, 0, + 0, 0, 79, 0, 0, 0, 0,125, 0, 0, 0,126, 0, 0, 0,127, + 0,128, 0, 0, 0, 0,129,130,131, 0,132, 0,133, 0, 0, 0, + 134,135,136, 0, 77, 0, 0, 0, 0, 0, 35, 0, 0, 0,137, 0, + 0, 0,138, 0, 0, 0,139, 0, 0,140, 0, 0,141, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, + 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, + 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, + 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, + 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, 42, 0, 0, 0, + 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, 21, 0, 0, 47, + 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, 0, 19, 52, 1, + 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, + 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 59, + 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, 64, 0, + 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, + 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, 0, 77, 0, 0, + 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, 0, 80, 0, 0, + 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, + 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, 1, 52, 15, 86, + 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, 1, 0, 0, 0, + 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, 0, 78, 0, 0, + 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, 21, 1, 21, 92, + 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, 81, 99,100, 4, + 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 61, + 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50, 0, 0, 0, 38, + 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68, 61, 0, 0, 0, + 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, 0, 0, 0,107, + 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, + 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0, 0, 0, 49, 50, 0, 0, 19, 58, 0, 0, 0, 51, 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61, 0, 0,113, 0, 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0, 78, 55, - 0, 38, 1, 58, 1, 58, 0, 0, 63, 89, 0, 0,115, 0, 0, 0, - 55, 0, 0, 0, 0,115, 0, 0, 0, 0, 61, 0, 0, 0, 0, 79, - 0, 61, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 79, 0, 0, 0, - 8, 91, 0, 0, 1, 87, 0, 0,116, 0, 0, 0, 0, 0, 0,117, - 0,118,119,120,121, 0,104, 4,122, 49, 23, 0, 0, 0, 38, 50, - 38, 58, 0, 0, 1, 87, 1, 1, 1, 1, 39, 1, 48,105, 87, 0, - 0, 0, 0, 1, 0, 0, 0,123, 4,122, 0, 0, 0, 1,124, 0, - 0, 0, 0, 0,230,230,230,230,230,232,220,220,220,220,232,216, - 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220, - 1, 1, 1, 1, 1,220,220,220,220,230,230,230,230,240,230,220, - 220,220,230,230,230,220,220, 0,230,230,230,220,220,220,220,230, - 232,220,220,230,233,234,234,233,234,234,233,230, 0, 0, 0,230, - 0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220, - 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, - 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, - 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230, - 220,230,230,220, 35, 0, 0, 0, 0, 0,230,230,230, 0, 0,230, - 230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0,230,220,230,230, - 220,220,230,220,220,230,220,230,220,230,230, 0, 0,220, 0, 0, - 230,230, 0,230, 0,230,230,230,230,230, 0, 0, 0,220,220,220, - 230,220,220,220,230,230, 0,220, 27, 28, 29,230, 7, 0, 0, 0, - 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0,230, 0, - 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 9, 0, - 103,103, 9, 0,107,107,107,107,118,118, 9, 0,122,122,122,122, - 220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0, 0,129,130, 0, - 132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0,130, 0,230,230, - 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7, 0, 9, 9, 0, - 9, 9, 0, 0, 0,230, 0, 0, 0,228, 0, 0, 0,222,230,220, - 220, 0, 0, 0,230, 0, 0,220,230,220, 0,220,230,230,230, 0, - 0, 0, 9, 9, 0, 0, 7, 0,230, 0, 1, 1, 1, 0, 0, 0, - 230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230, - 233,220,230,220,230,230, 1, 1, 1, 1, 1,230, 0, 1, 1,230, - 220,230, 1, 1, 0, 0,218,228,232,222,224,224, 0, 8, 8, 0, - 0, 0, 0,220,230, 0,230,230,220, 0, 0,230, 0, 0, 26, 0, - 0,220, 0,230,230, 1,220, 0, 0,230,220, 0, 0, 0,220,220, - 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, - 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, 0, 0, - 0,226,216,216,216,216,216, 0,220,220,220, 0,232,232,220,230, - 230,230, 7, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19, - 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17, + 0, 38, 1, 58, 1, 58, 0, 0, 0, 0, 0, 88, 63, 89, 0, 0, + 115, 0, 0, 0, 55, 0, 0, 0, 0,115, 0, 0, 0, 0, 61, 0, + 0, 0, 0, 79, 0, 61, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, + 79, 0, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0,116, 0, 0, 0, + 0, 0, 0,117, 0,118,119,120,121, 0,104, 4,122, 49, 23, 0, + 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1, 1, 1, 39, 1, + 48,105, 87, 0, 0, 0, 0, 1, 0, 0, 0,123, 0, 0, 0,112, + 4,122, 0, 0, 0, 1,124, 0, 0, 0, 0, 0,230,230,230,230, + 230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220, + 220,220,220,202,202,220,220,220, 1, 1, 1, 1, 1,220,220,220, + 220,230,230,230,230,240,230,220,220,220,230,230,230,220,220, 0, + 230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233, + 234,234,233,230, 0, 0, 0,230, 0,220,230,230,230,230,220,230, + 230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0, + 230,220, 0, 18, 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31, + 32, 33, 34,230,230,220,220,230,220,230,230,220, 35, 0, 0, 0, + 0, 0,230,230,230, 0, 0,230,230, 0,220,230,230,220, 0, 0, + 0, 36, 0, 0,230,220,230,230,220,220,230,220,220,230,220,230, + 220,230,230, 0, 0,220, 0, 0,230,230, 0,230, 0,230,230,230, + 230,230, 0, 0, 0,220,220,220,230,220,220,220,230,230, 0,220, + 27, 28, 29,230, 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230, + 230, 0, 0, 0, 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, + 9, 0, 0, 0, 0, 0, 9, 0,103,103, 9, 0,107,107,107,107, + 118,118, 9, 0,122,122,122,122,220,220, 0, 0, 0,220, 0,220, + 0,216, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130, + 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, + 0, 0, 0, 7, 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0, + 0,228, 0, 0, 0,222,230,220,220, 0, 0, 0,230, 0, 0,220, + 230,220, 0,220,230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0, + 230, 0, 1, 1, 1, 0, 0, 0,230,234,214,220,202,230,230,230, + 230,230,232,228,228,220,218,230,233,220,230,220,230,230, 1, 1, + 1, 1, 1,230, 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228, + 232,222,224,224, 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230, + 220, 0, 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, + 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, + 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, + 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0, + 220,220,220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 17, + 17, 17, 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113, + 129,169, 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17,237, 0, 1, 2, 2, 0, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, 0, 0, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, - 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, 25, 26, 0, 27, 0, 28, - 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 36, 0, - 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, - 0, 0, 0, 0, 1, 2, 40, 41, 0, 1, 2, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, - 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, - 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 11, 12, - 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, 0, 1, 17, 18, 0, 19, - 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, 20, 20, 20, 20, 20, 8, - 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, 25, 0, 0, 0, 26, 27, - 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, 30, 31, 0, 0, 20, 0, - 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 20, 20, - 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20, - 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20, - 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0, - 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, 0, 1, 0, 1, 0, 0, - 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45, - 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 46, 7, 1, 10, 1, - 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 26, 34, 9, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0, - 0, 0, 26, 21, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13, - 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42, 7, 7, 43, 7, - 44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, + 9, 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, + 23, 24, 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, + 0, 0, 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, + 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, + 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, + 0, 0, 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, + 20, 20, 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, + 20, 20, 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, + 28, 29, 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, + 0, 10, 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, + 36, 34, 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, + 21, 1, 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, + 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 21, 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, + 0, 0, 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, + 1, 20, 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 20, 20, 20, 20, 20, 20, + 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 20, 33, + 34, 35, 34, 34, 36, 37, 20, 20, 20, 20, 20, 20, 38, 20, 39, 40, + 41, 41, 41, 41, 41, 42, 43, 44, 20, 20, 20, 20, 20, 20, 20, 45, + 46, 20, 20, 47, 20, 20, 20, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 20, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45, 0, 0, 1, - 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2, 53, 54, 55, 56, - 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61, - 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109, - 110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123, - 124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138, - 139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151, - 152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164, - 164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169, - 169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173, - 173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182, - 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, - 182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182, - 182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189, - 190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197, - 198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208, - 208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212, - 213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218, - 219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226, - 59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233, - 59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70, - 70, 70, 70, 70, 70,241, 70, 70, 70, 70,242, 96, 96, 96, 70, 70, - 70, 70,243, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, - 70, 70, 70, 70,244, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70,245, 96, 96, 96, 96, 96, 96, 96, 96,246, 96, - 247,248, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, - 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 0, 19, 0, - 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, - 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, - 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2, - 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 2, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 2, 4, 4, 4, 2, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, - 2, 2, 2, 2, 2, 2, 14, 14, 14, 2, 2, 2, 2, 14, 14, 14, - 14, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, - 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 3, - 3, 3, 3, 3, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, - 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 2, 2, 95, 2, 37, 37, 37, 2, 2, 2, 2, 2, 3, 3, - 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, - 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, - 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 5, 5, - 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, - 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, - 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, - 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2, - 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5, - 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 11, - 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, - 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, - 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11, - 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11, - 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2, - 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 10, - 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, - 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, - 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10, - 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2, - 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, - 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21, - 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, - 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, - 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21, - 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2, - 2, 2, 2, 21, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21, - 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22, - 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22, - 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 2, - 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, - 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, - 2, 2, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2, - 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 23, 23, - 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, - 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2, - 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 2, 16, - 16, 16, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 2, 2, - 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 2, 36, - 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, - 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, 2, - 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, - 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18, - 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18, - 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, - 18, 18, 18, 18, 18, 2, 18, 18, 2, 2, 18, 18, 18, 18, 25, 25, - 25, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 2, 2, 2, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, - 25, 25, 25, 0, 0, 0, 0, 25, 25, 2, 2, 2, 2, 2, 33, 33, - 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 2, 8, 2, 2, 2, 2, 2, 8, 2, 2, 8, 8, - 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, - 30, 30, 30, 30, 30, 2, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, - 30, 30, 30, 2, 2, 2, 30, 30, 2, 2, 2, 2, 2, 2, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, - 28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 0, 0, 0, 35, 35, 35, 2, 2, 2, 2, 2, 2, 2, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 0, 0, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 2, 2, 31, 31, - 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 2, 2, 2, 2, 32, 2, - 2, 2, 2, 2, 2, 2, 32, 32, 32, 2, 2, 2, 2, 2, 28, 28, - 28, 28, 28, 28, 2, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, 2, 2, 2, 2, 48, 2, - 2, 2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 2, 2, 2, 2, 58, 58, - 2, 2, 2, 2, 2, 2, 58, 58, 58, 2, 2, 2, 58, 58, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 91, 91, - 91, 91, 91, 2, 2, 91, 91, 91, 2, 2, 2, 2, 2, 2, 91, 91, - 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 2, 2, 2, 62, 62, - 62, 62, 62, 62, 62, 2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 13, 13, + 13, 61, 62, 13, 13, 13, 13, 63, 13, 13, 13, 13, 13, 13, 64, 65, + 20, 20, 66, 20, 13, 13, 13, 13, 67, 13, 13, 13, 68, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2, + 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9, + 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, + 4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14, + 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37, + 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 2, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 2, 2, 95, 2, 37, 37, + 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, + 2, 2, 2, 2, 2, 3, 3, 3, 0, 3, 3, 3, 3, 3, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7, + 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, + 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, + 5, 2, 2, 2, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 2, + 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, + 2, 2, 5, 5, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11, + 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 11, 11, 11, 11, 11, 2, + 11, 11, 2, 11, 11, 2, 11, 11, 2, 2, 11, 2, 11, 11, 11, 2, + 2, 11, 11, 11, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, + 11, 11, 11, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 2, + 10, 10, 2, 10, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, 10, 10, + 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 10, 10, + 10, 10, 2, 2, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10, + 10, 10, 10, 10, 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21, + 21, 21, 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 2, + 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21, 21, 2, + 2, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2, + 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, 2, + 22, 22, 2, 22, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2, + 22, 22, 22, 22, 2, 2, 2, 22, 22, 2, 22, 2, 22, 22, 2, 2, + 2, 22, 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 2, 2, 2, 2, 22, 22, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2, + 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2, + 23, 23, 23, 23, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23, 23, 2, + 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23, + 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 2, 2, + 2, 2, 2, 2, 2, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 2, 16, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16, 16, 2, + 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 16, 16, + 16, 16, 2, 2, 16, 16, 2, 16, 16, 16, 2, 2, 2, 2, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2, + 20, 20, 20, 20, 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, + 20, 20, 2, 2, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, + 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 2, 36, 2, 2, 2, 2, 36, 2, 2, 2, 2, 36, 36, 36, + 36, 36, 36, 2, 36, 2, 2, 2, 2, 2, 2, 2, 36, 36, 2, 2, + 36, 36, 36, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 24, 24, + 24, 24, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18, + 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, + 18, 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 18, 18, + 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25, + 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, + 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2, + 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12, + 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, + 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, + 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30, + 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2, + 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2, + 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32, + 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32, + 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48, + 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52, + 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58, + 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91, + 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 2, 62, 62, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 73, 73, - 73, 73, 73, 73, 73, 73, 6, 2, 2, 2, 2, 2, 2, 2, 8, 8, + 73, 73, 73, 73, 73, 73, 6, 6, 6, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 19, 19, @@ -1896,31 +1872,30 @@ _hb_ucd_u8[17884] = 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 0, 0, 2, 2, 2, 2, 0, 0, - 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, - 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 56, 56, - 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55, - 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2, - 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 13, 13, - 13, 13, 13, 13, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13, - 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1, - 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2, - 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 0, 0, - 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 12, 12, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27, + 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, + 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61, + 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 0, 0, + 0, 0, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 1, 1, 1, 12, 12, 13, 13, 13, 13, 0, 0, 0, 0, 2, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 2, 2, 1, 1, 0, 0, 15, 15, 15, 0, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 17, 17, 17, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 0, 12, 12, 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0, - 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 19, 19, - 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, - 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65, + 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 19, 19, + 2, 19, 2, 19, 19, 19, 2, 2, 19, 19, 19, 19, 19, 19, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 2, 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, @@ -1943,36 +1918,38 @@ _hb_ucd_u8[17884] = 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1, - 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 3, 3, - 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, - 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, - 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, - 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0, - 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2, - 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118, - 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40, - 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50, - 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135, - 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104, - 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161, - 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161, - 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,110,110, - 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110, - 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2, - 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, + 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 2, 2, + 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, + 49, 2, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 2, 2, 49, 49, + 49, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, + 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 2, 2, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 2, 2, 2, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 2, 2, 2, 2, 2, 2, 2, 2, 2, 42, 42, 42, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 2, 2, 2, 2, 2,118,118, + 118,118,118,118,118,118,118,118,118, 2, 2, 2, 2, 2, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59, + 59, 59, 59, 59, 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51, + 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 2, 2, 50, 50, 2, 2, 2, 2, 2, 2,135,135, + 135,135,135,135,135,135,135,135,135,135, 2, 2, 2, 2,106,106, + 106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104, + 104,104, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,104,161,161, + 161,161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161, + 161, 2,161,161, 2,161,161,161, 2,161,161,161,161,161,161,161, + 2,161,161, 2, 2, 2,170,170,170,170,170,170,170,170,170,170, + 170,170, 2, 2, 2, 2,110,110,110,110,110,110,110,110,110,110, + 110,110,110,110,110, 2,110,110,110,110,110,110, 2, 2, 19, 19, + 19, 19, 19, 19, 2, 19, 19, 2, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 2, 2, 2, 2, 2, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120, @@ -1998,122 +1975,135 @@ _hb_ucd_u8[17884] = 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130, 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144, - 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,156,156, + 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,165,165, + 165,165,165,165,165,165,165,165,165,165,165,165, 2, 2, 2,165, + 165,165,165,165,165,165, 2, 2, 2, 2, 2, 2,165,165,156,156, 156,156,156,156,156,156,156,156, 2,156,156,156, 2, 2,156,156, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,147,147, - 147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148, - 2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158, - 2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153, - 153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149, - 149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2, - 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101, - 101,101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101, - 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 2, 96, 96,111,111,111,111,111,111,111,111,111,111, - 111,111,111,111,111, 2,100,100,100,100,100,100,100,100, 2, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108, - 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108, - 2, 2, 2, 2, 2, 2,129,129,129,129,129,129,129, 2,129, 2, - 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129, 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109, - 109,109,109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109, - 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107, - 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107, - 107,107,107,107,107,107,107, 2,107,107,107,107,107,107,107, 2, - 107,107, 2,107,107,107,107,107, 2, 1,107,107,107,107,107, 2, - 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, - 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107, - 107,107,107, 2, 2, 2,137,137,137,137,137,137,137,137,137,137, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3,147,147,147,147,147,147,147,147,148,148, + 148,148,148,148,148,148,148,148, 2, 2, 2, 2, 2, 2,158,158, + 158,158,158,158,158,158,158,158, 2, 2, 2, 2, 2, 2,153,153, + 153,153,153,153,153,153,153,153,153,153, 2, 2, 2, 2,149,149, + 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, + 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 2, 2, 2, 94, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101, 2, + 2, 2, 2, 2, 2, 2,101,101, 2, 2, 2, 2, 2, 2, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111, 2,100,100, + 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 2, 2, 2,108,108,108,108,108,108,108,108,108,108, + 2,108,108,108,108,108,108,108, 2, 2, 2, 2, 2, 2,129,129, + 129,129,129,129,129, 2,129, 2,129,129,129,129, 2,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129, 2,129,129,129, + 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109, + 109, 2, 2, 2, 2, 2,109,109, 2, 2, 2, 2, 2, 2,107,107, + 107,107, 2,107,107,107,107,107,107,107,107, 2, 2,107,107, 2, + 2,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2, + 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107, + 2, 1,107,107,107,107,107, 2, 2,107,107,107, 2, 2,107, 2, + 2, 2, 2, 2, 2,107, 2, 2, 2, 2, 2,107,107,107,107,107, + 107,107, 2, 2,107,107,107,107,107,107,107, 2, 2, 2,171,171, + 171,171,171,171,171,171,171,171, 2,171, 2, 2,171, 2,171,171, + 171,171,171,171, 2,171,171, 2,171, 2, 2,171, 2,171,171,171, + 171, 2,171,171,171,171,171, 2, 2, 2, 2, 2, 2, 2, 2,171, + 171, 2, 2, 2, 2, 2,137,137,137,137,137,137,137,137,137,137, 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2,124,124, 124,124,124,124,124,124,124,124, 2, 2, 2, 2, 2, 2,123,123, 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,114,114, 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 2, 2, 2,102,102, - 102,102,102,102,102,102,102,102, 2, 2, 2, 2, 2, 2,126,126, - 126,126,126,126,126,126,126,126,126, 2, 2,126,126,126,126,126, - 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2,142,142, - 142,142,142,142,142,142,142,142,142,142, 2, 2, 2, 2,125,125, - 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154, - 2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154, - 154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2, - 2,154,154,154,154,154,154,154, 2, 2, 2, 2, 2, 2,150,150, - 150,150,150,150,150,150, 2, 2,150,150,150,150,150,150,150,150, - 150,150,150, 2, 2, 2,141,141,141,141,141,141,141,141,140,140, - 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2,121,121, - 121,121,121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2, 7, 7, - 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2, - 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133, - 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134, - 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134, - 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138, - 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138, - 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138, - 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2, - 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, - 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2, - 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145, - 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2,163,163, - 163,163,163,163,163,163,163, 2,163,163,163,163,163,163,163,163, - 163, 2, 2, 2,163,163,163,163, 2, 2, 2, 2, 2, 2, 86, 2, - 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63, - 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157, - 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 2,127,127, - 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 79, 2, + 102,102,102,102,102,102,102,102, 2, 2, 2, 2, 2, 2, 33, 33, + 33, 33, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126, + 126, 2, 2,126,126,126,126,126,126,126, 2, 2, 2, 2,126,126, + 126,126,126,126,126, 2,142,142,142,142,142,142,142,142,142,142, + 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125, + 125, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125,154,154, + 154,154,154,154,154, 2, 2,154, 2, 2,154,154,154,154,154,154, + 154,154, 2,154,154, 2,154,154,154,154,154,154,154,154,154,154, + 154,154,154,154, 2,154,154, 2, 2,154,154,154,154,154,154,154, + 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2, + 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2,141,141, + 141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140, + 140, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121, 2, + 2, 2, 2, 2, 2, 2, 7, 7, 2, 2, 2, 2, 2, 2,169,169, + 169,169,169,169,169,169,169,169, 2, 2, 2, 2, 2, 2,133,133, + 133,133,133,133,133,133,133, 2,133,133,133,133,133,133,133,133, + 133,133,133,133,133, 2,133,133,133,133,133,133, 2, 2,133,133, + 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134, 2, 2, + 134,134,134,134,134,134, 2,134,134,134,134,134,134,134,134,134, + 134,134,134,134,134, 2,138,138,138,138,138,138,138, 2,138,138, + 2,138,138,138,138,138,138,138,138,138,138,138,138,138, 2, 2, + 138, 2,138,138, 2,138,138,138, 2, 2, 2, 2, 2, 2,143,143, + 143,143,143,143, 2,143,143, 2,143,143,143,143,143,143,143,143, + 143,143,143,143,143,143,143,143,143,143,143,143,143, 2,143,143, + 2,143,143,143,143,143,143, 2, 2, 2, 2, 2, 2, 2,143,143, + 2, 2, 2, 2, 2, 2,145,145,145,145,145,145,145,145,145, 2, + 2, 2, 2, 2, 2, 2,163,163,163,163,163,163,163,163,163, 2, + 163,163,163,163,163,163,163,163,163, 2, 2, 2,163,163,163,163, + 163, 2, 2, 2, 2, 2, 86, 2, 2, 2, 2, 2, 2, 2, 22, 22, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2, 63, 63, + 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 63, 63, + 63, 63, 2, 2, 2, 2,157,157,157,157,157,157,157,157,157,157, + 157, 2, 2, 2, 2, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 2, 2, 80, 80, 80, 2, 2, 2, 2, 2,127,127, + 127,127,127,127,127,127,127,127,127,127,127,127,127, 2,166,166, + 166,166,166,166,166,166,166,166, 2, 2, 2, 2, 2, 2, 79, 2, 2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115, 2,115,115, 2, 2, 2, 2,115,115,159,159, 159,159,159,159,159,159,159,159,159,159,159,159,159, 2,159,159, 2, 2, 2, 2, 2, 2,103,103,103,103,103,103,103,103,103,103, 103,103,103,103, 2, 2,119,119,119,119,119,119,119,119,119,119, 119,119,119,119, 2, 2,119,119, 2,119,119,119,119,119, 2, 2, - 2, 2, 2,119,119,119,146,146,146,146,146,146,146,146,146,146, + 2, 2, 2,119,119,119,167,167,167,167,167,167,167,167,167,167, + 2, 2, 2, 2, 2, 2,146,146,146,146,146,146,146,146,146,146, 146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 2, 2, 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136,136,136,136,136,136,136,155,155, - 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2,136, 2, - 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17, - 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17, - 17, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, 2, 15, 15, - 15, 2, 2, 17, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139, - 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105, - 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105, - 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105, - 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, - 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, - 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131, - 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131, - 131,131,131,131,131,131, 2, 2, 2, 2, 2, 19, 19, 19, 56, 56, - 56, 56, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, - 2, 56, 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2, 6, 6, - 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,151,151, - 151,151,151,151,151,151,151,151,151,151,151, 2, 2, 2,151,151, - 151,151,151,151, 2, 2,151,151, 2, 2, 2, 2,151,151,160,160, - 160,160,160,160,160,160,160,160,160,160,160,160,160, 2,152,152, - 152,152,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164, - 164,164,164,164,164,164,164,164, 2, 2, 2, 2, 2, 2, 30, 30, - 30, 30, 2, 30, 30, 2,113,113,113,113,113,113,113,113,113,113, - 113,113,113, 2, 2,113,113,113,113,113,113,113,113, 2,132,132, - 132,132,132,132,132,132,132,132,132,132, 2, 2, 2, 2,132,132, - 2, 2, 2, 2,132,132, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, - 3, 2, 3, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, - 3, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, - 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, - 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, - 3, 3, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0, + 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2, 2, 2, + 2, 2, 2, 2, 2,155,136, 2, 2, 2, 2, 2, 2, 2, 17, 17, + 17, 17, 2, 17, 17, 17, 17, 17, 17, 17, 2, 17, 17, 2, 17, 15, + 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2, + 15, 2, 2, 2, 2, 2, 15, 15, 15, 2, 2, 17, 2, 2, 2, 2, + 2, 2, 17, 17, 17, 17,139,139,139,139,139,139,139,139,139,139, + 139,139, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105, + 105, 2, 2, 2, 2, 2,105,105,105,105,105, 2, 2, 2,105, 2, + 2, 2, 2, 2, 2, 2,105,105, 2, 2,105,105,105,105, 1, 1, + 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,131,131, + 131,131,131,131,131,131,131,131,131,131, 2, 2, 2, 2, 2, 2, + 2,131,131,131,131,131, 2,131,131,131,131,131,131,131, 2, 2, + 2, 2, 2, 19, 19, 19, 56, 56, 56, 56, 56, 56, 56, 2, 56, 2, + 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56, + 56, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 6,151,151,151,151,151,151,151,151,151,151, + 151,151,151, 2, 2, 2,151,151,151,151,151,151, 2, 2,151,151, + 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160, + 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152, + 2, 2, 2, 2, 2,152,164,164,164,164,164,164,164,164,164,164, + 2, 2, 2, 2, 2, 2,168,168,168,168,168,168,168,168,168,168, + 168, 2, 2, 2, 2,168, 30, 30, 30, 30, 2, 30, 30, 2,113,113, + 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113, + 113,113,113,113,113, 2,132,132,132,132,132,132,132,132,132,132, + 132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,132,132, 3, 3, + 3, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, + 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, + 2, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, - 2, 0, 0, 0, 0, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13, + 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 2, 2, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, @@ -2123,13 +2113,13 @@ _hb_ucd_u8[17884] = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 18, 9, 9, 9, 9, 9, 19, 20, 21, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 9, + 9, 9, 9, 9, 24, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 25, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, @@ -2138,7 +2128,7 @@ _hb_ucd_u8[17884] = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2175,23 +2165,29 @@ _hb_ucd_u8[17884] = 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147, 148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 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,162, 0,163, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,164,165, 0, 0, 0, 0, 0, 0, 0,166, 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, + 167, 0, 0, 0,168,169, 0, 0,170, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,171, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,172, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,174, 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,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176, - 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192, - 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 0, 0, + 0, 0,175, 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,176,177, 0, 0, 0, 0,178,179, 0, 0, 0,180,181,182,183, + 184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199, + 200,201,202,203,204,205,206,207,208,209,210,211,212,213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, }; static const uint16_t -_hb_ucd_u16[9344] = +_hb_ucd_u16[10400] = { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, @@ -2210,9 +2206,10 @@ _hb_ucd_u16[9344] = 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140, 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140, 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 168, 169, 48, 48, - 168, 48, 48, 170, 171, 172, 48, 48, 48, 171, 48, 48, 48, 173, 174, 175, - 48, 176, 9, 9, 9, 9, 9, 177, 178, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 168, 169, 48, 48, 168, 48, 48, 170, 171, 172, 48, 48, + 48, 171, 48, 48, 48, 173, 174, 175, 48, 176, 9, 9, 9, 9, 9, 177, + 178, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183, 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193, 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199, @@ -2225,28 +2222,34 @@ _hb_ucd_u16[9344] = 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278, - 279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282, - 209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271, - 271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209, - 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279, - 300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305, - 209, 306, 209, 209, 209, 209, 209, 209, 9, 9, 9, 11, 11, 11, 307, 308, - 13, 13, 13, 13, 13, 13, 309, 310, 11, 11, 311, 48, 48, 48, 312, 313, - 48, 314, 315, 315, 315, 315, 32, 32, 316, 317, 318, 319, 320, 321, 140, 140, - 209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 209, - 325, 326, 327, 328, 136, 48, 48, 48, 48, 329, 178, 48, 48, 48, 48, 330, - 331, 48, 48, 136, 48, 48, 48, 48, 200, 332, 48, 48, 209, 209, 333, 48, - 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209, - 48, 48, 48, 48, 209, 209, 209, 209, 48, 338, 48, 48, 48, 48, 48, 48, - 151, 209, 209, 209, 287, 48, 48, 229, 339, 48, 340, 140, 13, 13, 341, 342, - 13, 343, 48, 48, 48, 48, 344, 345, 31, 346, 347, 348, 13, 13, 13, 349, - 350, 351, 352, 353, 354, 355, 140, 356, 357, 48, 358, 359, 48, 48, 48, 360, - 361, 48, 48, 362, 363, 192, 32, 364, 64, 48, 365, 48, 366, 367, 48, 151, - 76, 48, 48, 368, 369, 370, 371, 372, 48, 48, 373, 374, 375, 376, 48, 377, - 48, 48, 48, 378, 379, 380, 381, 382, 383, 384, 315, 11, 11, 385, 386, 11, - 11, 11, 11, 11, 48, 48, 387, 192, 48, 48, 388, 48, 389, 48, 48, 206, - 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209, + 209, 209, 176, 140, 287, 140, 271, 271, 271, 288, 209, 209, 209, 209, 289, 271, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 290, 291, 209, 209, 292, + 209, 209, 209, 209, 209, 209, 293, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 294, 295, 271, 296, 209, 209, 297, 279, 298, 279, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 279, 279, 279, 279, 279, 279, 279, 279, 299, 300, 279, 279, 279, 301, 279, 302, + 209, 209, 209, 279, 303, 209, 209, 304, 209, 305, 209, 209, 209, 209, 209, 209, + 9, 9, 9, 11, 11, 11, 306, 307, 13, 13, 13, 13, 13, 13, 308, 309, + 11, 11, 310, 48, 48, 48, 311, 312, 48, 313, 314, 314, 314, 314, 32, 32, + 315, 316, 317, 318, 319, 320, 140, 140, 209, 321, 209, 209, 209, 209, 209, 322, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, 140, 209, + 324, 325, 326, 327, 136, 48, 48, 48, 48, 328, 178, 48, 48, 48, 48, 329, + 330, 48, 48, 136, 48, 48, 48, 48, 200, 331, 48, 48, 209, 209, 332, 48, + 209, 333, 334, 209, 335, 336, 209, 209, 334, 209, 209, 336, 209, 209, 209, 209, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 209, 209, 209, 209, + 48, 337, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 151, 209, 209, 209, 338, 48, 48, 229, + 339, 48, 340, 140, 13, 13, 341, 342, 13, 343, 48, 48, 48, 48, 344, 345, + 31, 346, 347, 348, 13, 13, 13, 349, 350, 351, 352, 353, 354, 355, 140, 356, + 357, 48, 358, 359, 48, 48, 48, 360, 361, 48, 48, 362, 363, 192, 32, 364, + 64, 48, 365, 48, 366, 367, 48, 151, 76, 48, 48, 368, 369, 370, 371, 372, + 48, 48, 373, 374, 375, 376, 48, 377, 48, 48, 48, 378, 379, 380, 381, 382, + 383, 384, 314, 11, 11, 385, 386, 11, 11, 11, 11, 11, 48, 48, 387, 192, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 388, 48, 389, 48, 48, 206, + 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140, 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48, 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403, @@ -2257,108 +2260,204 @@ _hb_ucd_u16[9344] = 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430, 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140, 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439, - 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140, - 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140, + 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 48, 48, 48, 388, + 48, 48, 48, 313, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140, 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453, 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271, 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467, 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140, 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474, - 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476, - 48, 48, 477, 478, 140, 140, 140, 479, 48, 464, 480, 48, 62, 481, 140, 48, - 482, 140, 140, 48, 483, 140, 48, 314, 484, 48, 48, 485, 486, 457, 487, 488, - 222, 48, 48, 489, 490, 48, 196, 192, 491, 48, 492, 493, 494, 48, 48, 495, - 222, 48, 48, 496, 497, 498, 499, 500, 48, 97, 501, 502, 503, 140, 140, 140, - 504, 505, 506, 48, 48, 507, 508, 192, 509, 83, 84, 510, 511, 512, 513, 514, - 48, 48, 48, 515, 516, 517, 478, 140, 48, 48, 48, 518, 519, 192, 140, 140, - 48, 48, 520, 521, 522, 523, 140, 140, 48, 48, 48, 524, 525, 192, 526, 140, - 48, 48, 527, 528, 192, 140, 140, 140, 48, 173, 529, 530, 314, 140, 140, 140, - 48, 48, 501, 531, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 532, - 533, 534, 48, 535, 536, 192, 140, 140, 140, 140, 537, 48, 48, 538, 539, 140, - 540, 48, 48, 541, 542, 543, 48, 48, 544, 545, 546, 48, 48, 48, 48, 196, - 547, 140, 140, 140, 140, 140, 140, 140, 84, 48, 520, 548, 549, 148, 175, 550, - 48, 551, 552, 553, 140, 140, 140, 140, 554, 48, 48, 555, 556, 192, 557, 48, - 558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 560, - 561, 115, 48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566, - 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568, - 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 569, - 48, 48, 48, 570, 571, 572, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140, - 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 573, - 48, 48, 48, 574, 575, 576, 577, 578, 48, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 9, 9, 11, 11, 271, 579, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586, - 48, 48, 48, 48, 48, 48, 48, 440, 48, 48, 48, 48, 48, 199, 140, 140, - 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587, - 48, 48, 588, 589, 140, 590, 591, 48, 48, 48, 48, 48, 48, 48, 48, 206, - 48, 48, 48, 48, 48, 48, 71, 151, 196, 592, 593, 140, 140, 140, 140, 140, - 32, 32, 594, 32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140, - 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598, - 599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140, - 140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461, - 9, 603, 11, 604, 605, 606, 241, 9, 607, 608, 609, 610, 611, 9, 603, 11, - 612, 613, 11, 614, 615, 616, 617, 9, 618, 11, 9, 603, 11, 604, 605, 11, - 241, 9, 607, 617, 9, 618, 11, 9, 603, 11, 619, 9, 620, 621, 622, 623, - 11, 624, 9, 625, 626, 627, 628, 11, 629, 9, 630, 11, 631, 632, 632, 632, - 32, 32, 32, 633, 32, 32, 634, 635, 636, 637, 45, 140, 140, 140, 140, 140, - 638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643, 27, 27, 27, 644, 140, - 645, 140, 140, 140, 140, 140, 140, 140, 48, 48, 151, 646, 647, 140, 140, 140, - 140, 48, 648, 140, 48, 48, 649, 650, 140, 140, 140, 140, 140, 48, 651, 192, - 140, 140, 140, 140, 140, 140, 652, 200, 48, 48, 48, 48, 653, 595, 140, 140, - 9, 9, 607, 11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499, - 271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140, - 659, 48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668, - 209, 209, 669, 209, 209, 209, 209, 209, 209, 323, 334, 670, 670, 670, 209, 324, - 671, 209, 209, 209, 209, 209, 209, 209, 209, 209, 672, 140, 140, 140, 673, 209, - 674, 209, 209, 669, 675, 676, 324, 140, 209, 209, 209, 209, 209, 209, 209, 677, - 209, 209, 209, 209, 209, 678, 426, 426, 209, 209, 209, 209, 209, 209, 209, 679, - 209, 209, 209, 209, 209, 176, 669, 427, 669, 209, 209, 209, 680, 176, 209, 209, - 680, 209, 672, 676, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 672, 426, - 675, 209, 209, 681, 682, 669, 675, 675, 209, 683, 209, 209, 288, 140, 140, 192, - 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 207, 48, 48, 48, 48, - 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 100, 48, 48, 48, 48, 48, 48, 204, 140, 140, - 48, 204, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 71, 48, 48, 48, - 48, 48, 48, 140, 140, 140, 140, 140, 684, 140, 570, 570, 570, 570, 570, 570, + 48, 48, 475, 192, 476, 9, 477, 11, 478, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 271, 479, 48, 48, 480, 481, 482, 140, 140, 483, + 48, 464, 484, 48, 62, 485, 140, 48, 486, 140, 140, 48, 487, 140, 48, 313, + 488, 48, 48, 489, 490, 457, 491, 492, 222, 48, 48, 493, 494, 48, 196, 192, + 495, 48, 496, 497, 498, 48, 48, 499, 222, 48, 48, 500, 501, 502, 503, 504, + 48, 97, 505, 506, 507, 140, 140, 140, 508, 509, 510, 48, 48, 511, 512, 192, + 513, 83, 84, 514, 515, 516, 517, 518, 519, 48, 48, 520, 521, 522, 523, 140, + 48, 48, 48, 524, 525, 526, 481, 140, 48, 48, 48, 527, 528, 192, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 529, 530, 531, 532, 140, 140, + 48, 48, 48, 533, 534, 192, 535, 140, 48, 48, 536, 537, 192, 538, 539, 140, + 48, 540, 541, 542, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 505, 543, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 544, + 545, 546, 48, 547, 548, 192, 140, 140, 140, 140, 549, 48, 48, 550, 551, 140, + 552, 48, 48, 553, 554, 555, 48, 48, 556, 557, 558, 48, 48, 48, 48, 196, + 559, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 560, 192, + 84, 48, 529, 561, 562, 148, 175, 563, 48, 564, 565, 566, 140, 140, 140, 140, + 567, 48, 48, 568, 569, 192, 570, 48, 571, 572, 192, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 573, + 574, 115, 48, 575, 576, 577, 140, 140, 140, 140, 140, 100, 271, 578, 579, 580, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 207, 140, 140, 140, 140, 140, 140, + 272, 272, 272, 272, 272, 272, 581, 582, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 583, + 48, 48, 48, 584, 585, 586, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 71, + 48, 48, 48, 48, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 587, 588, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 589, + 48, 48, 48, 590, 591, 592, 593, 594, 48, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 595, 48, 596, 192, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 9, 9, 11, 11, 271, 597, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 48, 598, 599, 600, 600, 601, 602, 140, 140, 140, 140, 603, 604, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 440, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 199, 140, 605, + 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 606, + 48, 48, 607, 608, 140, 609, 610, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 206, + 48, 48, 48, 48, 48, 48, 71, 151, 196, 611, 612, 140, 140, 140, 140, 140, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 192, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, 140, + 32, 32, 613, 32, 614, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, + 209, 209, 615, 209, 209, 209, 616, 617, 618, 209, 619, 209, 209, 209, 287, 140, + 209, 209, 209, 209, 620, 140, 140, 140, 140, 140, 140, 140, 271, 621, 271, 621, + 209, 209, 209, 209, 209, 338, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140, + 9, 622, 11, 623, 624, 625, 241, 9, 626, 627, 628, 629, 630, 9, 622, 11, + 631, 632, 11, 633, 634, 635, 636, 9, 637, 11, 9, 622, 11, 623, 624, 11, + 241, 9, 626, 636, 9, 637, 11, 9, 622, 11, 638, 9, 639, 640, 641, 642, + 11, 643, 9, 644, 645, 646, 647, 11, 648, 9, 649, 11, 650, 538, 538, 538, + 32, 32, 32, 651, 32, 32, 652, 653, 654, 655, 45, 140, 140, 140, 140, 140, + 656, 657, 658, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 659, 660, 661, 27, 27, 27, 662, 140, 663, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 151, 664, 665, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 666, 140, 48, 48, 667, 668, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 669, 192, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 587, 670, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 671, 200, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 672, 614, 140, 140, + 9, 9, 626, 11, 673, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 503, 271, 271, 674, 675, 140, 140, 140, 140, + 503, 271, 676, 677, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 678, 48, 679, 680, 681, 682, 683, 684, 685, 206, 686, 206, 140, 140, 140, 687, + 209, 209, 688, 209, 209, 209, 209, 209, 209, 322, 333, 689, 689, 689, 209, 323, + 690, 209, 209, 209, 209, 209, 209, 209, 209, 209, 691, 140, 140, 140, 692, 209, + 693, 209, 209, 688, 694, 695, 323, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 696, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 697, 426, 426, + 209, 209, 209, 209, 209, 209, 209, 698, 209, 209, 209, 209, 209, 176, 688, 427, + 688, 209, 209, 209, 699, 176, 209, 209, 699, 209, 691, 688, 695, 140, 140, 140, + 209, 209, 209, 209, 209, 322, 691, 426, 700, 209, 209, 209, 701, 702, 176, 694, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 703, 209, 209, 209, 209, 209, 192, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140, + 48, 48, 48, 207, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 481, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 48, + 48, 48, 48, 48, 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 48, 71, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140, 140, 140, 140, + 704, 140, 584, 584, 584, 584, 584, 584, 140, 140, 140, 140, 140, 140, 140, 140, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140, - 391, 391, 391, 391, 391, 391, 391, 685, 391, 391, 391, 391, 391, 391, 391, 686, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 705, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 706, + 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, + 11, 11, 12, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 57, 58, 59, 60, 60, 60, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 7, 4, 4, 4, 4, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 110, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 112, 112, 112, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 114, 0, + 115, 116, 117, 118, 119, 120, 121, 122, 0, 123, 124, 125, 126, 126, 126, 127, + 128, 129, 130, 131, 132, 60, 133, 134, 135, 136, 0, 137, 138, 139, 0, 0, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 0, 126, 126, 126, 126, 126, 126, 126, 126, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 141, 142, 143, 143, 143, 143, 144, 11, 145, 146, 147, 4, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 166, 167, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 126, 126, 126, 126, 126, 169, 126, 170, 171, 172, 19, 173, + 19, 19, 19, 19, 174, 19, 175, 176, 177, 178, 19, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 168, 168, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 206, 206, 206, 207, 208, 209, 168, + 210, 211, 212, 213, 214, 168, 215, 216, 217, 218, 219, 220, 221, 222, 223, 168, + 224, 225, 226, 227, 228, 229, 230, 168, 168, 231, 232, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 168, 168, 258, 259, 260, 261, 262, 263, 264, 265, 168, 168, + 266, 168, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 168, 168, 278, + 279, 280, 281, 168, 282, 283, 284, 168, 168, 168, 168, 285, 286, 287, 288, 289, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291, 168, + 290, 292, 290, 290, 290, 293, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 294, 295, + 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 297, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 298, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 301, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 302, 302, 302, 302, 302, 302, 302, 302, 303, 304, 305, 306, 307, 308, 309, 168, + 168, 168, 168, 168, 168, 310, 168, 168, 168, 311, 312, 168, 313, 314, 315, 316, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 318, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 319, 319, 319, 319, + 319, 319, 319, 320, 321, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 322, + 323, 324, 324, 324, 325, 326, 327, 327, 327, 327, 327, 328, 168, 168, 168, 168, + 329, 330, 331, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 0, 0, 0, 332, 0, 0, 0, 0, 0, 0, 333, 168, 334, 335, 0, 336, + 0, 0, 0, 337, 338, 339, 340, 341, 189, 342, 168, 343, 0, 344, 168, 168, + 0, 345, 346, 347, 348, 349, 0, 0, 0, 0, 350, 0, 0, 0, 0, 351, + 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 353, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 354, 168, 168, 168, + 355, 356, 357, 168, 358, 359, 168, 168, 168, 168, 360, 361, 168, 168, 168, 168, + 168, 168, 168, 362, 168, 168, 168, 363, 168, 168, 168, 168, 168, 168, 168, 364, + 365, 365, 365, 366, 367, 368, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 369, 370, 168, 371, 168, 168, 168, 372, 373, 374, 375, 168, 168, 168, 168, + 376, 0, 377, 378, 0, 0, 379, 380, 381, 382, 168, 168, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 383, 0, 384, 0, 385, + 386, 387, 388, 389, 0, 0, 0, 0, 0, 390, 391, 392, 0, 0, 393, 332, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 394, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 395, 126, 126, 126, + 396, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 397, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 398, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 399, 168, 168, 168, 168, 168, 168, + 126, 126, 126, 126, 126, 126, 126, 126, 399, 168, 168, 168, 168, 168, 168, 168, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 400, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 401, 168, + 402, 0, 168, 168, 7, 7, 7, 403, 0, 1, 2, 3, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 0, 0, 0, 0, 0, 4, 0, 4, 2, 2, 5, 2, 2, 2, 5, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 0, 7, 8, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11, - 12, 13, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, 16, 17, 14, 14, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 20, 21, 21, 21, 22, 20, 21, 21, 21, 21, - 21, 23, 24, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 27, 28, 26, - 29, 30, 31, 32, 31, 31, 31, 31, 33, 34, 35, 31, 31, 31, 36, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 29, 31, 31, 31, 31, - 37, 38, 37, 37, 37, 37, 37, 37, 37, 39, 31, 31, 31, 31, 31, 31, - 40, 40, 40, 40, 40, 40, 41, 26, 42, 42, 42, 42, 42, 42, 42, 43, - 44, 44, 44, 44, 44, 45, 44, 46, 47, 47, 47, 48, 37, 49, 31, 31, - 31, 50, 51, 31, 31, 31, 31, 31, 31, 31, 31, 31, 52, 31, 31, 31, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 53, 55, 53, 53, 53, - 56, 57, 58, 59, 59, 60, 61, 62, 57, 63, 64, 65, 66, 59, 59, 67, - 68, 69, 70, 71, 71, 72, 73, 74, 69, 75, 76, 77, 78, 71, 79, 26, - 80, 81, 82, 83, 83, 84, 85, 86, 81, 87, 88, 26, 89, 83, 90, 91, - 92, 93, 94, 95, 95, 96, 97, 98, 93, 99, 100, 101, 102, 95, 95, 26, - 103, 104, 105, 106, 107, 104, 108, 109, 104, 105, 110, 26, 111, 108, 108, 112, - 113, 114, 115, 113, 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113, - 122, 123, 124, 122, 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130, 26, - 131, 132, 133, 131, 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131, - 136, 137, 138, 139, 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145, 26, - 146, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 149, 26, 26, 26, 26, - 150, 151, 152, 152, 153, 152, 152, 154, 155, 156, 152, 157, 26, 26, 26, 26, - 158, 158, 158, 158, 158, 158, 158, 158, 158, 159, 158, 158, 158, 160, 159, 158, - 158, 158, 158, 159, 158, 158, 158, 161, 158, 161, 162, 163, 26, 26, 26, 26, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, + 0, 0, 0, 0, 7, 8, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 11, 12, 13, 14, 14, 15, 14, 14, 14, + 14, 14, 14, 14, 16, 17, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 20, 21, + 21, 21, 22, 20, 21, 21, 21, 21, 21, 23, 24, 25, 25, 25, 25, 25, + 25, 26, 25, 25, 25, 27, 28, 26, 29, 30, 31, 32, 31, 31, 31, 31, + 33, 34, 35, 31, 31, 31, 36, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 29, 31, 31, 31, 31, 37, 38, 37, 37, 37, 37, 37, 37, + 37, 39, 31, 31, 31, 31, 31, 31, 40, 40, 40, 40, 40, 40, 41, 26, + 42, 42, 42, 42, 42, 42, 42, 43, 44, 44, 44, 44, 44, 45, 44, 46, + 47, 47, 47, 48, 37, 49, 31, 31, 31, 50, 51, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 52, 31, 31, 31, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 54, 53, 55, 53, 53, 53, 56, 57, 58, 59, 59, 60, 61, 62, + 57, 63, 64, 65, 66, 59, 59, 67, 68, 69, 70, 71, 71, 72, 73, 74, + 69, 75, 76, 77, 78, 71, 79, 26, 80, 81, 82, 83, 83, 84, 85, 86, + 81, 87, 88, 26, 89, 83, 90, 91, 92, 93, 94, 95, 95, 96, 97, 98, + 93, 99, 100, 101, 102, 95, 95, 26, 103, 104, 105, 106, 107, 104, 108, 109, + 104, 105, 110, 26, 111, 108, 108, 112, 113, 114, 115, 113, 113, 115, 113, 116, + 114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122, 122, 124, 125, 126, + 123, 127, 128, 128, 129, 122, 130, 26, 131, 132, 133, 131, 131, 131, 131, 131, + 132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139, 137, 137, 140, 141, + 138, 142, 143, 137, 144, 137, 145, 26, 146, 147, 147, 147, 147, 147, 147, 148, + 147, 147, 147, 149, 26, 26, 26, 26, 150, 151, 152, 152, 153, 152, 152, 154, + 155, 156, 152, 157, 26, 26, 26, 26, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 159, 158, 158, 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161, + 158, 161, 162, 163, 26, 26, 26, 26, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 165, 165, 165, 165, 166, 167, 165, 165, 165, 165, 165, 168, - 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, - 170, 170, 170, 170, 170, 170, 170, 170, 170, 171, 172, 171, 170, 170, 170, 170, - 170, 171, 170, 170, 170, 170, 171, 172, 171, 170, 172, 170, 170, 170, 170, 170, - 170, 170, 171, 170, 170, 170, 170, 170, 170, 170, 170, 173, 170, 170, 170, 174, - 170, 170, 170, 175, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 177, 177, - 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 171, 172, 171, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 171, 172, + 171, 170, 172, 170, 170, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 170, + 170, 170, 170, 173, 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 177, 177, 178, 178, 178, 178, 178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181, 181, 181, 181, 181, 181, 182, 181, 183, 184, 184, 185, 186, 187, 187, 188, 26, 189, 189, 190, 26, 191, 192, 193, 26, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 195, 194, 196, 194, 196, @@ -2368,208 +2467,164 @@ _hb_ucd_u16[9344] = 210, 210, 210, 210, 210, 211, 210, 210, 210, 212, 210, 213, 194, 194, 194, 194, 214, 214, 214, 215, 216, 216, 216, 216, 216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219, 216, 220, 9, 9, 9, 221, 26, 26, 26, 26, 26, 26, - 222, 222, 222, 222, 222, 222, 222, 222, 222, 223, 222, 222, 222, 222, 222, 224, - 225, 225, 225, 225, 225, 225, 225, 225, 226, 226, 226, 226, 226, 226, 227, 228, - 229, 229, 229, 229, 229, 229, 229, 230, 229, 231, 232, 232, 232, 232, 232, 232, - 18, 233, 165, 165, 165, 165, 165, 234, 225, 26, 235, 9, 236, 237, 238, 239, - 2, 2, 2, 2, 240, 241, 2, 2, 2, 2, 2, 242, 243, 244, 2, 245, - 2, 2, 2, 2, 2, 2, 2, 246, 9, 9, 9, 9, 9, 9, 9, 9, - 14, 14, 247, 247, 14, 14, 14, 14, 247, 247, 14, 248, 14, 14, 14, 247, - 14, 14, 14, 14, 14, 14, 249, 14, 249, 14, 250, 251, 14, 14, 252, 253, - 0, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 256, 257, - 0, 258, 2, 259, 0, 0, 0, 0, 260, 26, 9, 9, 9, 9, 261, 26, - 0, 0, 0, 0, 262, 263, 4, 0, 0, 264, 0, 0, 2, 2, 2, 2, - 2, 265, 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, 258, 26, 26, 26, 0, 266, 26, 26, 0, 0, 0, 0, - 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, - 0, 0, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 2, 2, 2, 2, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 271, 272, - 165, 165, 165, 165, 166, 167, 273, 273, 273, 273, 273, 273, 273, 274, 275, 274, - 170, 170, 172, 26, 172, 172, 172, 172, 172, 172, 172, 172, 18, 18, 18, 18, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276, 26, 26, 26, 26, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 223, 222, 222, 222, 222, 222, 222, + 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227, + 228, 228, 228, 228, 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231, + 18, 232, 165, 165, 165, 165, 165, 233, 224, 26, 234, 9, 235, 236, 237, 238, + 2, 2, 2, 2, 239, 240, 2, 2, 2, 2, 2, 241, 242, 243, 2, 244, + 2, 2, 2, 2, 2, 2, 2, 245, 14, 14, 246, 246, 14, 14, 14, 14, + 246, 246, 14, 247, 14, 14, 14, 246, 14, 14, 14, 14, 14, 14, 248, 14, + 248, 14, 249, 250, 14, 14, 251, 252, 0, 253, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 254, 0, 255, 256, 0, 257, 2, 258, 0, 0, 0, 0, + 259, 26, 9, 9, 9, 9, 260, 26, 0, 0, 0, 0, 261, 262, 4, 0, + 0, 263, 0, 0, 2, 2, 2, 2, 2, 264, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 265, 26, 26, 0, 266, 26, 26, 0, 0, 0, 0, + 267, 267, 267, 267, 267, 267, 267, 267, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 0, 269, 0, 0, 0, 0, 0, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 2, 2, 2, 2, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 271, 272, 165, 165, 165, 165, 166, 167, 273, 273, + 273, 273, 273, 273, 273, 274, 275, 274, 170, 170, 172, 26, 172, 172, 172, 172, + 172, 172, 172, 172, 18, 18, 18, 18, 0, 0, 0, 276, 26, 26, 26, 26, 277, 277, 277, 278, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 279, 26, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 26, 26, 26, 0, 0, 281, 0, 0, 0, 282, 283, 0, 284, 285, 286, 286, 286, 286, 286, 286, 286, 286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291, - 292, 293, 293, 293, 293, 293, 294, 169, 169, 169, 169, 169, 169, 169, 169, 169, - 169, 295, 0, 0, 293, 293, 293, 293, 0, 0, 0, 0, 296, 297, 290, 290, - 169, 169, 169, 295, 0, 0, 0, 0, 0, 0, 0, 0, 169, 169, 169, 298, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 290, 290, 290, 290, 299, + 292, 293, 293, 293, 293, 293, 294, 169, 169, 295, 0, 0, 293, 293, 293, 293, + 0, 0, 0, 0, 276, 296, 290, 290, 169, 169, 169, 295, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 169, 169, 297, 0, 0, 290, 290, 290, 290, 290, 298, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 0, 0, 0, 0, 0, - 277, 277, 277, 277, 277, 277, 277, 277, 0, 0, 0, 0, 0, 0, 0, 0, - 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, - 300, 301, 300, 300, 300, 300, 300, 300, 302, 26, 303, 303, 303, 303, 303, 303, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 305, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 26, - 0, 0, 0, 0, 307, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 308, 2, 2, 2, 2, 2, 2, 2, 309, 310, 311, 26, 26, 312, 2, - 313, 313, 313, 313, 313, 314, 0, 315, 316, 316, 316, 316, 316, 316, 316, 26, - 317, 317, 317, 317, 317, 317, 317, 317, 318, 319, 317, 320, 53, 53, 53, 53, - 321, 321, 321, 321, 321, 322, 323, 323, 323, 323, 324, 325, 169, 169, 169, 326, - 327, 327, 327, 327, 327, 327, 327, 327, 327, 328, 327, 329, 164, 164, 164, 330, - 331, 331, 331, 331, 331, 331, 332, 26, 331, 333, 331, 334, 164, 164, 164, 164, - 335, 335, 335, 335, 335, 335, 335, 335, 336, 26, 26, 337, 338, 338, 339, 26, - 340, 340, 340, 26, 172, 172, 2, 2, 2, 2, 2, 341, 342, 343, 176, 176, - 176, 176, 176, 176, 176, 176, 176, 176, 338, 338, 338, 338, 338, 344, 338, 345, - 169, 169, 169, 169, 346, 26, 169, 169, 295, 347, 169, 169, 169, 169, 169, 346, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 348, 26, 26, 26, 26, - 349, 26, 350, 351, 25, 25, 352, 353, 354, 25, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 355, 26, 356, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 357, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 358, 31, 31, 31, 31, 31, 31, 359, 26, 26, 26, 26, 31, 31, - 9, 9, 0, 315, 9, 360, 0, 0, 0, 0, 361, 0, 258, 296, 362, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 363, - 364, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 365, 290, 289, 290, - 290, 290, 290, 366, 169, 169, 169, 295, 367, 367, 367, 368, 258, 258, 26, 369, - 370, 371, 370, 370, 372, 370, 370, 373, 370, 374, 370, 374, 26, 26, 26, 26, - 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 375, - 376, 0, 0, 0, 0, 0, 377, 0, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 253, 0, 378, 379, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 380, - 381, 381, 381, 382, 383, 383, 383, 383, 383, 383, 384, 26, 385, 0, 0, 296, - 386, 386, 386, 386, 387, 388, 389, 389, 389, 390, 391, 391, 391, 391, 391, 392, - 393, 393, 393, 394, 395, 395, 395, 395, 396, 395, 397, 26, 26, 26, 26, 26, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 399, 399, 399, 399, 399, 399, - 400, 400, 400, 401, 400, 402, 403, 403, 403, 403, 404, 403, 403, 403, 403, 404, - 405, 405, 405, 405, 405, 26, 406, 406, 406, 406, 406, 406, 407, 408, 409, 410, - 409, 410, 411, 409, 412, 409, 412, 413, 26, 26, 26, 26, 26, 26, 26, 26, - 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, - 414, 414, 414, 414, 414, 414, 415, 26, 414, 414, 416, 26, 414, 26, 26, 26, - 417, 2, 2, 2, 2, 2, 418, 309, 26, 26, 26, 26, 26, 26, 26, 26, - 419, 420, 421, 421, 421, 421, 422, 423, 424, 424, 425, 424, 426, 426, 426, 426, - 427, 427, 427, 428, 429, 427, 26, 26, 26, 26, 26, 26, 430, 430, 431, 432, - 433, 433, 433, 434, 435, 435, 435, 436, 26, 26, 26, 26, 26, 26, 26, 26, - 437, 437, 437, 437, 438, 438, 438, 439, 438, 438, 440, 438, 438, 438, 438, 438, - 441, 442, 443, 444, 445, 445, 446, 447, 445, 448, 445, 448, 449, 449, 449, 449, - 450, 450, 450, 450, 26, 26, 26, 26, 451, 451, 451, 451, 452, 453, 452, 26, - 454, 454, 454, 454, 454, 454, 455, 456, 457, 457, 458, 457, 459, 459, 460, 459, - 461, 461, 462, 463, 26, 464, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 465, 465, 465, 465, 465, 465, 465, 465, 465, 466, 26, 26, 26, 26, 26, 26, - 467, 467, 467, 467, 467, 467, 468, 26, 467, 467, 467, 467, 467, 467, 468, 469, - 470, 470, 470, 470, 470, 26, 470, 471, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 50, - 472, 472, 472, 472, 472, 473, 474, 26, 26, 26, 26, 26, 26, 26, 26, 475, - 476, 476, 476, 476, 476, 26, 477, 477, 477, 477, 477, 478, 26, 26, 479, 479, - 479, 480, 26, 26, 26, 26, 481, 481, 481, 482, 26, 26, 483, 483, 484, 26, - 485, 485, 485, 485, 485, 485, 485, 485, 485, 486, 487, 485, 485, 485, 486, 488, - 489, 489, 489, 489, 489, 489, 489, 489, 490, 491, 492, 492, 492, 493, 492, 494, - 495, 495, 495, 495, 495, 495, 496, 495, 495, 26, 497, 497, 497, 497, 498, 26, - 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 500, 137, 501, 26, - 502, 502, 503, 502, 502, 502, 502, 502, 504, 26, 26, 26, 26, 26, 26, 26, - 505, 506, 507, 508, 507, 509, 510, 510, 510, 510, 510, 510, 510, 511, 510, 512, - 513, 514, 515, 516, 516, 517, 518, 519, 514, 520, 521, 522, 523, 524, 524, 26, - 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 526, 527, 26, 26, 26, - 528, 528, 528, 528, 528, 528, 528, 528, 528, 26, 528, 529, 26, 26, 26, 26, - 530, 530, 530, 530, 530, 530, 531, 530, 530, 530, 530, 531, 26, 26, 26, 26, - 532, 532, 532, 532, 532, 532, 532, 532, 533, 26, 532, 534, 198, 535, 26, 26, - 536, 536, 536, 536, 536, 536, 536, 537, 536, 537, 26, 26, 26, 26, 26, 26, - 538, 538, 538, 539, 538, 540, 538, 538, 541, 26, 26, 26, 26, 26, 26, 26, - 542, 542, 542, 542, 542, 542, 542, 543, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 545, 546, - 547, 548, 549, 550, 550, 550, 551, 552, 547, 26, 550, 553, 26, 26, 26, 26, - 26, 26, 26, 26, 554, 555, 554, 554, 554, 554, 554, 555, 556, 26, 26, 26, - 557, 557, 557, 557, 557, 557, 557, 557, 557, 26, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 559, 26, 178, 178, 560, 560, 560, 560, 560, 560, 560, 561, - 53, 562, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 563, 564, 563, 563, 563, 563, 565, 563, 566, 26, 563, 563, 563, 567, 568, 568, - 568, 568, 569, 568, 568, 570, 571, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 572, 573, 574, 574, 574, 574, 572, 575, 574, 26, 574, 576, 577, 578, 579, 579, - 579, 580, 581, 582, 579, 583, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 584, 584, 584, 585, - 586, 586, 587, 586, 586, 586, 586, 588, 586, 586, 586, 589, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 590, 26, 108, 108, 108, 108, 108, 108, 591, 592, - 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, - 593, 593, 593, 594, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 595, 596, 26, - 593, 593, 593, 593, 593, 593, 593, 593, 597, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 599, 26, - 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, - 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 601, 26, 26, 26, 26, 26, - 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, - 602, 602, 602, 602, 602, 602, 602, 602, 603, 26, 26, 26, 26, 26, 26, 26, - 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 604, 605, 605, 605, 606, 605, 607, 608, 608, - 608, 608, 608, 608, 608, 608, 608, 609, 608, 610, 611, 611, 611, 612, 612, 26, - 613, 613, 613, 613, 613, 613, 613, 613, 614, 26, 613, 615, 615, 613, 613, 616, - 613, 613, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 617, 617, 617, 617, 617, 617, 617, 617, - 617, 617, 617, 618, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 619, 619, 619, 619, 619, 619, 619, 619, 619, 620, 619, 619, 619, 619, 619, 619, - 619, 621, 619, 619, 26, 26, 26, 26, 26, 26, 26, 26, 622, 26, 348, 26, - 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, - 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 26, - 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, - 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 625, 26, 26, 26, 26, 26, - 623, 626, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 627, 628, - 629, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 630, 26, 631, 26, 26, 26, 632, 26, 633, 26, 634, 634, - 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, - 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 635, - 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 637, 636, 638, - 636, 639, 636, 640, 296, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 9, 9, 9, 9, 9, 641, 9, 9, 221, 26, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 296, 26, 26, 26, 26, 26, 26, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276, 26, - 0, 0, 0, 0, 258, 364, 0, 0, 0, 0, 0, 0, 642, 643, 0, 644, - 645, 646, 0, 0, 0, 647, 0, 0, 0, 0, 0, 0, 0, 266, 26, 26, - 14, 14, 14, 14, 14, 14, 14, 14, 247, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 296, 26, 0, 0, 296, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258, 26, 0, 0, 0, 260, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, - 0, 0, 0, 255, 648, 649, 0, 650, 651, 0, 0, 0, 0, 0, 0, 0, - 269, 652, 255, 255, 0, 0, 0, 653, 654, 655, 656, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, - 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, - 657, 658, 26, 659, 660, 657, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 2, 2, 2, 349, 661, 309, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 662, 270, 270, 663, 664, 665, 18, 18, 18, 18, 18, 18, 18, 666, 26, 26, - 26, 667, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 668, 668, 668, 668, 668, 669, 668, 670, 668, 671, 26, 26, 26, 26, 26, 26, - 26, 26, 672, 672, 672, 673, 26, 26, 674, 674, 674, 674, 674, 674, 674, 675, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 676, 676, 676, 676, 676, 677, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 172, 678, 170, 172, - 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, - 679, 679, 679, 679, 679, 679, 679, 679, 680, 679, 681, 26, 26, 26, 26, 26, - 682, 682, 682, 682, 682, 682, 682, 682, 682, 683, 682, 684, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 364, 0, - 0, 0, 0, 0, 0, 0, 378, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 364, 0, 0, 0, 0, 0, 0, 276, 26, 26, 26, 26, 26, 26, 26, 26, - 685, 31, 31, 31, 686, 687, 688, 689, 690, 691, 686, 692, 686, 688, 688, 693, - 31, 694, 31, 695, 696, 694, 31, 695, 26, 26, 26, 26, 26, 26, 51, 26, - 0, 0, 0, 0, 0, 296, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 296, 26, 0, 258, 364, 0, 364, 0, 364, 0, 0, 0, 276, 26, - 0, 0, 0, 0, 0, 276, 26, 26, 26, 26, 26, 26, 697, 0, 0, 0, - 698, 26, 0, 0, 0, 0, 0, 296, 0, 260, 315, 26, 276, 26, 26, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 699, 0, 378, 0, 378, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258, 700, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 315, 0, 296, 260, 26, - 0, 296, 0, 0, 0, 0, 0, 0, 0, 26, 0, 315, 0, 0, 0, 0, - 0, 26, 0, 0, 0, 276, 315, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 296, 26, 0, 276, 0, 378, - 0, 260, 0, 0, 0, 0, 0, 269, 276, 697, 0, 296, 0, 260, 0, 260, - 0, 0, 361, 0, 0, 0, 0, 0, 0, 266, 26, 26, 26, 26, 0, 315, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 26, 26, 26, 26, - 277, 277, 277, 277, 277, 277, 277, 348, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 348, 26, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 701, 26, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 26, 26, 26, 26, - 277, 277, 277, 280, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 702, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 703, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 299, 299, 299, 299, 299, 299, + 301, 26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 303, 303, 303, + 303, 303, 303, 303, 303, 304, 26, 26, 18, 18, 18, 18, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 26, 0, 0, 0, 0, 306, 2, 2, 2, + 2, 307, 2, 2, 2, 2, 2, 2, 2, 308, 309, 258, 26, 26, 310, 2, + 311, 311, 311, 311, 311, 312, 0, 265, 313, 313, 313, 313, 313, 313, 313, 26, + 314, 314, 314, 314, 314, 314, 314, 314, 315, 316, 314, 317, 53, 53, 53, 53, + 318, 318, 318, 318, 318, 319, 320, 320, 320, 320, 321, 322, 169, 169, 169, 323, + 324, 324, 324, 324, 324, 324, 324, 324, 324, 325, 324, 326, 164, 164, 164, 327, + 328, 328, 328, 328, 328, 328, 329, 26, 328, 330, 328, 331, 164, 164, 164, 164, + 332, 332, 332, 332, 332, 332, 332, 332, 333, 26, 26, 334, 335, 335, 336, 26, + 337, 337, 337, 26, 172, 172, 2, 2, 2, 2, 2, 338, 339, 340, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 335, 335, 335, 335, 335, 341, 335, 342, + 169, 169, 169, 169, 343, 26, 169, 169, 295, 344, 169, 169, 169, 169, 169, 343, + 26, 26, 26, 26, 26, 26, 26, 26, 277, 277, 277, 277, 277, 280, 277, 277, + 277, 277, 277, 345, 26, 26, 26, 26, 346, 26, 347, 348, 25, 25, 349, 350, + 351, 25, 31, 31, 31, 31, 31, 31, 352, 26, 353, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 354, 31, 31, 355, 31, 31, 31, 31, 31, + 31, 356, 26, 26, 26, 26, 31, 31, 9, 9, 0, 265, 9, 357, 0, 0, + 0, 0, 358, 0, 257, 359, 360, 31, 31, 31, 31, 31, 31, 31, 31, 361, + 362, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 363, 290, 289, 290, + 290, 290, 290, 364, 169, 169, 169, 295, 365, 365, 365, 366, 257, 257, 26, 367, + 368, 369, 368, 368, 370, 368, 368, 371, 368, 372, 368, 372, 26, 26, 26, 26, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 373, + 374, 0, 0, 0, 0, 0, 375, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 252, 0, 376, 377, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 378, + 379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382, 26, 383, 0, 0, 359, + 384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390, + 391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395, 26, 26, 26, 26, 26, + 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397, + 398, 398, 398, 399, 398, 400, 401, 401, 401, 401, 402, 401, 401, 401, 401, 402, + 403, 403, 403, 403, 403, 26, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408, + 407, 408, 409, 407, 410, 407, 410, 411, 412, 412, 412, 412, 412, 412, 413, 26, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 415, 26, + 414, 414, 416, 26, 414, 26, 26, 26, 417, 2, 2, 2, 2, 2, 418, 419, + 420, 421, 422, 422, 422, 422, 423, 424, 425, 425, 426, 425, 427, 427, 427, 427, + 428, 428, 428, 429, 430, 428, 26, 26, 26, 26, 26, 26, 431, 431, 432, 433, + 434, 434, 434, 435, 436, 436, 436, 437, 438, 438, 438, 438, 439, 439, 439, 440, + 439, 439, 441, 439, 439, 439, 439, 439, 442, 443, 444, 445, 446, 446, 447, 448, + 446, 449, 446, 449, 450, 450, 450, 450, 451, 451, 451, 451, 26, 26, 26, 26, + 452, 452, 452, 452, 453, 454, 453, 26, 455, 455, 455, 455, 455, 455, 456, 457, + 458, 458, 459, 458, 460, 460, 461, 460, 462, 462, 463, 464, 26, 465, 26, 26, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 467, 26, 26, 26, 26, 26, 26, + 468, 468, 468, 468, 468, 468, 469, 26, 468, 468, 468, 468, 468, 468, 469, 470, + 471, 471, 471, 471, 471, 26, 471, 472, 473, 473, 473, 473, 474, 475, 473, 473, + 474, 476, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 50, + 477, 477, 477, 477, 477, 478, 479, 26, 480, 26, 26, 26, 26, 26, 26, 481, + 482, 482, 482, 482, 482, 26, 483, 483, 483, 483, 483, 484, 26, 26, 485, 485, + 485, 486, 26, 26, 26, 26, 487, 487, 487, 488, 26, 26, 489, 489, 490, 26, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 492, 493, 491, 491, 491, 492, 494, + 495, 495, 495, 495, 495, 495, 495, 495, 496, 497, 498, 498, 498, 499, 498, 500, + 501, 501, 501, 501, 501, 501, 502, 501, 501, 26, 503, 503, 503, 503, 504, 26, + 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 506, 137, 507, 26, + 508, 508, 509, 508, 508, 508, 508, 508, 510, 26, 26, 26, 26, 26, 26, 26, + 511, 512, 513, 514, 513, 515, 516, 516, 516, 516, 516, 516, 516, 517, 516, 518, + 519, 520, 521, 522, 522, 523, 524, 525, 520, 526, 527, 528, 529, 530, 530, 26, + 531, 532, 531, 531, 531, 531, 533, 531, 534, 535, 533, 536, 537, 26, 26, 26, + 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 539, 540, 26, 26, 26, + 541, 541, 541, 541, 541, 541, 541, 541, 541, 26, 541, 542, 26, 26, 26, 26, + 543, 543, 543, 543, 543, 543, 544, 543, 543, 543, 543, 544, 26, 26, 26, 26, + 545, 545, 545, 545, 545, 545, 545, 545, 546, 26, 545, 547, 198, 548, 26, 26, + 549, 549, 549, 549, 549, 549, 549, 550, 549, 550, 164, 164, 551, 26, 26, 26, + 552, 552, 552, 553, 552, 554, 552, 552, 555, 26, 26, 26, 26, 26, 26, 26, + 556, 556, 556, 556, 556, 556, 556, 557, 26, 26, 26, 26, 558, 558, 558, 558, + 558, 558, 558, 558, 558, 558, 559, 560, 561, 562, 563, 564, 564, 564, 565, 566, + 561, 26, 564, 567, 26, 26, 26, 26, 26, 26, 26, 26, 568, 569, 568, 568, + 568, 568, 568, 569, 570, 26, 26, 26, 571, 571, 571, 571, 571, 571, 571, 571, + 571, 26, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 573, 26, 178, 178, + 574, 574, 574, 574, 574, 574, 574, 575, 53, 576, 26, 26, 26, 26, 26, 26, + 577, 577, 577, 577, 578, 26, 577, 578, 579, 580, 579, 579, 579, 579, 581, 579, + 582, 26, 579, 579, 579, 583, 584, 584, 584, 584, 585, 584, 584, 586, 587, 26, + 588, 589, 590, 590, 590, 590, 588, 591, 590, 26, 590, 592, 593, 594, 595, 595, + 595, 596, 597, 598, 595, 599, 26, 26, 26, 26, 26, 26, 600, 600, 600, 601, + 602, 602, 603, 602, 602, 602, 602, 604, 602, 602, 602, 605, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 606, 26, 108, 108, 108, 108, 108, 108, 607, 608, + 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 610, 26, 26, 26, 26, + 609, 609, 609, 609, 609, 611, 612, 26, 613, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 615, 26, + 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 617, 26, 616, 616, 616, 616, + 616, 616, 616, 616, 616, 616, 616, 618, 619, 619, 619, 619, 619, 619, 619, 619, + 620, 26, 26, 26, 26, 26, 26, 26, 621, 621, 621, 621, 621, 621, 621, 622, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 623, + 624, 624, 624, 625, 624, 626, 627, 627, 627, 627, 627, 627, 627, 627, 627, 628, + 627, 629, 630, 630, 630, 631, 631, 26, 632, 632, 632, 632, 632, 632, 632, 632, + 633, 26, 632, 634, 634, 632, 632, 635, 632, 632, 26, 26, 26, 26, 26, 26, + 636, 636, 636, 636, 636, 636, 636, 637, 638, 638, 638, 638, 638, 638, 638, 638, + 638, 638, 638, 639, 26, 26, 26, 26, 640, 640, 640, 640, 640, 640, 640, 640, + 640, 641, 640, 640, 640, 640, 640, 640, 640, 642, 640, 640, 26, 26, 26, 26, + 26, 26, 26, 26, 643, 26, 345, 26, 644, 644, 644, 644, 644, 644, 644, 644, + 644, 644, 644, 644, 644, 644, 644, 26, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 646, 26, 26, 26, 26, 647, 644, 648, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 649, 650, 651, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 652, 26, 653, 26, + 26, 26, 654, 26, 655, 26, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 657, 658, 658, 658, 658, 658, 658, 658, 658, + 658, 658, 658, 658, 658, 659, 658, 660, 658, 661, 658, 662, 359, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 265, 0, 0, 0, 0, 0, 0, 359, 26, + 9, 9, 9, 9, 9, 663, 9, 9, 221, 26, 0, 0, 0, 0, 0, 0, + 359, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 276, 26, + 0, 0, 0, 0, 257, 362, 0, 0, 0, 0, 0, 0, 664, 665, 0, 666, + 667, 668, 0, 0, 0, 669, 0, 0, 0, 0, 0, 0, 0, 266, 26, 26, + 246, 26, 26, 26, 26, 26, 26, 26, 0, 0, 359, 26, 0, 0, 359, 26, + 0, 0, 257, 26, 0, 0, 0, 259, 0, 0, 254, 0, 0, 0, 0, 0, + 0, 0, 0, 254, 670, 671, 0, 672, 673, 0, 0, 0, 0, 0, 0, 0, + 269, 674, 254, 254, 0, 0, 0, 675, 676, 677, 678, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 276, 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, + 679, 679, 679, 679, 679, 679, 679, 679, 679, 680, 26, 681, 682, 679, 26, 26, + 2, 2, 2, 346, 683, 419, 26, 26, 684, 270, 270, 685, 686, 687, 18, 18, + 18, 18, 18, 18, 18, 688, 26, 26, 26, 689, 26, 26, 26, 26, 26, 26, + 690, 690, 690, 690, 690, 691, 690, 692, 690, 693, 26, 26, 26, 26, 26, 26, + 26, 26, 694, 694, 694, 695, 26, 26, 696, 696, 696, 696, 696, 696, 696, 697, + 26, 26, 698, 698, 698, 698, 698, 699, 26, 26, 700, 700, 700, 700, 700, 701, + 26, 26, 26, 26, 172, 702, 170, 172, 703, 703, 703, 703, 703, 703, 703, 703, + 704, 703, 705, 26, 26, 26, 26, 26, 706, 706, 706, 706, 706, 706, 706, 706, + 706, 707, 706, 708, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 362, 0, + 0, 0, 0, 0, 0, 0, 376, 26, 362, 0, 0, 0, 0, 0, 0, 276, + 709, 31, 31, 31, 710, 711, 712, 713, 714, 715, 710, 716, 710, 712, 712, 717, + 31, 718, 31, 719, 720, 718, 31, 719, 26, 26, 26, 26, 26, 26, 721, 26, + 0, 0, 0, 0, 0, 359, 0, 0, 0, 0, 359, 26, 0, 257, 362, 0, + 362, 0, 362, 0, 0, 0, 276, 26, 0, 0, 0, 0, 0, 276, 26, 26, + 26, 26, 26, 26, 722, 0, 0, 0, 723, 26, 0, 0, 0, 0, 0, 359, + 0, 259, 265, 26, 276, 26, 26, 26, 0, 0, 0, 724, 0, 376, 0, 376, + 0, 0, 0, 0, 0, 0, 257, 725, 0, 0, 0, 265, 0, 359, 259, 26, + 0, 359, 0, 0, 0, 0, 0, 0, 0, 26, 0, 265, 0, 0, 0, 0, + 0, 26, 0, 0, 0, 276, 0, 359, 265, 26, 26, 26, 26, 26, 26, 26, + 0, 0, 359, 26, 0, 276, 0, 376, 0, 726, 0, 0, 0, 0, 0, 0, + 257, 722, 0, 727, 0, 265, 0, 259, 0, 0, 358, 0, 0, 0, 0, 0, + 277, 277, 277, 277, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 345, + 277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 345, 26, 277, 277, + 277, 277, 277, 277, 728, 26, 277, 277, 277, 277, 277, 280, 26, 26, 26, 26, + 277, 729, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 26, 26, + 730, 26, 26, 26, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0, @@ -2732,17 +2787,24 @@ _hb_ucd_u16[9344] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575, 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0, 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950, - 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959, - 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0,1939, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1940, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1943,1944, 0, 0, 0, + 0, 0, 0,1945, 0,1946, 0, 0, 0, 0, 0, 0, 0, 0,1947, 0, + 0,1948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1950, 0,1949,1951, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1953,1952, 0,1954, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1955,1956, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1957, 0, 0, 0, 0, 0, 0, 0, + 0,1958,1961,1959,1965,1960,1962,1964,1963, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1967,1966,1968, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1969,1970, + 1971,1972,1973,1974,1975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1976,1977,1978,1980,1979, + 1981, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, @@ -2799,12 +2861,12 @@ _hb_ucd_i16[196] = static inline uint_fast8_t _hb_ucd_gc (unsigned u) { - return u<1114110u?_hb_ucd_u8[6808+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; + return u<1114110u?_hb_ucd_u8[6472+(((_hb_ucd_u8[816+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>4>>4])<<4)+((u>>1>>3>>4)&15u))])<<4)+((u>>1>>3)&15u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; } static inline uint_fast8_t _hb_ucd_ccc (unsigned u) { - return u<125259u?_hb_ucd_u8[8800+(((_hb_ucd_u8[8244+(((_hb_ucd_u8[7784+(((_hb_ucd_u8[7432+(((_hb_ucd_u8[7186+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; + return u<125259u?_hb_ucd_u8[8504+(((_hb_ucd_u8[7936+(((_hb_ucd_u8[7460+(((_hb_ucd_u8[7100+(((_hb_ucd_u8[6854+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; } static inline unsigned _hb_ucd_b4 (const uint8_t* a, unsigned i) @@ -2814,107 +2876,76 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i) static inline int_fast16_t _hb_ucd_bmg (unsigned u) { - return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9548+(((_hb_ucd_u8[9428+(((_hb_ucd_b4(9300+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9252+(((_hb_ucd_u8[9132+(((_hb_ucd_b4(9004+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; } static inline uint_fast8_t _hb_ucd_sc (unsigned u) { - return u<918000u?_hb_ucd_u8[11070+(((_hb_ucd_u16[2048+(((_hb_ucd_u8[10334+(((_hb_ucd_u8[9884+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2; + return u<918000u?_hb_ucd_u8[10486+(((_hb_ucd_u16[3744+(((_hb_ucd_u16[2624+(((_hb_ucd_u8[9588+(u>>3>>3>>4)])<<4)+((u>>3>>3)&15u))])<<3)+((u>>3)&7u))])<<3)+((u)&7u))]:2; } static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[6032+(((_hb_ucd_u8[17084+(((_hb_ucd_u8[16702+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[6976+(((_hb_ucd_u8[16716+(((_hb_ucd_u8[16334+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; } #elif !defined(HB_NO_UCD_UNASSIGNED) static const uint8_t -_hb_ucd_u8[14752] = +_hb_ucd_u8[17524] = { - 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24, 7, 7, - 25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 22, 42, - 7, 7, 43, 7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47, + 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 5, 5, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 5, 17, 15, 18, 19, 20, 21, 22, 23, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 25, 26, 5, 27, 28, + 5, 29, 30, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 31, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 33, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73, - 69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83, - 84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34, - 91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96, - 97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105, - 106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, - 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, - 107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117, - 118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131, - 132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146, - 147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122, - 160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173, - 34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177, - 34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122, - 34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188, - 34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191, - 34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122, - 122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197, - 69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211, - 69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122, - 215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220, - 34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122, - 228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236, - 237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34, - 244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34, - 34, 34, 34, 34, 34, 34, 34,246, 34, 34, 34, 34,247,122,122,122, - 34, 34, 34, 34,248,122,122,122,122,122,122,122,122,122,122,122, - 34, 34, 34, 34, 34, 34,249, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34,250,122,122,122,122,122,122,122,122, - 251,122,252,253,122,122,122,122,122,122,122,122,122,122,122,122, - 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254, - 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,255, + 16, 17, 18, 19, 20, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 33, 41, 42, 43, 44, 45, + 46, 47, 48, 39, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 50, 17, 17, 17, 51, 17, 52, 53, 54, 55, 56, 57, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 58, 59, 59, 59, 59, 59, 59, 59, 59, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 17, 61, 62, 17, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 17, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 17, 17, 17, 97, 98, 99,100,100,100,100,100,100,100,100,100,101, + 17, 17, 17, 17,102, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17,103, 17, 17,104,100,100,100,100,100,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 100,105,100,100,100,100,100,100, 17, 17,106,107,100,108,109,110, + 17, 17, 17, 17, 17, 17, 17,111, 17, 17, 17, 17,112,113,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,114, + 17,115,116,100,100,100,100,100,100,100,100,100,117,100,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,118, 39,119,120, + 121,122,123,124,125,126,127,128, 39, 39,129,100,100,100,100,130, + 131,132,133,100,134,135,100,136,137,138,100,100,139,140,141,100, + 142,143,144,145, 39, 39,146,147,148, 39,149,150,100,100,100,100, + 17, 17, 17, 17, 17, 17,151, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17,152,153, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,154, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,155, 17, 17,156,100, + 100,100,100,100,100,100,100,100, 17, 17,157,100,100,100,100,100, + 17, 17, 17,158, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17,159,100,100,100,100,100,100,100,100,100,100,100,100, + 160,161,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,162, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,163, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2, 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, @@ -2951,7 +2982,7 @@ _hb_ucd_u8[14752] = 43, 43, 40, 21, 2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43, 43, 43, 75, 43, 75, 43, 43, 44, 2, 2, 2, 2, 2, 2, 2, 64, 36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44, - 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43, + 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 57, 43, 43, 43, 43, 36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43, 43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86, 87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36, @@ -3024,13 +3055,13 @@ _hb_ucd_u8[14752] = 85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57, 2, 2, 2, 88, 2, 2, 2, 44, 43, 43, 43, 43, 43, 43, 43,109, 43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36, - 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44, - 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64, + 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 2, + 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 2, 43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36, 36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44, 2, 2, 36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93, 2, 2, 7, 7, 7, 7, 7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40, 2, - 16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11, + 16, 16, 16, 16, 34,110, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11, 2, 2, 2, 2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43, 85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44, 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16, @@ -3058,33 +3089,33 @@ _hb_ucd_u8[14752] = 67, 67, 67, 67, 4, 4, 67, 67, 8, 67, 67, 67,145,146, 67, 67, 67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26, 8, 8, 8, 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, - 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, - 67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67, - 67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67, - 26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, 8, 8, - 67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67, 4, 4, 4, 4, - 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, - 8, 8,129,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, - 8,129,148,148,148,148,148,148,148,148,148,148,147, 8, 8, 8, - 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, - 8, 8,144, 26, 8, 8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67, - 67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11, - 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149, - 43, 32, 44, 44, 93, 2, 99, 2, 16, 16, 16,150, 44, 44,150, 44, - 36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57, - 36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61, - 2,121,121, 2,125,126,121, 2, 2, 2, 2, 6, 2,108,121, 2, - 121, 4, 4, 4, 4, 2, 2, 88, 2, 2, 2, 2, 2,120, 2, 2, - 108,151, 2, 2, 2, 2, 2, 2, 67, 2,152,148,148,148,153, 44, - 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44, - 67, 67, 67, 44, 44, 44, 44, 44, 1, 2,154,155, 4, 4, 4, 4, - 4, 67, 4, 4, 4, 4,156,157,158,105,105,105,105, 43, 43, 86, - 159, 40, 40, 67,105,160, 63, 67, 36, 36, 36, 61, 57,161,162, 69, - 36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36, - 67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 55, - 67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67, - 67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, - 36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164, 2, + 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, + 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, + 67, 67, 67, 26, 67, 67, 67, 67, 26, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 8, 8, 8, 8, 67, 67, 67, 67, 67, 67, 67, 26, + 67, 67, 67, 67, 4, 4, 4, 4, 4, 4, 4, 27, 27, 27, 27, 27, + 27, 27, 67, 67, 67, 67, 67, 67, 8, 8,129,147, 8, 8, 8, 8, + 8, 8, 8, 4, 4, 4, 4, 4, 8,129,148,148,148,148,148,148, + 148,148,148,148,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 8, 8, + 8, 8, 8, 8, 8, 8, 4, 8, 8, 8,144, 26, 8, 8,144, 67, + 67, 67, 44, 67, 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, + 32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11, + 32, 32,140, 67, 67,138, 34,149, 43, 32, 44, 44, 93, 2, 99, 2, + 16, 16, 16,150, 44, 44,150, 44, 36, 36, 36, 36, 44, 44, 44, 52, + 64, 44, 44, 44, 44, 44, 44, 57, 36, 36, 36, 61, 44, 44, 44, 44, + 36, 36, 36, 61, 36, 36, 36, 61, 2,121,121, 2,125,126,121, 2, + 2, 2, 2, 6, 2,108,121, 2,121, 4, 4, 4, 4, 2, 2, 88, + 2, 2, 2, 2, 2,120, 2, 2,108,151, 2, 2, 2, 2, 2, 2, + 67, 2,152,148,148,148,153, 44, 67, 67, 67, 67, 67, 55, 67, 67, + 67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44, + 1, 2,154,155, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4,156,157, + 158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67, + 36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69, + 44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67, + 67, 67, 67, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, 92, + 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, + 163, 27, 27, 27, 27, 27, 27, 27, 36, 36, 83, 36, 36, 36, 36, 36, + 67, 67, 67, 92, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,164, 2, 7, 7, 7, 7, 7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70, 51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36,105,105,105,105,105, 43, 2, 2, 2, 44, 44, 44, 44, @@ -3092,7 +3123,7 @@ _hb_ucd_u8[14752] = 16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32, - 32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44, + 32, 32, 11, 11, 34, 34, 32, 44, 32,150,150, 32, 32, 32, 47, 44, 44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36, 36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44, 36, 36, 2, 2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36, @@ -3153,8 +3184,10 @@ _hb_ucd_u8[14752] = 36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93, 2, 64, 44, 44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44, 16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44, - 27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44, - 36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43, + 7, 7, 7, 7, 7, 36, 36, 69, 11, 11, 11, 44, 57, 43, 43,159, + 16, 16, 16, 44, 44, 44, 44, 8, 27, 27, 27, 27, 27, 27, 27,100, + 36, 36, 36, 36, 36, 57,184, 44, 36, 44, 44, 44, 44, 44, 44, 44, + 44, 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30, 2, 2, 44, 44, 44, 36, 43, 43, 2, 2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44, 87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, @@ -3172,14 +3205,18 @@ _hb_ucd_u8[14752] = 86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44, 61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44, - 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43, - 86, 43, 85, 71, 36, 63, 2, 2, 7, 7, 7, 7, 7, 2, 93, 71, - 86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44, - 36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87, - 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 44, - 86, 87, 43, 43, 43, 85, 87, 87, 60, 2, 61, 44, 44, 44, 44, 44, - 2, 2, 2, 2, 2, 2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86, - 43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44, + 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 62, 44, 61, + 36, 36, 36, 62, 86, 87, 43, 43, 80, 90, 89, 89, 86, 90, 86, 85, + 71, 71, 2, 93, 64, 44, 44, 44, 57, 80, 44, 44, 44, 44, 44, 44, + 36, 36, 94, 86, 43, 43, 43, 43, 86, 43, 85, 71, 36, 63, 2, 2, + 7, 7, 7, 7, 7, 2, 93, 71, 86, 87, 43, 43, 85, 85, 86, 87, + 85, 43, 36, 72, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 94, + 86, 43, 43, 44, 86, 86, 43, 87, 60, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 36, 36, 43, 44, 86, 87, 43, 43, 43, 85, 87, 87, + 60, 2, 61, 44, 44, 44, 44, 44, 2, 2, 2, 2, 2, 2, 64, 44, + 36, 36, 36, 36, 36, 70, 87, 86, 43, 43, 43, 87, 63, 44, 44, 44, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 44, 44, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 61, 57, 87, 86, 43, 43, 87, 43, 43, 44, 44, 7, 7, 7, 7, 7, 27, 2, 97, 43, 43, 43, 43, 87, 60, 44, 44, 27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36, 36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71, @@ -3189,49 +3226,52 @@ _hb_ucd_u8[14752] = 2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43, 2, 72, 2, 2, 64, 44, 44, 44, 44, 44, 44, 2, 2, 2, 2, 2, 44, 44, 44, - 43, 43, 43, 80, 43, 43, 43, 87, 63, 2, 2, 44, 44, 44, 44, 44, - 2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44, - 36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57, - 43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36, - 36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44, - 36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36, - 36, 36, 86, 43, 43, 80, 44, 86, 85, 60, 2, 2, 2, 2, 2, 2, + 63, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87, + 63, 2, 2, 44, 44, 44, 44, 44, 2, 36, 36, 36, 36, 36, 36, 36, + 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43, + 85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36, + 70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44, + 36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90, + 43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44, + 43, 94, 36, 36, 36, 36, 36, 36, 36, 36, 86, 43, 43, 80, 44, 86, + 85, 60, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 80, 44, 44, 27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181, 2, 2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44, 65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43, - 43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44, + 43, 43, 43, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 43, + 43, 43, 43, 43, 43, 86, 87, 43, 43, 43, 60, 44, 44, 44, 44, 44, 43, 43, 43, 60, 2, 2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44, 7, 7, 7, 7, 7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30, 2, 64, 44, 44, + 36, 36, 36, 36, 44, 44, 62, 36, 40, 69, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 83,164, 2, 27, 27, 27, 30, 2, 64, 44, 44, 36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57, 43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44, - 86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81, - 36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44, - 36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, - 36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44, - 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44, - 67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86, - 86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67, - 67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44, - 27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16, - 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, - 16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11, - 11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16, - 16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16, - 16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11, - 47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11, - 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11, - 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, - 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, - 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, - 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 43, 43, 43, 76, 67, 50, 43, 43, + 86, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 62, + 40, 40, 52, 40, 40, 40, 52, 81, 36, 61, 44, 44, 44, 44, 44, 44, + 44, 61, 44, 44, 44, 44, 44, 44, 36, 61, 62, 44, 44, 44, 44, 44, + 44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60, + 65, 65, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44, + 43, 43, 43, 80, 44, 44, 44, 44, 67, 67, 67, 92, 55, 67, 67, 67, + 67, 67,186, 87, 43, 67,186, 86, 86,187, 65, 65, 65, 84, 43, 43, + 43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67, + 67, 43, 76, 44, 44, 44, 44, 44, 27, 27, 44, 44, 44, 44, 44, 44, + 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 16, 16, 16,110, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 47, 11, + 44, 47, 48, 47, 48, 11, 47, 11, 11, 11, 11, 16, 16,150,150, 16, + 16, 16,150, 16, 16, 16, 16, 16, 16, 16, 11, 48, 11, 47, 48, 11, + 11, 11, 47, 11, 11, 11, 47, 16, 16, 16, 16, 16, 11, 48, 11, 47, + 11, 11, 47, 47, 44, 11, 11, 11, 47, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, + 16, 16, 16, 44, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, + 11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, + 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, + 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, + 16, 33, 16, 16, 16, 32, 44, 7, 43, 43, 43, 76, 67, 50, 43, 43, 43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67, 67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43, 16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110, @@ -3241,22 +3281,23 @@ _hb_ucd_u8[14752] = 43, 43, 43, 74, 40, 40, 40, 44, 7, 7, 7, 7, 7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43, - 36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27, - 16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27, - 188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163, - 27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36, - 62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44, - 44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62, - 62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61, - 36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36, - 8, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44, - 55, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, 27, 27, 91, 67, - 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, - 67, 92, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 92, 44, 44, 44, - 67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41, - 67, 67, 67, 67, 44, 44, 67, 67, 67, 67, 67, 92, 44, 55, 67, 67, - 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 55, - 67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 67, 67, 67, 67, 67, 67, + 188, 7, 7, 7, 7,189, 44, 93, 36, 36, 36, 61, 36, 36, 62, 61, + 36, 36, 61,179, 27, 27, 27, 27, 16, 16, 43, 43, 43, 74, 44, 44, + 27, 27, 27, 27, 27, 27,163, 27,190, 27,100, 44, 44, 44, 44, 44, + 27, 27, 27, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, 44, + 36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36, + 36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36, + 62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36, + 36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36, + 62, 36, 62, 36, 36, 62, 36, 36, 8, 44, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, + 27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44, + 44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67, + 67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 92, 44, 44, 44, 67, + 67, 67, 67, 67, 67, 67, 92, 55, 67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,171,171,171,171,171,171,171, 44, 171,171,171,171,171,171,171, 0, 0, 0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9, @@ -3282,482 +3323,677 @@ _hb_ucd_u8[14752] = 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3, 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25, 2, 25, 24, 2, 15, 12, 15, 14, 2, 21, 14, 7, 15, 12, 17, 21, 1, 26, 10, 10, 1, - 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, - 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0, + 7, 13, 13, 2, 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 10, 11, 12, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 19, 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, 17, 18, 19, 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, 0, 0, 0, 20, - 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20, 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 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, 35, 0, 36, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 36, 0, 37, 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, - 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, - 0, 0, 40, 41, 42, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 5, - 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, 16, 18, - 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, 0, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, - 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, - 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, 0, 0, - 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, 62, 63, - 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, 0, 0, - 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, - 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0, - 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 75, 76, 0, 77, 78, 0, - 0, 79, 80, 0, 81, 62, 0, 82, 83, 0, 0, 84, 85, 86, 0, 0, - 0, 87, 0, 88, 0, 0, 51, 89, 51, 0, 90, 0, 91, 0, 0, 0, - 80, 0, 0, 0, 92, 93, 0, 94, 95, 96, 97, 0, 0, 0, 0, 0, - 51, 0, 0, 0, 0, 98, 99, 0, 0, 0, 0, 0, 0,100, 0, 0, - 0, 0, 0,101,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,103, - 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,106, 0, - 0,107, 0, 0, 0, 0, 0, 0,108, 0,109, 0,102, 0, 0, 0, - 0, 0,110,111, 0, 0, 0, 0, 0, 0, 0,112, 0, 0, 0, 0, - 0, 0, 0,113, 0,114, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, - 5, 6, 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, - 0, 13, 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, - 21, 0, 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, - 0, 27, 0, 0, 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, - 33, 0, 0, 35, 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, - 38, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, - 42, 0, 0, 0, 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, - 47, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, - 0, 51, 0, 52, 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, - 0, 56, 0, 0, 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, - 0, 0, 0, 61, 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, - 0, 0, 0, 67, 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, - 0, 0, 77, 78, 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, - 0, 81, 0, 0, 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, - 84, 0, 85, 0, 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, - 0, 0, 0, 88, 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, - 0, 0, 33, 0, 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, - 0, 0, 93, 0, 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, - 0, 0, 98, 0, 0, 0, 99, 0, 0, 0, 0,100,101, 93, 0, 0, - 102, 0, 0, 0, 84, 0, 0,103, 0, 0, 0,104,105, 0, 0,106, - 107, 0, 0, 0, 0, 0, 0,108, 0, 0,109, 0, 0, 0, 0,110, - 33, 0,111,112,113, 35, 0, 0,114, 0, 0, 0,115, 0, 0, 0, - 0, 0, 0,116, 0, 0,117, 0, 0, 0, 0,118, 88, 0, 0, 0, - 0, 0, 57, 0, 0, 0, 0, 52,119, 0, 0, 0, 0,120, 0, 0, - 121, 0, 0, 0, 0,119, 0, 0,122, 0, 0, 0, 0, 0, 0,123, - 0, 0, 0,124, 0, 0, 0,125, 0,126, 0, 0, 0, 0,127,128, - 129, 0,130, 0,131, 0, 0, 0,132,133,134, 0, 77, 0, 0, 0, - 0, 0, 35, 0, 0, 0,135, 0, 0, 0,136, 0, 0,137, 0, 0, - 138, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, - 5, 6, 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, - 18, 1, 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, - 25, 26, 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, - 34, 35, 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, - 42, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, - 21, 0, 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, - 0, 0, 52, 1, 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, - 54, 21, 35, 1, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, - 0, 0, 0, 59, 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, - 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, - 0, 0, 68, 0, 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, - 0, 77, 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, - 0, 80, 0, 0, 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, - 0, 0, 83, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, - 1, 52, 15, 86, 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, - 1, 0, 0, 0, 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, - 0, 78, 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, - 21, 1, 21, 92, 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, - 81, 99,100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, - 0, 0, 0, 61, 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50, - 0, 0, 0, 38, 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68, - 61, 0, 0, 0, 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, - 0, 0, 0,107, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, - 0, 0, 0,108, 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 40, + 0, 0, 0, 0, 0, 0, 41, 42, 43, 0, 44, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, + 0, 0, 4, 5, 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, + 16, 17, 16, 18, 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, + 21, 19, 0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 34, 0, 0, 35, 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, + 0, 0, 0, 0, 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, + 0, 0, 0, 0, 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, + 60, 61, 62, 63, 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, + 67, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 69, 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, + 0, 0, 0, 0, 0, 0, 0, 0, 74, 75, 0, 0, 0, 0, 76, 77, + 0, 78, 79, 0, 0, 80, 81, 0, 82, 62, 0, 83, 84, 0, 0, 85, + 86, 87, 0, 88, 0, 89, 0, 90, 0, 0, 51, 91, 51, 0, 92, 0, + 93, 0, 0, 0, 81, 0, 0, 0, 94, 95, 0, 96, 97, 98, 99, 0, + 0, 0, 0, 0, 51, 0, 0, 0, 0,100,101, 0, 0, 0, 0, 0, + 0,102, 0, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 0, 0,104, + 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,106, 0, 0,107, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,108,109, 0, 0,110, 0, 0, + 0, 0, 0, 0,111, 0,112, 0,105, 0, 0, 0, 0, 0,113,114, + 0, 0, 0, 0, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0,117, + 0,118, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, + 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, + 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, 0, 0, + 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, 0, 27, 0, 0, + 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, 33, 0, 0, 35, + 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, + 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, + 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, 47, 0, 0, 0, + 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, 0, 51, 0, 52, + 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, 0, 56, 0, 0, + 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, 0, 0, 0, 61, + 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, 0, 0, 0, 67, + 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, 0, 0, 77, 78, + 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, 0, 81, 0, 0, + 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, 84, 0, 85, 0, + 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, 0, 0, 0, 88, + 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, 0, 0, 33, 0, + 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, 0, 0, 93, 0, + 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, 0, 0, 98, 0, + 0, 0, 99, 0, 0, 0,100, 0, 0, 0, 0,101,102, 93, 0, 0, + 103, 0, 0, 0, 84, 0, 0,104, 0, 0, 0,105,106, 0, 0,107, + 108, 0, 0, 0, 0, 0, 0,109, 0, 0,110, 0, 0, 0, 0,111, + 33, 0,112,113,114, 57, 0, 0,115, 35, 0, 0,116, 0, 0, 0, + 117, 0, 0, 0, 0, 0, 0,118, 0, 0,119, 0, 0, 0, 0,120, + 88, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 52,121, 0, 0, 0, + 0,122, 0, 0,123, 0, 0, 0, 0,121, 0, 0,124, 0, 0, 0, + 0, 0, 79, 0, 0, 0, 0,125, 0, 0, 0,126, 0, 0, 0,127, + 0,128, 0, 0, 0, 0,129,130,131, 0,132, 0,133, 0, 0, 0, + 134,135,136, 0, 77, 0, 0, 0, 0, 0, 35, 0, 0, 0,137, 0, + 0, 0,138, 0, 0, 0,139, 0, 0,140, 0, 0,141, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, + 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, + 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, + 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, + 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, 42, 0, 0, 0, + 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, 21, 0, 0, 47, + 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, 0, 19, 52, 1, + 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, + 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 59, + 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, 64, 0, + 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, + 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, 0, 77, 0, 0, + 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, 0, 80, 0, 0, + 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, + 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, 1, 52, 15, 86, + 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, 1, 0, 0, 0, + 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, 0, 78, 0, 0, + 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, 21, 1, 21, 92, + 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, 81, 99,100, 4, + 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 61, + 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50, 0, 0, 0, 38, + 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68, 61, 0, 0, 0, + 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, 0, 0, 0,107, + 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, + 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0, 0, 0, 49, 50, 0, 0, 19, 58, 0, 0, 0, 51, 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61, 0, 0,113, 0, 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0, 78, 55, - 0, 38, 1, 58, 1, 58, 0, 0, 63, 89, 0, 0,115, 0, 0, 0, - 55, 0, 0, 0, 0,115, 0, 0, 0, 0, 61, 0, 0, 0, 0, 79, - 0, 61, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 79, 0, 0, 0, - 8, 91, 0, 0, 1, 87, 0, 0,116, 0, 0, 0, 0, 0, 0,117, - 0,118,119,120,121, 0,104, 4,122, 49, 23, 0, 0, 0, 38, 50, - 38, 58, 0, 0, 1, 87, 1, 1, 1, 1, 39, 1, 48,105, 87, 0, - 0, 0, 0, 1, 0, 0, 0,123, 4,122, 0, 0, 0, 1,124, 0, - 0, 0, 0, 0,230,230,230,230,230,232,220,220,220,220,232,216, - 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220, - 1, 1, 1, 1, 1,220,220,220,220,230,230,230,230,240,230,220, - 220,220,230,230,230,220,220, 0,230,230,230,220,220,220,220,230, - 232,220,220,230,233,234,234,233,234,234,233,230, 0, 0, 0,230, - 0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220, - 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, - 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, - 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230, - 220,230,230,220, 35, 0, 0, 0, 0, 0,230,230,230, 0, 0,230, - 230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0,230,220,230,230, - 220,220,230,220,220,230,220,230,220,230,230, 0, 0,220, 0, 0, - 230,230, 0,230, 0,230,230,230,230,230, 0, 0, 0,220,220,220, - 230,220,220,220,230,230, 0,220, 27, 28, 29,230, 7, 0, 0, 0, - 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0,230, 0, - 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 9, 0, - 103,103, 9, 0,107,107,107,107,118,118, 9, 0,122,122,122,122, - 220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0, 0,129,130, 0, - 132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0,130, 0,230,230, - 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7, 0, 9, 9, 0, - 9, 9, 0, 0, 0,230, 0, 0, 0,228, 0, 0, 0,222,230,220, - 220, 0, 0, 0,230, 0, 0,220,230,220, 0,220,230,230,230, 0, - 0, 0, 9, 9, 0, 0, 7, 0,230, 0, 1, 1, 1, 0, 0, 0, - 230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230, - 233,220,230,220,230,230, 1, 1, 1, 1, 1,230, 0, 1, 1,230, - 220,230, 1, 1, 0, 0,218,228,232,222,224,224, 0, 8, 8, 0, - 0, 0, 0,220,230, 0,230,230,220, 0, 0,230, 0, 0, 26, 0, - 0,220, 0,230,230, 1,220, 0, 0,230,220, 0, 0, 0,220,220, - 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, - 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, 0, 0, - 0,226,216,216,216,216,216, 0,220,220,220, 0,232,232,220,230, - 230,230, 7, 0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145, - 26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 38, 1, 58, 1, 58, 0, 0, 0, 0, 0, 88, 63, 89, 0, 0, + 115, 0, 0, 0, 55, 0, 0, 0, 0,115, 0, 0, 0, 0, 61, 0, + 0, 0, 0, 79, 0, 61, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, + 79, 0, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0,116, 0, 0, 0, + 0, 0, 0,117, 0,118,119,120,121, 0,104, 4,122, 49, 23, 0, + 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1, 1, 1, 39, 1, + 48,105, 87, 0, 0, 0, 0, 1, 0, 0, 0,123, 0, 0, 0,112, + 4,122, 0, 0, 0, 1,124, 0, 0, 0, 0, 0,230,230,230,230, + 230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220, + 220,220,220,202,202,220,220,220, 1, 1, 1, 1, 1,220,220,220, + 220,230,230,230,230,240,230,220,220,220,230,230,230,220,220, 0, + 230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233, + 234,234,233,230, 0, 0, 0,230, 0,220,230,230,230,230,220,230, + 230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0, + 230,220, 0, 18, 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31, + 32, 33, 34,230,230,220,220,230,220,230,230,220, 35, 0, 0, 0, + 0, 0,230,230,230, 0, 0,230,230, 0,220,230,230,220, 0, 0, + 0, 36, 0, 0,230,220,230,230,220,220,230,220,220,230,220,230, + 220,230,230, 0, 0,220, 0, 0,230,230, 0,230, 0,230,230,230, + 230,230, 0, 0, 0,220,220,220,230,220,220,220,230,230, 0,220, + 27, 28, 29,230, 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230, + 230, 0, 0, 0, 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, + 9, 0, 0, 0, 0, 0, 9, 0,103,103, 9, 0,107,107,107,107, + 118,118, 9, 0,122,122,122,122,220,220, 0, 0, 0,220, 0,220, + 0,216, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130, + 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, + 0, 0, 0, 7, 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0, + 0,228, 0, 0, 0,222,230,220,220, 0, 0, 0,230, 0, 0,220, + 230,220, 0,220,230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0, + 230, 0, 1, 1, 1, 0, 0, 0,230,234,214,220,202,230,230,230, + 230,230,232,228,228,220,218,230,233,220,230,220,230,230, 1, 1, + 1, 1, 1,230, 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228, + 232,222,224,224, 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230, + 220, 0, 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, + 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, + 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, + 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0, + 220,220,220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 33, + 17, 49, 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17,177, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 5, 3, - 3, 3, 3, 3, 6, 7, 8, 3, 3, 3, 3, 3, 9, 10, 11, 12, - 13, 3, 3, 3, 3, 3, 3, 3, 3, 14, 3, 15, 3, 3, 3, 3, - 3, 3, 16, 17, 18, 19, 20, 21, 3, 3, 3, 22, 23, 24, 3, 3, - 3, 3, 3, 3, 25, 3, 3, 3, 3, 3, 3, 3, 3, 26, 3, 3, - 27, 28, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, - 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, - 0, 0, 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, - 13, 0, 0, 14, 15, 16, 6, 0, 17, 18, 19, 19, 19, 20, 21, 22, - 23, 24, 19, 25, 0, 26, 27, 19, 19, 28, 29, 30, 0, 31, 0, 0, - 0, 8, 0, 0, 0, 0, 0, 0, 0, 19, 28, 0, 32, 33, 9, 34, - 35, 19, 0, 0, 36, 37, 38, 39, 40, 19, 0, 41, 42, 43, 44, 31, - 0, 1, 45, 42, 0, 0, 0, 0, 0, 32, 14, 14, 0, 0, 0, 0, - 14, 0, 0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51, - 52, 53, 43, 21, 0, 0, 0, 0, 0, 0, 0, 54, 6, 55, 0, 14, - 19, 1, 0, 0, 0, 0, 56, 57, 0, 0, 0, 0, 0, 19, 58, 31, - 0, 0, 0, 0, 0, 0, 0, 59, 14, 0, 0, 0, 0, 1, 0, 2, - 0, 0, 0, 3, 0, 0, 0, 60, 61, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 2, 3, 0, 4, 5, 0, 0, 6, 0, 0, - 0, 7, 0, 0, 0, 1, 1, 0, 0, 8, 9, 0, 8, 9, 0, 0, - 0, 0, 8, 9, 10, 11, 12, 0, 0, 0, 13, 0, 0, 0, 0, 14, - 15, 16, 17, 0, 0, 0, 1, 0, 0, 18, 19, 0, 0, 0, 20, 0, - 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 8, - 21, 9, 0, 0, 22, 0, 0, 0, 0, 1, 0, 23, 24, 25, 0, 0, - 26, 0, 0, 0, 8, 21, 27, 0, 1, 0, 0, 1, 1, 1, 1, 0, - 1, 28, 29, 30, 0, 31, 32, 20, 1, 1, 0, 0, 0, 8, 21, 9, - 1, 4, 5, 0, 0, 0, 33, 9, 0, 1, 1, 1, 0, 8, 21, 21, - 21, 21, 34, 1, 35, 21, 21, 21, 9, 36, 0, 0, 37, 38, 1, 0, - 39, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 8, 21, 9, 1, 0, - 0, 0, 40, 0, 8, 21, 21, 21, 21, 21, 21, 21, 21, 9, 0, 1, - 1, 1, 1, 8, 21, 21, 21, 9, 0, 0, 0, 41, 0, 42, 43, 0, - 0, 0, 1, 44, 0, 0, 0, 45, 8, 9, 1, 0, 0, 0, 8, 21, - 21, 21, 9, 0, 1, 0, 1, 1, 8, 21, 21, 9, 0, 4, 5, 8, - 9, 1, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 12, 13, - 13, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 13, 22, 13, 13, 13, - 13, 23, 24, 24, 25, 26, 13, 13, 13, 27, 28, 29, 13, 30, 31, 32, - 33, 34, 35, 36, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, - 7, 41, 13, 42, 7, 7, 43, 7, 44, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 45, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37, - 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 2, 2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59, - 59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 79, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, - 82, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, 97, 98, 99,100,101,101, - 102,103,104,105,106,107,108,109,110,111, 96,112,113,114,115,116, - 117,118,119,119,120,121,122,123,124,125,126,127,128,129,130,131, - 132, 96,133,134,135,136,137,138,139,140,141,142,143, 96,144,145, - 96,146,147,148,149, 96,150,151,152,153,154,155,156, 96,157,158, - 159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164, - 167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171, - 171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96, - 96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182, - 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, - 182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185, - 186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204, - 205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96, - 96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215, - 96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221, - 222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59, - 59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96, - 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70,238, 70,239, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 70, 70, - 70, 70,242, 96, 96, 96, 70, 70, 70, 70,243, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,244, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,245, 96, 96, - 96, 96, 96, 96, 96, 96,246, 96,247,248, 0, 1, 2, 2, 0, 1, - 2, 2, 2, 3, 4, 5, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0, 0, 0, - 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2, - 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9, - 9, 2, 9, 2, 9, 9, 9, 9, 2, 9, 9, 9, 55, 55, 55, 55, - 55, 55, 6, 6, 6, 6, 6, 1, 1, 6, 2, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 2, 2, 2, 2, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0, - 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, - 3, 3, 1, 3, 3, 3, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37, - 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 2, 2, 64, 64, - 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, - 2, 2, 90, 90, 90, 2, 95, 95, 95, 95, 2, 2, 95, 2, 3, 3, - 3, 2, 3, 3, 2, 2, 3, 3, 0, 3, 7, 7, 7, 7, 7, 1, - 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 2, 5, - 5, 5, 5, 2, 2, 5, 5, 2, 5, 5, 5, 2, 5, 2, 2, 2, - 5, 5, 5, 5, 2, 2, 5, 5, 5, 2, 2, 2, 2, 5, 5, 5, - 2, 5, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, - 2, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11, - 2, 2, 2, 11, 2, 2, 11, 2, 11, 2, 2, 2, 11, 11, 2, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, - 2, 2, 10, 2, 2, 2, 2, 2, 10, 10, 2, 21, 21, 21, 21, 21, - 21, 21, 21, 2, 2, 21, 21, 2, 21, 21, 21, 21, 2, 2, 21, 21, - 2, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22, - 22, 2, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, - 2, 22, 22, 2, 2, 2, 22, 22, 22, 22, 23, 23, 23, 23, 23, 2, - 23, 23, 23, 23, 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23, - 2, 2, 2, 2, 23, 23, 2, 2, 2, 23, 16, 16, 16, 16, 16, 2, - 16, 16, 2, 16, 16, 16, 16, 16, 2, 2, 2, 16, 16, 2, 2, 2, - 16, 16, 20, 20, 20, 20, 20, 2, 20, 20, 2, 2, 20, 20, 2, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, - 2, 36, 2, 36, 2, 2, 2, 2, 36, 2, 2, 2, 2, 36, 36, 2, - 36, 2, 36, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 2, 2, 2, 2, 0, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18, - 18, 2, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18, 2, 2, 18, 2, - 18, 2, 25, 25, 25, 25, 2, 25, 25, 25, 25, 2, 2, 2, 25, 2, - 25, 25, 25, 0, 0, 0, 0, 25, 25, 2, 33, 33, 33, 33, 8, 8, - 8, 8, 8, 8, 2, 8, 2, 8, 2, 2, 8, 8, 8, 0, 12, 12, - 12, 12, 30, 30, 30, 30, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, - 30, 2, 2, 30, 30, 30, 30, 2, 2, 2, 29, 29, 29, 29, 29, 29, - 2, 2, 28, 28, 28, 28, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35, - 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2, 2, 2, 45, 45, - 45, 45, 45, 45, 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 0, - 0, 2, 43, 43, 43, 43, 46, 46, 46, 46, 46, 2, 46, 46, 31, 31, - 31, 31, 31, 31, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, - 32, 32, 32, 32, 2, 2, 32, 2, 2, 2, 32, 32, 32, 2, 28, 28, - 2, 2, 48, 48, 48, 48, 48, 48, 48, 2, 48, 2, 2, 2, 52, 52, - 52, 52, 52, 52, 2, 2, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, - 2, 2, 58, 58, 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 2, 2, - 54, 54, 91, 91, 91, 91, 91, 91, 91, 2, 91, 2, 2, 91, 91, 91, - 2, 2, 1, 1, 1, 2, 62, 62, 62, 62, 62, 2, 2, 2, 62, 62, - 62, 2, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 2, 2, - 2, 70, 70, 70, 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 6, 2, - 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1, 1, 0, 1, 0, - 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 2, 19, 19, - 9, 9, 9, 9, 9, 6, 19, 9, 9, 9, 9, 9, 19, 19, 9, 9, - 9, 19, 6, 19, 19, 19, 19, 19, 19, 9, 9, 9, 2, 2, 2, 9, - 2, 9, 2, 9, 9, 9, 1, 1, 0, 0, 0, 2, 0, 0, 0, 19, - 2, 2, 0, 0, 0, 19, 0, 0, 0, 2, 19, 2, 2, 2, 0, 2, - 2, 2, 1, 2, 2, 2, 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, - 27, 27, 2, 2, 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 2, 55, - 55, 55, 61, 61, 61, 61, 2, 2, 2, 61, 61, 2, 2, 2, 0, 0, - 2, 2, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 2, 2, 0, 13, - 0, 13, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 2, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1, 1, 0, 0, 15, - 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 2, 26, - 26, 26, 26, 26, 26, 26, 2, 12, 12, 12, 12, 12, 12, 2, 12, 12, - 12, 0, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39, 39, 2, 86, 86, - 86, 86, 77, 77, 77, 77, 79, 79, 79, 79, 19, 19, 19, 2, 19, 19, - 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 19, 19, 60, 60, - 60, 60, 60, 2, 2, 2, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, - 2, 2, 2, 2, 75, 75, 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, - 74, 74, 2, 2, 2, 74, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, - 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33, 33, 2, 68, 68, - 68, 68, 68, 68, 68, 2, 68, 68, 2, 2, 92, 92, 92, 92, 92, 92, - 92, 2, 2, 2, 2, 92, 87, 87, 87, 87, 87, 87, 87, 2, 19, 9, - 19, 19, 19, 19, 0, 0, 87, 87, 2, 2, 2, 2, 2, 12, 2, 2, - 2, 4, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 2, 2, - 2, 3, 3, 3, 0, 0, 2, 2, 3, 3, 1, 1, 6, 6, 3, 2, - 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, 0, 0, 17, 17, 17, 17, - 0, 0, 2, 2, 12, 12, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, - 49, 2, 49, 49, 2, 49, 49, 49, 2, 2, 9, 2, 2, 2, 0, 1, - 2, 2, 71, 71, 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 2, - 2, 2, 42, 42, 42, 42, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, - 41, 2,118,118,118,118,118,118,118, 2, 53, 53, 53, 53, 53, 53, - 2, 53, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40, 40, 40, 51, 51, - 51, 51, 50, 50, 50, 50, 50, 50, 2, 2,135,135,135,135,106,106, - 106,106,104,104,104,104, 2, 2, 2,104,161,161,161,161,161,161, - 161, 2,161,161, 2,161,161, 2, 2, 2,110,110,110,110,110,110, - 110, 2,110,110, 2, 2, 19, 2, 19, 19, 47, 47, 47, 47, 47, 47, - 2, 2, 47, 2, 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, - 2, 47, 81, 81, 81, 81, 81, 81, 2, 81,120,120,120,120,116,116, - 116,116,116,116,116, 2, 2, 2, 2,116,128,128,128,128,128,128, - 128, 2,128,128, 2, 2, 2, 2, 2,128, 66, 66, 66, 66, 2, 2, - 2, 66, 72, 72, 72, 72, 72, 72, 2, 2, 2, 2, 2, 72, 98, 98, - 98, 98, 97, 97, 97, 97, 2, 2, 97, 97, 57, 57, 57, 57, 2, 57, - 57, 2, 2, 57, 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, - 2, 57, 57, 2, 2, 2, 88, 88, 88, 88,117,117,117,117,112,112, - 112,112,112,112,112, 2, 2, 2, 2,112, 78, 78, 78, 78, 78, 78, - 2, 2, 2, 78, 78, 78, 83, 83, 83, 83, 83, 83, 2, 2, 82, 82, - 82, 82, 82, 82, 82, 2,122,122,122,122,122,122, 2, 2, 2,122, - 122,122,122, 2, 2, 2, 89, 89, 89, 89, 89, 2, 2, 2,130,130, - 130,130,130,130,130, 2, 2, 2,130,130,144,144,144,144,144,144, - 2, 2,156,156,156,156,156,156, 2,156,156,156, 2, 2, 2, 3, - 3, 3,147,147,147,147,148,148,148,148,148,148, 2, 2,158,158, - 158,158,158,158, 2, 2,153,153,153,153,149,149,149,149,149,149, - 149, 2, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 2, 2, - 2, 94, 85, 85, 85, 85, 85, 85, 85, 2, 2, 85, 2, 2,101,101, - 101,101,101, 2, 2, 2,101,101, 2, 2, 96, 96, 96, 96, 96, 2, - 96, 96,111,111,111,111,111,111,111, 2,100,100,100,100,108,108, - 108,108,108,108, 2,108,108,108, 2, 2,129,129,129,129,129,129, - 129, 2,129, 2,129,129,129,129, 2,129,129,129, 2, 2,109,109, - 109,109,109,109,109, 2,109,109, 2, 2,107,107,107,107, 2,107, - 107,107,107, 2, 2,107,107, 2,107,107,107,107, 2, 1,107,107, - 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2,107,107,137,137, - 137,137, 2,137,137,137,137,137, 2, 2,124,124,124,124,124,124, - 2, 2,123,123,123,123,123,123, 2, 2,114,114,114,114,114, 2, - 2, 2,114,114, 2, 2,102,102,102,102,102,102, 2, 2,126,126, - 126,126,126,126,126, 2, 2,126,126,126,142,142,142,142,125,125, - 125,125,125,125,125, 2, 2, 2, 2,125,154,154,154,154,154,154, - 154, 2, 2,154, 2, 2, 2,154,154, 2,154,154, 2,154,154, 2, - 2,154,154,154, 2, 2,150,150,150,150, 2, 2,150,150,150, 2, - 2, 2,141,141,141,141,140,140,140,140,140,140,140, 2,121,121, - 121,121,121, 2, 2, 2, 7, 7, 2, 2,133,133,133,133,133, 2, - 133,133,133,133,133, 2,133,133, 2, 2,133, 2, 2, 2,134,134, - 134,134, 2, 2,134,134, 2,134,134,134,134,134,134, 2,138,138, - 138,138,138,138,138, 2,138,138, 2,138, 2, 2,138, 2,138,138, - 2, 2,143,143,143,143,143,143, 2,143,143, 2,143,143,143,143, - 143, 2,143, 2, 2, 2,143,143, 2, 2,145,145,145,145,145, 2, - 2, 2,163,163,163,163,163, 2,163,163,163,163,163, 2, 2, 2, - 163,163,163,163, 2, 2, 86, 2, 2, 2, 63, 63, 63, 63, 63, 63, - 2, 2, 63, 63, 63, 2, 63, 2, 2, 2,157,157,157,157,157,157, - 157, 2, 80, 80, 80, 80, 80, 80, 2, 2,127,127,127,127,127,127, - 127, 2, 79, 2, 2, 2,115,115,115,115,115,115,115, 2,115,115, - 2, 2, 2, 2,115,115,159,159,159,159,159,159,159, 2,159,159, - 2, 2,103,103,103,103,103,103, 2, 2,119,119,119,119,119,119, - 2, 2,119,119, 2,119, 2,119,119,119,146,146,146,146,146,146, - 146, 2, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99,136,139, - 13, 13,155, 2, 2, 2,136,136,136,136,155,155,155,155,155,155, - 2, 2,136, 2, 2, 2, 2, 17, 17, 17, 2, 17, 17, 2, 17, 15, - 15, 15, 17, 17, 17, 2, 2, 2, 15, 2, 2, 17, 2, 2,139,139, - 139,139,105,105,105,105,105,105,105, 2,105, 2, 2, 2,105,105, - 2, 2, 1, 1, 2, 2, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, - 1, 1, 2, 2, 0, 2, 2, 0, 0, 2, 0, 2, 0, 2,131,131, - 131,131, 2, 2, 2,131, 2,131,131,131, 56, 56, 56, 2, 56, 2, - 2, 56, 56, 56, 2, 56, 56, 2, 56, 56, 6, 6, 2, 2, 2, 2, - 2, 6,151,151,151,151,151, 2, 2, 2,151,151, 2, 2, 2, 2, - 151,151,160,160,160,160,160,160,160, 2,152,152,152,152,152,152, - 2, 2, 2, 2, 2,152,164,164,164,164,164,164, 2, 2, 2, 30, - 30, 2,113,113,113,113,113, 2, 2,113,113,113,113, 2,132,132, - 132,132,132,132, 2, 2, 2, 2,132,132, 2, 3, 3, 2, 3, 2, - 2, 3, 2, 3, 2, 3, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, - 2, 3, 15, 0, 0, 2, 13, 2, 2, 2, 13, 13, 13, 2, 2, 0, - 2, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, - 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,177, 0, 1, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 6, 7, 8, 3, + 3, 3, 3, 3, 9, 10, 11, 12, 13, 3, 3, 3, 3, 3, 3, 3, + 3, 14, 3, 15, 3, 3, 3, 3, 3, 3, 16, 17, 18, 19, 20, 21, + 3, 3, 3, 22, 23, 24, 3, 3, 3, 3, 3, 3, 25, 3, 3, 3, + 3, 3, 3, 3, 3, 26, 3, 3, 27, 28, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 10, 11, 12, 13, 0, 0, 14, 15, 16, 6, 0, + 17, 18, 19, 19, 19, 20, 21, 22, 23, 24, 19, 25, 0, 26, 27, 19, + 19, 28, 29, 30, 0, 31, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 19, 28, 0, 32, 33, 9, 34, 35, 19, 0, 0, 36, 37, 38, 39, + 40, 19, 0, 41, 42, 43, 44, 31, 0, 1, 45, 42, 0, 0, 0, 0, + 0, 32, 14, 14, 0, 0, 0, 0, 14, 0, 0, 46, 47, 47, 47, 47, + 48, 49, 47, 47, 47, 47, 50, 51, 52, 53, 43, 21, 0, 0, 0, 0, + 0, 0, 0, 54, 6, 55, 0, 14, 19, 1, 0, 0, 0, 0, 56, 57, + 0, 0, 0, 0, 0, 19, 58, 31, 0, 0, 0, 0, 0, 0, 0, 59, + 14, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 60, + 61, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, + 0, 4, 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0, + 0, 8, 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, + 0, 0, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0, + 0, 18, 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0, + 0, 1, 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0, + 1, 0, 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20, + 1, 1, 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9, + 0, 1, 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21, + 9, 36, 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21, + 21, 21, 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9, + 0, 0, 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45, + 8, 9, 1, 0, 0, 0, 8, 21, 21, 21, 9, 0, 1, 0, 1, 1, + 8, 21, 21, 9, 0, 4, 5, 8, 9, 1, 0, 0, 0, 1, 2, 3, + 4, 5, 5, 5, 5, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 9, 16, 17, 18, 9, 19, 20, 21, 22, 23, 24, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 25, 26, 27, 5, 28, 29, 5, 30, 31, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 0, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 1, 29, 30, 31, + 32, 32, 33, 32, 32, 32, 34, 32, 32, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 46, 46, + 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 44, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 95, + 95, 96, 97, 98, 56, 56, 56, 56, 56, 56, 56, 56, 56, 99,100,100, + 100,100,101,100,100,100,100,100,100,100,100,100,100,100,100,100, + 100,102,103,103,104, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,105, + 56, 56, 56, 56, 56, 56,106,106,107,108, 56,109,110,111,112,112, + 112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, + 112,112,112,112,112,113,112,112,112,114,115,116, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,117,118,119, + 120, 56, 56, 56, 56, 56, 56, 56, 56, 56,121, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,122, 32,123,124,125,126, + 127,128,129,130,131,132,133,133,134, 56, 56, 56, 56,135,136,137, + 138, 56,139,140, 56,141,142,143, 56, 56,144,145,146, 56,147,148, + 149, 32, 32, 32,150,151,152, 32,153,154, 56, 56, 56, 56, 44, 44, + 44, 44, 44, 44,155, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44,156,157, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,158, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44,159, 44, 44,160, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 44, 44,161, 56, 56, 56, 56, 56, 44, 44, + 44,162, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44,163, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,164,165, + 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, + 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, + 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2, + 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 2, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 2, 4, 4, 4, 2, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, + 2, 2, 2, 2, 2, 2, 14, 14, 14, 2, 2, 2, 2, 14, 14, 14, + 14, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 3, + 3, 3, 3, 3, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, + 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 2, 2, 95, 2, 37, 37, 37, 2, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, + 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, + 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 5, 5, + 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, + 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, + 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, + 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2, + 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5, + 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 11, + 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, + 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, + 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11, + 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11, + 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2, + 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 10, + 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, + 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, + 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10, + 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2, + 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, + 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21, + 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, + 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, + 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21, + 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2, + 2, 2, 2, 21, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21, + 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22, + 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22, + 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 2, + 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, + 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, + 2, 2, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2, + 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 23, 23, + 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, + 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2, + 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 2, 16, + 16, 16, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 2, 2, + 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 2, 36, + 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, + 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, 2, + 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, + 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18, + 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18, + 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 2, 18, 18, 2, 2, 18, 18, 18, 18, 25, 25, + 25, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 2, 2, 2, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, + 25, 25, 25, 0, 0, 0, 0, 25, 25, 2, 2, 2, 2, 2, 33, 33, + 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 2, 8, 2, 2, 2, 2, 2, 8, 2, 2, 8, 8, + 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, + 30, 30, 30, 30, 30, 2, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, + 30, 30, 30, 2, 2, 2, 30, 30, 2, 2, 2, 2, 2, 2, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, + 28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 0, 0, 0, 35, 35, 35, 2, 2, 2, 2, 2, 2, 2, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 0, 0, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 2, 2, 31, 31, + 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 2, 2, 2, 2, 32, 2, + 2, 2, 2, 2, 2, 2, 32, 32, 32, 2, 2, 2, 2, 2, 28, 28, + 28, 28, 28, 28, 2, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, 2, 2, 2, 2, 48, 2, + 2, 2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 2, 2, 2, 2, 58, 58, + 2, 2, 2, 2, 2, 2, 58, 58, 58, 2, 2, 2, 58, 58, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 91, 91, + 91, 91, 91, 2, 2, 91, 91, 91, 2, 2, 2, 2, 2, 2, 91, 91, + 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 2, 62, 62, 76, 76, + 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70, + 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 6, 6, + 6, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, + 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, + 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, + 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 6, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, + 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9, + 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, + 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19, + 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, + 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, + 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 56, 56, + 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55, + 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2, + 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 13, 13, + 13, 13, 13, 13, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13, + 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1, + 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2, + 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, + 2, 2, 2, 2, 2, 0, 12, 12, 12, 12, 12, 12, 12, 0, 17, 17, + 17, 17, 17, 17, 17, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 86, 86, + 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, + 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 2, 2, 19, 19, 2, 19, 2, 19, 19, 19, 2, 2, + 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 2, 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, + 2, 2, 2, 2, 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 74, 12, 12, 12, 12, 12, 2, 2, 2, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 2, 0, 84, 84, + 2, 2, 2, 2, 84, 84, 33, 33, 33, 33, 33, 33, 33, 2, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 68, 68, + 68, 68, 68, 68, 2, 2, 68, 68, 2, 2, 68, 68, 68, 68, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 2, 2, 2, + 2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 2, 2, 30, 30, 30, 30, 30, 30, 2, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 19, 19, 19, 19, + 0, 0, 2, 2, 2, 2, 87, 87, 87, 87, 87, 87, 2, 2, 87, 87, + 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, + 2, 12, 12, 12, 12, 12, 13, 13, 2, 2, 2, 2, 2, 2, 19, 19, + 19, 19, 19, 19, 19, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14, + 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 3, 3, + 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, + 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 6, 6, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, + 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, + 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0, + 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2, + 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118, + 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40, + 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50, + 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135, + 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104, + 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161, + 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161, + 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,170,170, + 170,170,170,170,170,170,170,170,170,170, 2, 2, 2, 2,110,110, + 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110, + 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 47, 47, + 47, 47, 47, 47, 2, 2, 47, 2, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, 2, + 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 2, 81,120,120,120,120,120,120,120,120,116,116, + 116,116,116,116,116,116,116,116,116,116,116,116,116, 2, 2, 2, + 2, 2, 2, 2, 2,116,128,128,128,128,128,128,128,128,128,128, + 128, 2,128,128, 2, 2, 2, 2, 2,128,128,128,128,128, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 2, 2, 2, 66, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 2, 2, 2, 2, 2, 72, 98, 98, + 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 2, 2, + 2, 2, 97, 97, 97, 97, 2, 2, 97, 97, 97, 97, 97, 97, 57, 57, + 57, 57, 2, 57, 57, 2, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, + 57, 57, 2, 57, 57, 57, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, 2, 57, 57, + 57, 2, 2, 2, 2, 57, 57, 2, 2, 2, 2, 2, 2, 2, 88, 88, + 88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,112,112, + 112,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2, + 2,112,112,112,112,112, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 2, 2, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 2, 2, 2, 2, 2,122,122, + 122,122,122,122,122,122,122,122, 2, 2, 2, 2, 2, 2, 2,122, + 122,122,122, 2, 2, 2, 2,122,122,122,122,122,122,122, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 2, 2, 2, 2, 2, 2, 2,130,130, + 130,130,130,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, + 130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144, + 2, 2, 2, 2, 2, 2,165,165,165,165,165,165,165,165,165,165, + 165,165,165,165, 2, 2, 2,165,165,165,165,165,165,165, 2, 2, + 2, 2, 2, 2,165,165,156,156,156,156,156,156,156,156,156,156, + 2,156,156,156, 2, 2,156,156, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,147,147, + 147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148, + 2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158, + 2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153, + 153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149, + 149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2, + 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101, + 101,101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101, + 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 2, 96, 96,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111, 2,100,100,100,100,100,100,100,100, 2, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108, + 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108, + 2, 2, 2, 2, 2, 2,129,129,129,129,129,129,129, 2,129, 2, + 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129, 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109, + 109,109,109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109, + 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107, + 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107, + 107,107,107,107,107,107,107, 2,107,107,107,107,107,107,107, 2, + 107,107, 2,107,107,107,107,107, 2, 1,107,107,107,107,107, 2, + 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, + 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107, + 107,107,107, 2, 2, 2,171,171,171,171,171,171,171,171,171,171, + 2,171, 2, 2,171, 2,171,171,171,171,171,171, 2,171,171, 2, + 171, 2, 2,171, 2,171,171,171,171, 2,171,171,171,171,171, 2, + 2, 2, 2, 2, 2, 2, 2,171,171, 2, 2, 2, 2, 2,137,137, + 137,137,137,137,137,137,137,137,137,137, 2,137,137,137,137,137, + 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124, + 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123, + 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114, + 114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32, + 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102, + 2, 2, 2, 2, 2, 2, 33, 33, 33, 33, 2, 2, 2, 2,126,126, + 126,126,126,126,126,126,126,126,126, 2, 2,126,126,126,126,126, + 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2,142,142, + 142,142,142,142,142,142,142,142,142,142, 2, 2, 2, 2,125,125, + 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154, + 2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154, + 154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2, + 2,154,154,154,154,154,154,154, 2, 2, 2, 2, 2, 2,150,150, + 150,150,150,150,150,150, 2, 2,150,150,150,150,150,150,150,150, + 150,150,150, 2, 2, 2,141,141,141,141,141,141,141,141,140,140, + 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2,121,121, + 121,121,121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2, 7, 7, + 2, 2, 2, 2, 2, 2,169,169,169,169,169,169,169,169,169,169, + 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2, + 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133, + 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134, + 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138, + 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138, + 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138, + 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2, + 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2, + 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145, + 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2,163,163, + 163,163,163,163,163,163,163, 2,163,163,163,163,163,163,163,163, + 163, 2, 2, 2,163,163,163,163,163, 2, 2, 2, 2, 2, 86, 2, + 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63, + 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157, + 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 2, 80, 80, + 80, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127, + 127,127,127,127,127, 2,166,166,166,166,166,166,166,166,166,166, + 2, 2, 2, 2, 2, 2, 79, 2, 2, 2, 2, 2, 2, 2,115,115, + 115,115,115,115,115,115,115,115,115,115,115,115,115, 2,115,115, + 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159, + 159,159,159,159,159, 2,159,159, 2, 2, 2, 2, 2, 2,103,103, + 103,103,103,103,103,103,103,103,103,103,103,103, 2, 2,119,119, + 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,119,119, + 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119,167,167, + 167,167,167,167,167,167,167,167, 2, 2, 2, 2, 2, 2,146,146, + 146,146,146,146,146,146,146,146,146, 2, 2, 2, 2, 2, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 2, 2, + 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136, + 136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155, + 155,155,155,155, 2, 2, 2, 2, 2, 2, 2, 2, 2,155,136, 2, + 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17, + 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17, + 17, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, 2, 15, 15, + 15, 2, 2, 17, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139, + 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105, + 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105, + 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105, + 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2, + 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131, + 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131, + 131,131,131,131,131,131, 2, 2, 2, 2, 2, 19, 19, 19, 56, 56, + 56, 56, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, + 2, 56, 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2, 6, 6, + 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,151,151, + 151,151,151,151,151,151,151,151,151,151,151, 2, 2, 2,151,151, + 151,151,151,151, 2, 2,151,151, 2, 2, 2, 2,151,151,160,160, + 160,160,160,160,160,160,160,160,160,160,160,160,160, 2,152,152, + 152,152,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164, + 164,164,164,164,164,164,164,164, 2, 2, 2, 2, 2, 2,168,168, + 168,168,168,168,168,168,168,168,168, 2, 2, 2, 2,168, 30, 30, + 30, 30, 2, 30, 30, 2,113,113,113,113,113,113,113,113,113,113, + 113,113,113, 2, 2,113,113,113,113,113,113,113,113, 2,132,132, + 132,132,132,132,132,132,132,132,132,132, 2, 2, 2, 2,132,132, + 2, 2, 2, 2,132,132, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, + 3, 2, 3, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, + 3, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, + 3, 3, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 13, 2, + 2, 2, 2, 2, 2, 2, 13, 13, 13, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 9, 9, 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 16, 17, 9, 9, 9, 9, 18, 9, 9, 9, 9, 9, 19, 20, + 21, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 23, 9, 9, 9, 9, 9, 24, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, - 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, + 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, + 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 41, 42, 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, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, + 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, + 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, + 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, + 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, + 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, + 0, 0, 0, 0, 0, 0, 66, 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, 0, 0, 0, 0, 0, - 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, - 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, - 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, - 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, - 0, 0, 66, 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, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0, + 107, 0, 0, 0,108, 0,109, 0,110, 0,111,112,113, 0,114, 0, + 0, 0,115, 0, 0, 0,116, 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,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122,123,124, + 125,126, 0,127, 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,128,129,130,131,132,133,134,135,136,137,138,139, + 140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155, + 156,157, 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102, - 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0, - 108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, - 0, 0,116, 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,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126, 0,127, + 162, 0,163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,164,165, 0, + 0, 0, 0, 0, 0, 0,166, 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,167, 0, 0, 0,168,169, 0, 0, + 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,171, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151,152,153,154,155,156,157, 0, 0, - 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, - 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,173, 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,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,174, 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,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,175, 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,169,170, 0, 0, 0, 0,171,172, 0, 0, 0, - 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188, - 189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204, - 205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0,176,177, 0, 0, 0, 0,178, + 179, 0, 0, 0,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, }; static const uint16_t -_hb_ucd_u16[10060] = +_hb_ucd_u16[9668] = { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, @@ -3776,9 +4012,10 @@ _hb_ucd_u16[10060] = 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140, 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140, 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 168, 169, 48, 48, - 168, 48, 48, 170, 171, 172, 48, 48, 48, 171, 48, 48, 48, 173, 174, 175, - 48, 176, 9, 9, 9, 9, 9, 177, 178, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 168, 169, 48, 48, 168, 48, 48, 170, 171, 172, 48, 48, + 48, 171, 48, 48, 48, 173, 174, 175, 48, 176, 9, 9, 9, 9, 9, 177, + 178, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183, 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193, 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199, @@ -3791,28 +4028,34 @@ _hb_ucd_u16[10060] = 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278, - 279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282, - 209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271, - 271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209, - 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279, - 300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305, - 209, 306, 209, 209, 209, 209, 209, 209, 9, 9, 9, 11, 11, 11, 307, 308, - 13, 13, 13, 13, 13, 13, 309, 310, 11, 11, 311, 48, 48, 48, 312, 313, - 48, 314, 315, 315, 315, 315, 32, 32, 316, 317, 318, 319, 320, 321, 140, 140, - 209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 209, - 325, 326, 327, 328, 136, 48, 48, 48, 48, 329, 178, 48, 48, 48, 48, 330, - 331, 48, 48, 136, 48, 48, 48, 48, 200, 332, 48, 48, 209, 209, 333, 48, - 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209, - 48, 48, 48, 48, 209, 209, 209, 209, 48, 338, 48, 48, 48, 48, 48, 48, - 151, 209, 209, 209, 287, 48, 48, 229, 339, 48, 340, 140, 13, 13, 341, 342, - 13, 343, 48, 48, 48, 48, 344, 345, 31, 346, 347, 348, 13, 13, 13, 349, - 350, 351, 352, 353, 354, 355, 140, 356, 357, 48, 358, 359, 48, 48, 48, 360, - 361, 48, 48, 362, 363, 192, 32, 364, 64, 48, 365, 48, 366, 367, 48, 151, - 76, 48, 48, 368, 369, 370, 371, 372, 48, 48, 373, 374, 375, 376, 48, 377, - 48, 48, 48, 378, 379, 380, 381, 382, 383, 384, 315, 11, 11, 385, 386, 11, - 11, 11, 11, 11, 48, 48, 387, 192, 48, 48, 388, 48, 389, 48, 48, 206, - 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209, + 209, 209, 176, 140, 287, 140, 271, 271, 271, 288, 209, 209, 209, 209, 289, 271, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 290, 291, 209, 209, 292, + 209, 209, 209, 209, 209, 209, 293, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 294, 295, 271, 296, 209, 209, 297, 279, 298, 279, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 279, 279, 279, 279, 279, 279, 279, 279, 299, 300, 279, 279, 279, 301, 279, 302, + 209, 209, 209, 279, 303, 209, 209, 304, 209, 305, 209, 209, 209, 209, 209, 209, + 9, 9, 9, 11, 11, 11, 306, 307, 13, 13, 13, 13, 13, 13, 308, 309, + 11, 11, 310, 48, 48, 48, 311, 312, 48, 313, 314, 314, 314, 314, 32, 32, + 315, 316, 317, 318, 319, 320, 140, 140, 209, 321, 209, 209, 209, 209, 209, 322, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, 140, 209, + 324, 325, 326, 327, 136, 48, 48, 48, 48, 328, 178, 48, 48, 48, 48, 329, + 330, 48, 48, 136, 48, 48, 48, 48, 200, 331, 48, 48, 209, 209, 332, 48, + 209, 333, 334, 209, 335, 336, 209, 209, 334, 209, 209, 336, 209, 209, 209, 209, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 209, 209, 209, 209, + 48, 337, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 151, 209, 209, 209, 338, 48, 48, 229, + 339, 48, 340, 140, 13, 13, 341, 342, 13, 343, 48, 48, 48, 48, 344, 345, + 31, 346, 347, 348, 13, 13, 13, 349, 350, 351, 352, 353, 354, 355, 140, 356, + 357, 48, 358, 359, 48, 48, 48, 360, 361, 48, 48, 362, 363, 192, 32, 364, + 64, 48, 365, 48, 366, 367, 48, 151, 76, 48, 48, 368, 369, 370, 371, 372, + 48, 48, 373, 374, 375, 376, 48, 377, 48, 48, 48, 378, 379, 380, 381, 382, + 383, 384, 314, 11, 11, 385, 386, 11, 11, 11, 11, 11, 48, 48, 387, 192, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 388, 48, 389, 48, 48, 206, + 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140, 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48, 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403, @@ -3823,571 +4066,540 @@ _hb_ucd_u16[10060] = 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430, 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140, 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439, - 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140, - 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140, + 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 48, 48, 48, 388, + 48, 48, 48, 313, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140, 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453, 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271, 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467, 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140, 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474, - 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476, - 48, 48, 477, 478, 140, 140, 140, 479, 48, 464, 480, 48, 62, 481, 140, 48, - 482, 140, 140, 48, 483, 140, 48, 314, 484, 48, 48, 485, 486, 457, 487, 488, - 222, 48, 48, 489, 490, 48, 196, 192, 491, 48, 492, 493, 494, 48, 48, 495, - 222, 48, 48, 496, 497, 498, 499, 500, 48, 97, 501, 502, 503, 140, 140, 140, - 504, 505, 506, 48, 48, 507, 508, 192, 509, 83, 84, 510, 511, 512, 513, 514, - 48, 48, 48, 515, 516, 517, 478, 140, 48, 48, 48, 518, 519, 192, 140, 140, - 48, 48, 520, 521, 522, 523, 140, 140, 48, 48, 48, 524, 525, 192, 526, 140, - 48, 48, 527, 528, 192, 140, 140, 140, 48, 173, 529, 530, 314, 140, 140, 140, - 48, 48, 501, 531, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 532, - 533, 534, 48, 535, 536, 192, 140, 140, 140, 140, 537, 48, 48, 538, 539, 140, - 540, 48, 48, 541, 542, 543, 48, 48, 544, 545, 546, 48, 48, 48, 48, 196, - 547, 140, 140, 140, 140, 140, 140, 140, 84, 48, 520, 548, 549, 148, 175, 550, - 48, 551, 552, 553, 140, 140, 140, 140, 554, 48, 48, 555, 556, 192, 557, 48, - 558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 560, - 561, 115, 48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566, - 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568, - 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 569, - 48, 48, 48, 570, 571, 572, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140, - 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 573, - 48, 48, 48, 574, 575, 576, 577, 578, 48, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 9, 9, 11, 11, 271, 579, 140, 140, 140, 140, 140, 140, - 48, 48, 48, 48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586, - 48, 48, 48, 48, 48, 48, 48, 440, 48, 48, 48, 48, 48, 199, 140, 140, - 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587, - 48, 48, 588, 589, 140, 590, 591, 48, 48, 48, 48, 48, 48, 48, 48, 206, - 48, 48, 48, 48, 48, 48, 71, 151, 196, 592, 593, 140, 140, 140, 140, 140, - 32, 32, 594, 32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140, - 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598, - 599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140, - 140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461, - 9, 603, 11, 604, 605, 606, 241, 9, 607, 608, 609, 610, 611, 9, 603, 11, - 612, 613, 11, 614, 615, 616, 617, 9, 618, 11, 9, 603, 11, 604, 605, 11, - 241, 9, 607, 617, 9, 618, 11, 9, 603, 11, 619, 9, 620, 621, 622, 623, - 11, 624, 9, 625, 626, 627, 628, 11, 629, 9, 630, 11, 631, 632, 632, 632, - 32, 32, 32, 633, 32, 32, 634, 635, 636, 637, 45, 140, 140, 140, 140, 140, - 638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643, 27, 27, 27, 644, 140, - 645, 140, 140, 140, 140, 140, 140, 140, 48, 48, 151, 646, 647, 140, 140, 140, - 140, 48, 648, 140, 48, 48, 649, 650, 140, 140, 140, 140, 140, 48, 651, 192, - 140, 140, 140, 140, 140, 140, 652, 200, 48, 48, 48, 48, 653, 595, 140, 140, - 9, 9, 607, 11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499, - 271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140, - 659, 48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668, - 209, 209, 669, 209, 209, 209, 209, 209, 209, 323, 334, 670, 670, 670, 209, 324, - 671, 209, 209, 209, 209, 209, 209, 209, 209, 209, 672, 140, 140, 140, 673, 209, - 674, 209, 209, 669, 675, 676, 324, 140, 209, 209, 209, 209, 209, 209, 209, 677, - 209, 209, 209, 209, 209, 678, 426, 426, 209, 209, 209, 209, 209, 209, 209, 679, - 209, 209, 209, 209, 209, 176, 669, 427, 669, 209, 209, 209, 680, 176, 209, 209, - 680, 209, 672, 676, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 672, 426, - 675, 209, 209, 681, 682, 669, 675, 675, 209, 683, 209, 209, 288, 140, 140, 192, - 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 207, 48, 48, 48, 48, - 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 100, 48, 48, 48, 48, 48, 48, 204, 140, 140, - 48, 204, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 71, 48, 48, 48, - 48, 48, 48, 140, 140, 140, 140, 140, 684, 140, 570, 570, 570, 570, 570, 570, + 48, 48, 475, 192, 476, 9, 477, 11, 478, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 271, 479, 48, 48, 480, 481, 482, 140, 140, 483, + 48, 464, 484, 48, 62, 485, 140, 48, 486, 140, 140, 48, 487, 140, 48, 313, + 488, 48, 48, 489, 490, 457, 491, 492, 222, 48, 48, 493, 494, 48, 196, 192, + 495, 48, 496, 497, 498, 48, 48, 499, 222, 48, 48, 500, 501, 502, 503, 504, + 48, 97, 505, 506, 507, 140, 140, 140, 508, 509, 510, 48, 48, 511, 512, 192, + 513, 83, 84, 514, 515, 516, 517, 518, 519, 48, 48, 520, 521, 522, 523, 140, + 48, 48, 48, 524, 525, 526, 481, 140, 48, 48, 48, 527, 528, 192, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 529, 530, 531, 532, 140, 140, + 48, 48, 48, 533, 534, 192, 535, 140, 48, 48, 536, 537, 192, 538, 539, 140, + 48, 540, 541, 542, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 505, 543, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 544, + 545, 546, 48, 547, 548, 192, 140, 140, 140, 140, 549, 48, 48, 550, 551, 140, + 552, 48, 48, 553, 554, 555, 48, 48, 556, 557, 558, 48, 48, 48, 48, 196, + 559, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 560, 192, + 84, 48, 529, 561, 562, 148, 175, 563, 48, 564, 565, 566, 140, 140, 140, 140, + 567, 48, 48, 568, 569, 192, 570, 48, 571, 572, 192, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 573, + 574, 115, 48, 575, 576, 577, 140, 140, 140, 140, 140, 100, 271, 578, 579, 580, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 207, 140, 140, 140, 140, 140, 140, + 272, 272, 272, 272, 272, 272, 581, 582, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 583, + 48, 48, 48, 584, 585, 586, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 71, + 48, 48, 48, 48, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 587, 588, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 589, + 48, 48, 48, 590, 591, 592, 593, 594, 48, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 595, 48, 596, 192, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 9, 9, 11, 11, 271, 597, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 48, 598, 599, 600, 600, 601, 602, 140, 140, 140, 140, 603, 604, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 440, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 199, 140, 605, + 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 606, + 48, 48, 607, 608, 140, 609, 610, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 206, + 48, 48, 48, 48, 48, 48, 71, 151, 196, 611, 612, 140, 140, 140, 140, 140, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 192, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, 140, + 32, 32, 613, 32, 614, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, + 209, 209, 615, 209, 209, 209, 616, 617, 618, 209, 619, 209, 209, 209, 287, 140, + 209, 209, 209, 209, 620, 140, 140, 140, 140, 140, 140, 140, 271, 621, 271, 621, + 209, 209, 209, 209, 209, 338, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140, + 9, 622, 11, 623, 624, 625, 241, 9, 626, 627, 628, 629, 630, 9, 622, 11, + 631, 632, 11, 633, 634, 635, 636, 9, 637, 11, 9, 622, 11, 623, 624, 11, + 241, 9, 626, 636, 9, 637, 11, 9, 622, 11, 638, 9, 639, 640, 641, 642, + 11, 643, 9, 644, 645, 646, 647, 11, 648, 9, 649, 11, 650, 538, 538, 538, + 32, 32, 32, 651, 32, 32, 652, 653, 654, 655, 45, 140, 140, 140, 140, 140, + 656, 657, 658, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 659, 660, 661, 27, 27, 27, 662, 140, 663, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 151, 664, 665, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 666, 140, 48, 48, 667, 668, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 669, 192, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 587, 670, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 671, 200, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 672, 614, 140, 140, + 9, 9, 626, 11, 673, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 503, 271, 271, 674, 675, 140, 140, 140, 140, + 503, 271, 676, 677, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 678, 48, 679, 680, 681, 682, 683, 684, 685, 206, 686, 206, 140, 140, 140, 687, + 209, 209, 688, 209, 209, 209, 209, 209, 209, 322, 333, 689, 689, 689, 209, 323, + 690, 209, 209, 209, 209, 209, 209, 209, 209, 209, 691, 140, 140, 140, 692, 209, + 693, 209, 209, 688, 694, 695, 323, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 696, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 697, 426, 426, + 209, 209, 209, 209, 209, 209, 209, 698, 209, 209, 209, 209, 209, 176, 688, 427, + 688, 209, 209, 209, 699, 176, 209, 209, 699, 209, 691, 688, 695, 140, 140, 140, + 209, 209, 209, 209, 209, 322, 691, 426, 700, 209, 209, 209, 701, 702, 176, 694, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 703, 209, 209, 209, 209, 209, 192, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140, + 48, 48, 48, 207, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 481, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 48, + 48, 48, 48, 48, 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 48, 48, 48, 48, 71, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140, 140, 140, 140, + 704, 140, 584, 584, 584, 584, 584, 584, 140, 140, 140, 140, 140, 140, 140, 140, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140, - 391, 391, 391, 391, 391, 391, 391, 685, 391, 391, 391, 391, 391, 391, 391, 686, - 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0, - 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 11, 11, 11, 13, 11, - 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 16, 17, 18, 17, 17, 19, 20, 21, 21, 22, 21, 23, 24, - 25, 26, 27, 27, 28, 29, 27, 30, 27, 27, 27, 27, 27, 31, 27, 27, - 32, 33, 33, 33, 34, 27, 27, 27, 35, 35, 35, 36, 37, 37, 37, 38, - 39, 39, 40, 41, 42, 43, 44, 27, 45, 46, 27, 27, 27, 27, 47, 27, - 48, 48, 48, 48, 48, 49, 50, 48, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 109, 110, 111, 112, 109, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 122, 123, 122, 124, 125, 125, 126, 127, 128, 129, 130, 131, 125, 125, - 132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 125, 125, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141, - 142, 142, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 144, 145, 143, 143, - 144, 143, 143, 146, 147, 148, 143, 143, 143, 147, 143, 143, 143, 149, 143, 150, - 143, 151, 152, 152, 152, 152, 152, 153, 154, 154, 154, 154, 154, 154, 154, 154, - 155, 156, 157, 157, 157, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 168, 168, 168, 168, 169, 170, 170, 171, 172, 173, 173, 173, 173, 173, 174, - 173, 173, 175, 154, 154, 154, 154, 176, 177, 178, 179, 179, 180, 181, 182, 183, - 184, 184, 185, 184, 186, 187, 168, 168, 188, 189, 190, 190, 190, 191, 190, 192, - 193, 193, 194, 8, 195, 125, 125, 125, 196, 196, 196, 196, 197, 196, 196, 198, - 199, 199, 199, 199, 200, 200, 200, 201, 202, 202, 202, 203, 204, 205, 205, 205, - 206, 139, 139, 207, 208, 209, 210, 211, 4, 4, 212, 4, 4, 213, 214, 215, - 4, 4, 4, 216, 8, 8, 8, 8, 11, 217, 11, 11, 217, 218, 11, 219, - 11, 11, 11, 220, 220, 221, 11, 222, 223, 0, 0, 0, 0, 0, 224, 225, - 226, 227, 0, 0, 228, 8, 8, 229, 0, 0, 230, 231, 232, 0, 4, 4, - 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 234, 125, 235, 125, 0, 0, 236, 236, 236, 236, 236, 236, 236, 236, - 0, 0, 0, 0, 0, 0, 0, 237, 0, 238, 0, 0, 0, 0, 0, 0, - 239, 239, 239, 239, 239, 239, 4, 4, 240, 240, 240, 240, 240, 240, 240, 241, - 139, 139, 140, 242, 242, 242, 243, 244, 143, 245, 246, 246, 246, 246, 14, 14, - 0, 0, 0, 0, 0, 247, 125, 125, 248, 249, 248, 248, 248, 248, 248, 250, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 125, 0, - 252, 0, 253, 254, 255, 256, 256, 256, 256, 257, 258, 259, 259, 259, 259, 260, - 261, 262, 262, 263, 142, 142, 142, 142, 264, 0, 262, 262, 0, 0, 265, 259, - 142, 264, 0, 0, 0, 0, 142, 266, 0, 0, 0, 0, 0, 259, 259, 267, - 259, 259, 259, 259, 259, 268, 0, 0, 248, 248, 248, 248, 0, 0, 0, 0, - 269, 269, 269, 269, 269, 269, 269, 269, 270, 269, 269, 269, 271, 272, 272, 272, - 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 274, 125, 14, 14, 14, 14, - 14, 14, 275, 275, 275, 275, 275, 276, 0, 0, 277, 4, 4, 4, 4, 4, - 278, 4, 4, 4, 279, 280, 125, 281, 282, 282, 283, 284, 285, 285, 285, 286, - 287, 287, 287, 287, 288, 289, 48, 48, 290, 290, 291, 292, 292, 293, 142, 294, - 295, 295, 295, 295, 296, 297, 138, 298, 299, 299, 299, 300, 301, 302, 138, 138, - 303, 303, 303, 303, 304, 305, 306, 307, 308, 309, 246, 4, 4, 310, 311, 152, - 152, 152, 152, 152, 306, 306, 312, 313, 142, 142, 314, 142, 315, 142, 142, 316, - 125, 125, 125, 125, 125, 125, 125, 125, 248, 248, 248, 248, 248, 248, 317, 248, - 248, 248, 248, 248, 248, 318, 125, 125, 319, 320, 21, 321, 322, 27, 27, 27, - 27, 27, 27, 27, 323, 324, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 325, 27, 27, 27, 27, 27, 326, 27, 27, 327, 125, 125, 27, - 8, 284, 328, 0, 0, 329, 330, 331, 27, 27, 27, 27, 27, 27, 27, 332, - 333, 0, 1, 2, 1, 2, 334, 258, 259, 335, 142, 264, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 344, 125, 125, 341, 341, 341, 341, 341, 341, 341, 345, - 346, 0, 0, 347, 11, 11, 11, 11, 348, 349, 350, 125, 125, 0, 0, 351, - 352, 353, 354, 354, 354, 355, 356, 357, 358, 358, 359, 360, 361, 362, 362, 363, - 364, 365, 366, 366, 367, 368, 125, 125, 369, 369, 369, 369, 369, 370, 370, 370, - 371, 372, 373, 374, 374, 375, 374, 376, 377, 377, 378, 379, 379, 379, 380, 381, - 381, 382, 383, 384, 125, 125, 125, 125, 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 386, 385, 387, 388, 125, 389, 4, 4, 390, 125, 125, 125, 125, - 391, 392, 392, 393, 394, 395, 396, 396, 397, 398, 399, 125, 125, 125, 400, 401, - 402, 403, 404, 405, 125, 125, 125, 125, 406, 406, 407, 408, 407, 409, 407, 407, - 410, 411, 412, 413, 414, 414, 415, 415, 416, 416, 125, 125, 417, 417, 418, 419, - 420, 420, 420, 421, 422, 423, 424, 425, 426, 427, 428, 125, 125, 125, 125, 125, - 429, 429, 429, 429, 430, 125, 125, 125, 431, 431, 431, 432, 431, 431, 431, 433, - 434, 434, 435, 436, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 27, 45, - 437, 437, 438, 439, 125, 125, 125, 440, 441, 441, 442, 443, 443, 444, 125, 445, - 446, 125, 125, 447, 448, 125, 449, 450, 451, 451, 451, 451, 452, 453, 451, 454, - 455, 455, 455, 455, 456, 457, 458, 459, 460, 460, 460, 461, 462, 463, 463, 464, - 465, 465, 465, 465, 465, 465, 466, 467, 468, 469, 468, 468, 470, 125, 125, 125, - 471, 472, 473, 474, 474, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 485, 485, 485, 485, 486, 487, 125, 488, 488, 488, 488, 489, 490, 125, 125, - 491, 491, 491, 492, 491, 493, 125, 125, 494, 494, 494, 494, 495, 496, 497, 125, - 498, 498, 498, 499, 499, 125, 125, 125, 500, 501, 502, 500, 503, 125, 125, 125, - 504, 504, 504, 505, 125, 125, 125, 125, 125, 125, 506, 506, 506, 506, 506, 507, - 508, 509, 510, 511, 512, 513, 125, 125, 125, 125, 514, 515, 515, 514, 516, 125, - 517, 517, 517, 517, 518, 519, 519, 519, 519, 519, 520, 154, 521, 521, 521, 522, - 523, 125, 125, 125, 125, 125, 125, 125, 524, 525, 525, 526, 527, 525, 528, 529, - 529, 530, 531, 532, 125, 125, 125, 125, 533, 534, 534, 535, 536, 537, 538, 539, - 540, 541, 542, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 543, 544, - 545, 546, 545, 547, 545, 548, 125, 125, 125, 125, 125, 549, 550, 550, 550, 551, - 552, 552, 552, 552, 552, 552, 552, 552, 552, 553, 125, 125, 125, 125, 125, 125, - 552, 552, 552, 552, 552, 552, 554, 555, 552, 552, 552, 552, 556, 125, 125, 125, - 125, 557, 557, 557, 557, 557, 557, 558, 559, 559, 559, 559, 559, 559, 559, 559, - 559, 559, 559, 559, 559, 560, 125, 125, 561, 561, 561, 561, 561, 561, 561, 561, - 561, 561, 561, 561, 562, 125, 125, 125, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 563, 564, 565, 566, 567, 567, 567, 567, 568, 569, 570, 571, 572, - 573, 573, 573, 573, 574, 575, 576, 577, 573, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 578, 578, 578, 578, 578, 579, 125, 125, 125, 125, 125, 125, - 580, 580, 580, 580, 581, 580, 580, 580, 582, 580, 125, 125, 125, 125, 583, 584, - 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 586, - 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 588, 125, 125, - 589, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 590, - 591, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 592, 593, 125, 594, 595, 596, 596, 596, 596, 596, 596, 596, 596, 596, - 596, 596, 596, 596, 596, 596, 596, 597, 598, 598, 598, 598, 598, 598, 599, 600, - 601, 602, 603, 125, 125, 125, 125, 125, 8, 8, 604, 8, 605, 0, 0, 0, - 0, 0, 0, 0, 603, 125, 125, 125, 0, 0, 0, 0, 0, 0, 0, 606, - 0, 0, 607, 0, 0, 0, 608, 609, 610, 0, 611, 0, 0, 0, 235, 125, - 11, 11, 11, 11, 612, 125, 125, 125, 125, 125, 125, 125, 0, 603, 0, 603, - 0, 0, 0, 0, 0, 234, 0, 613, 0, 0, 0, 0, 0, 224, 0, 0, - 0, 614, 615, 616, 617, 0, 0, 0, 618, 619, 0, 620, 621, 622, 0, 0, - 0, 0, 623, 0, 0, 0, 0, 0, 0, 0, 0, 0, 624, 0, 0, 0, - 625, 625, 625, 625, 625, 625, 625, 625, 626, 627, 628, 125, 125, 125, 125, 125, - 4, 629, 630, 125, 125, 125, 125, 125, 631, 632, 633, 14, 14, 14, 634, 125, - 635, 125, 125, 125, 125, 125, 125, 125, 636, 636, 637, 638, 639, 125, 125, 125, - 125, 640, 641, 125, 642, 642, 642, 643, 125, 125, 125, 125, 125, 644, 644, 645, - 125, 125, 125, 125, 125, 125, 646, 647, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 649, 650, 125, 125, 651, 651, 651, 651, 652, 653, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 333, 0, 0, 0, 654, 125, 125, 125, 125, - 333, 0, 0, 247, 125, 125, 125, 125, 655, 27, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 663, 125, 125, 125, 665, 0, 0, 357, 0, 0, 0, 0, 0, - 0, 603, 226, 333, 333, 333, 0, 606, 0, 0, 247, 125, 125, 125, 666, 0, - 667, 0, 0, 357, 613, 668, 606, 125, 0, 0, 0, 0, 0, 669, 349, 349, - 0, 0, 0, 0, 0, 0, 0, 670, 0, 0, 0, 0, 0, 284, 357, 228, - 357, 0, 0, 0, 671, 284, 0, 0, 671, 0, 247, 668, 125, 125, 125, 125, - 0, 0, 0, 0, 0, 603, 247, 349, 613, 0, 0, 672, 673, 357, 613, 613, - 0, 329, 0, 0, 235, 125, 125, 284, 248, 248, 248, 248, 248, 248, 125, 125, - 248, 248, 248, 318, 248, 248, 248, 248, 248, 317, 248, 248, 248, 248, 248, 248, - 248, 248, 584, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 674, 248, - 248, 248, 248, 248, 248, 317, 125, 125, 248, 317, 125, 125, 125, 125, 125, 125, - 248, 248, 248, 248, 675, 248, 248, 248, 248, 248, 248, 125, 125, 125, 125, 125, - 676, 125, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 1, 2, 2, 2, - 2, 2, 3, 0, 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, - 2, 2, 5, 0, 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 8, 8, 8, 8, 16, 8, 8, 8, 17, 18, 18, 18, - 19, 19, 19, 19, 19, 20, 19, 19, 21, 22, 22, 22, 22, 22, 22, 22, - 22, 23, 21, 22, 22, 22, 23, 21, 24, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 12, 12, 25, 25, 26, 27, 25, 28, 12, 12, 29, 30, 29, 31, - 29, 29, 32, 32, 29, 29, 29, 29, 31, 29, 33, 7, 7, 34, 29, 29, - 35, 29, 29, 29, 29, 29, 29, 30, 36, 36, 36, 37, 36, 36, 36, 36, - 36, 36, 38, 39, 40, 40, 40, 40, 41, 12, 12, 12, 42, 42, 42, 42, - 42, 42, 43, 44, 45, 45, 45, 45, 45, 45, 45, 46, 45, 45, 45, 47, - 48, 48, 48, 48, 48, 48, 48, 49, 36, 36, 38, 12, 29, 29, 29, 50, - 51, 12, 29, 29, 52, 29, 29, 29, 53, 53, 53, 53, 54, 55, 53, 53, - 53, 56, 53, 53, 57, 58, 57, 59, 59, 57, 57, 57, 57, 57, 60, 57, - 61, 62, 63, 57, 57, 59, 59, 64, 12, 65, 12, 66, 57, 62, 57, 57, - 57, 57, 57, 64, 67, 67, 68, 69, 70, 71, 71, 71, 71, 71, 72, 71, - 72, 73, 74, 72, 68, 69, 70, 74, 75, 12, 67, 76, 12, 77, 71, 71, - 71, 68, 12, 12, 78, 78, 79, 80, 80, 79, 79, 79, 79, 79, 81, 79, - 81, 78, 82, 79, 79, 80, 80, 82, 83, 12, 12, 12, 79, 84, 79, 79, - 82, 12, 78, 79, 85, 85, 86, 87, 87, 86, 86, 86, 86, 86, 88, 86, - 88, 85, 89, 86, 86, 87, 87, 89, 12, 85, 12, 90, 86, 91, 86, 86, - 86, 86, 12, 12, 92, 93, 94, 92, 95, 96, 97, 95, 98, 99, 94, 92, - 100, 100, 96, 92, 94, 92, 95, 96, 99, 98, 12, 12, 12, 92, 100, 100, - 100, 100, 94, 12, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 102, 101, - 101, 101, 103, 101, 101, 102, 102, 103, 12, 104, 105, 106, 101, 107, 101, 101, - 12, 108, 101, 101, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 110, 109, - 109, 111, 112, 109, 109, 110, 110, 112, 12, 113, 12, 113, 109, 114, 109, 109, - 111, 12, 12, 12, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115, - 115, 116, 116, 115, 12, 115, 115, 115, 115, 117, 115, 115, 118, 118, 119, 119, - 119, 120, 121, 119, 119, 119, 119, 119, 122, 119, 119, 123, 119, 120, 124, 125, - 119, 126, 119, 119, 12, 121, 119, 119, 121, 127, 12, 12, 128, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 130, 131, 129, 129, 129, 12, 12, 12, 12, 12, - 132, 133, 134, 135, 135, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 137, - 135, 138, 135, 134, 135, 135, 137, 135, 139, 139, 139, 139, 139, 139, 140, 139, - 139, 139, 139, 141, 140, 139, 139, 139, 139, 139, 139, 142, 139, 143, 144, 12, - 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 12, 148, 146, 146, 149, 146, - 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 152, 153, 151, 154, 152, 153, - 152, 153, 151, 154, 152, 153, 151, 151, 151, 154, 151, 151, 151, 151, 154, 155, - 151, 151, 151, 156, 151, 151, 153, 12, 157, 157, 157, 157, 157, 158, 157, 158, - 159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 162, 162, 162, 162, - 162, 162, 163, 164, 162, 162, 165, 12, 166, 166, 166, 166, 166, 167, 12, 168, - 169, 169, 169, 169, 169, 170, 12, 12, 171, 171, 171, 171, 171, 12, 12, 12, - 172, 172, 172, 173, 173, 12, 12, 12, 174, 174, 174, 174, 174, 174, 174, 175, - 174, 174, 175, 12, 176, 177, 178, 178, 178, 178, 179, 12, 178, 178, 178, 178, - 178, 178, 180, 12, 178, 178, 181, 12, 159, 182, 12, 12, 183, 183, 183, 183, - 183, 183, 183, 184, 183, 183, 183, 12, 185, 183, 183, 183, 186, 186, 186, 186, - 186, 186, 186, 187, 186, 188, 12, 12, 189, 189, 189, 189, 189, 189, 189, 12, - 189, 189, 190, 12, 189, 189, 191, 192, 193, 193, 193, 193, 193, 193, 193, 194, - 195, 195, 195, 195, 195, 195, 195, 196, 195, 195, 195, 197, 195, 195, 198, 12, - 195, 195, 195, 198, 7, 7, 7, 199, 200, 200, 200, 200, 200, 200, 200, 201, - 200, 200, 200, 202, 203, 203, 203, 203, 204, 204, 204, 204, 204, 12, 12, 204, - 205, 205, 205, 205, 205, 205, 206, 205, 205, 205, 207, 208, 209, 209, 209, 209, - 19, 19, 210, 12, 146, 146, 211, 212, 203, 203, 12, 12, 213, 7, 7, 7, - 214, 7, 215, 216, 0, 215, 217, 12, 2, 218, 219, 2, 2, 2, 2, 220, - 221, 218, 222, 2, 2, 2, 223, 2, 2, 2, 2, 224, 8, 225, 8, 225, - 8, 8, 226, 226, 8, 8, 8, 225, 8, 15, 8, 8, 8, 10, 8, 227, - 10, 15, 8, 14, 0, 0, 0, 228, 0, 229, 0, 0, 230, 0, 0, 231, - 0, 0, 0, 232, 2, 2, 2, 233, 234, 12, 12, 12, 235, 12, 12, 12, - 0, 236, 237, 0, 4, 0, 0, 0, 0, 0, 0, 4, 2, 2, 5, 12, - 0, 232, 12, 12, 0, 0, 232, 12, 238, 238, 238, 238, 0, 239, 0, 0, - 0, 240, 0, 0, 241, 241, 241, 241, 18, 18, 18, 18, 18, 12, 242, 18, - 243, 243, 243, 243, 243, 243, 12, 244, 245, 12, 12, 244, 151, 154, 12, 12, - 151, 154, 151, 154, 0, 0, 0, 246, 247, 247, 247, 247, 247, 247, 248, 247, - 247, 12, 12, 12, 247, 249, 12, 12, 0, 250, 0, 0, 251, 247, 252, 253, - 0, 0, 247, 0, 254, 255, 255, 255, 255, 255, 255, 255, 255, 256, 257, 258, - 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 261, 259, 12, 262, 263, 263, - 263, 263, 263, 263, 264, 150, 150, 150, 150, 150, 150, 265, 0, 12, 12, 131, - 150, 150, 150, 266, 260, 260, 260, 261, 260, 260, 0, 0, 267, 267, 267, 267, - 267, 267, 267, 268, 267, 269, 12, 12, 270, 270, 270, 270, 271, 271, 271, 271, - 271, 271, 271, 12, 272, 272, 272, 272, 272, 272, 12, 12, 237, 2, 2, 2, - 2, 2, 231, 2, 2, 2, 273, 12, 274, 275, 276, 12, 277, 2, 2, 2, - 278, 278, 278, 278, 278, 278, 278, 279, 0, 0, 246, 12, 280, 280, 280, 280, - 280, 280, 12, 12, 281, 281, 281, 281, 281, 282, 12, 283, 281, 281, 282, 12, - 284, 284, 284, 284, 284, 284, 284, 285, 286, 286, 286, 286, 286, 12, 12, 287, - 150, 150, 150, 288, 289, 289, 289, 289, 289, 289, 289, 290, 289, 289, 291, 292, - 145, 145, 145, 293, 294, 294, 294, 294, 294, 295, 12, 12, 294, 294, 294, 296, - 294, 294, 296, 294, 297, 297, 297, 297, 298, 12, 12, 12, 12, 12, 299, 297, - 300, 300, 300, 300, 300, 301, 12, 12, 155, 154, 155, 154, 155, 154, 12, 12, - 2, 2, 3, 2, 2, 302, 303, 12, 300, 300, 300, 304, 300, 300, 304, 12, - 150, 12, 12, 12, 150, 265, 305, 150, 150, 150, 150, 12, 247, 247, 247, 249, - 247, 247, 249, 12, 2, 273, 12, 12, 306, 22, 12, 24, 25, 26, 25, 307, - 308, 309, 25, 25, 50, 12, 12, 12, 310, 29, 29, 29, 29, 29, 29, 311, - 312, 29, 29, 29, 29, 29, 12, 310, 7, 7, 7, 313, 232, 0, 0, 0, - 0, 232, 0, 12, 29, 314, 29, 29, 29, 29, 29, 315, 316, 0, 0, 0, - 0, 317, 260, 260, 260, 260, 260, 318, 319, 150, 319, 150, 319, 150, 319, 288, - 0, 232, 0, 232, 12, 12, 316, 246, 320, 320, 320, 321, 320, 320, 320, 320, - 320, 322, 320, 320, 320, 320, 322, 323, 320, 320, 320, 324, 320, 320, 322, 12, - 232, 131, 0, 0, 0, 131, 0, 0, 8, 8, 8, 14, 0, 0, 0, 234, - 325, 12, 12, 12, 0, 0, 0, 326, 327, 327, 327, 327, 327, 327, 327, 328, - 329, 329, 329, 329, 330, 12, 12, 12, 215, 0, 0, 0, 0, 0, 0, 12, - 331, 331, 331, 331, 331, 12, 12, 332, 333, 333, 333, 333, 333, 333, 334, 12, - 335, 335, 335, 335, 335, 335, 336, 12, 337, 337, 337, 337, 337, 337, 337, 338, - 339, 339, 339, 339, 339, 12, 339, 339, 339, 340, 12, 12, 341, 341, 341, 341, - 342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 344, 343, 343, 344, 12, - 345, 345, 345, 345, 345, 12, 345, 345, 345, 345, 345, 12, 346, 346, 346, 346, - 346, 346, 12, 12, 347, 347, 347, 347, 347, 12, 12, 348, 349, 349, 350, 349, - 350, 351, 349, 349, 351, 349, 349, 349, 351, 349, 351, 352, 353, 353, 353, 353, - 353, 354, 12, 12, 353, 355, 12, 12, 353, 353, 12, 12, 2, 274, 2, 2, - 356, 2, 273, 12, 357, 358, 359, 357, 357, 357, 357, 357, 357, 360, 361, 362, - 363, 363, 363, 363, 363, 364, 363, 363, 365, 365, 365, 365, 366, 366, 366, 366, - 366, 366, 366, 367, 12, 368, 366, 366, 369, 369, 369, 369, 370, 371, 372, 369, - 373, 373, 373, 373, 373, 373, 373, 374, 375, 375, 375, 375, 375, 375, 376, 377, - 378, 378, 378, 378, 379, 379, 379, 379, 379, 379, 12, 379, 380, 379, 379, 379, - 381, 382, 12, 381, 381, 383, 383, 381, 381, 381, 381, 381, 381, 384, 385, 386, - 381, 381, 387, 12, 388, 388, 388, 388, 389, 389, 389, 389, 390, 390, 390, 390, - 390, 391, 392, 390, 390, 391, 12, 12, 393, 393, 393, 393, 393, 394, 395, 393, - 396, 396, 396, 396, 396, 397, 396, 396, 398, 398, 398, 398, 399, 12, 398, 398, - 400, 400, 400, 400, 401, 12, 402, 403, 12, 12, 402, 400, 404, 404, 404, 404, - 404, 404, 405, 12, 406, 406, 406, 406, 407, 12, 12, 12, 407, 12, 408, 406, - 409, 409, 409, 409, 409, 409, 12, 12, 409, 409, 410, 12, 411, 411, 411, 411, - 411, 411, 412, 413, 413, 12, 12, 12, 12, 12, 12, 414, 415, 415, 415, 415, - 415, 415, 12, 12, 416, 416, 416, 416, 416, 416, 417, 12, 418, 418, 418, 418, - 418, 418, 419, 12, 420, 420, 420, 420, 420, 420, 420, 12, 421, 421, 421, 421, - 421, 422, 12, 12, 423, 423, 423, 423, 423, 423, 423, 424, 425, 423, 423, 423, - 423, 424, 12, 426, 427, 427, 427, 427, 428, 12, 12, 429, 430, 430, 430, 430, - 430, 430, 431, 12, 430, 430, 432, 12, 433, 433, 433, 433, 433, 434, 433, 433, - 433, 433, 12, 12, 435, 435, 435, 435, 435, 436, 12, 12, 437, 437, 437, 437, - 118, 119, 119, 119, 119, 127, 12, 12, 438, 438, 438, 438, 439, 438, 438, 438, - 440, 12, 12, 12, 441, 442, 443, 444, 441, 441, 441, 444, 441, 441, 445, 12, - 446, 446, 446, 446, 446, 446, 447, 12, 446, 446, 448, 12, 449, 450, 449, 451, - 451, 449, 449, 449, 449, 449, 452, 449, 452, 450, 453, 449, 449, 451, 451, 454, - 455, 456, 12, 450, 449, 457, 449, 455, 449, 455, 12, 12, 458, 458, 458, 458, - 458, 458, 458, 459, 460, 12, 12, 12, 461, 461, 461, 461, 461, 461, 12, 12, - 461, 461, 462, 12, 463, 463, 463, 463, 463, 464, 463, 463, 463, 463, 463, 464, - 465, 465, 465, 465, 465, 466, 12, 12, 465, 465, 467, 12, 178, 178, 178, 180, - 468, 468, 468, 468, 468, 468, 469, 12, 470, 470, 470, 470, 470, 470, 471, 472, - 470, 470, 470, 12, 470, 471, 12, 12, 473, 473, 473, 473, 473, 473, 473, 12, - 474, 474, 474, 474, 475, 12, 12, 476, 477, 478, 479, 477, 477, 480, 477, 477, - 477, 477, 477, 477, 477, 481, 482, 477, 477, 478, 12, 12, 477, 477, 483, 12, - 484, 484, 485, 484, 484, 484, 484, 484, 484, 486, 12, 12, 487, 487, 487, 487, - 487, 487, 12, 12, 488, 488, 488, 488, 489, 12, 12, 12, 490, 490, 490, 490, - 490, 490, 491, 12, 53, 53, 492, 12, 493, 493, 494, 493, 493, 493, 493, 493, - 493, 495, 493, 493, 493, 496, 12, 12, 493, 493, 493, 497, 498, 498, 498, 498, - 499, 498, 498, 498, 498, 498, 500, 498, 498, 501, 12, 12, 502, 503, 504, 502, - 502, 502, 502, 502, 502, 503, 505, 504, 502, 502, 12, 12, 502, 502, 506, 12, - 507, 508, 509, 507, 507, 507, 507, 507, 507, 507, 507, 510, 508, 507, 511, 12, - 507, 507, 512, 12, 513, 513, 513, 513, 513, 513, 514, 12, 515, 515, 515, 515, - 516, 515, 515, 515, 515, 515, 517, 518, 515, 515, 519, 12, 520, 12, 12, 12, - 100, 100, 100, 100, 96, 12, 12, 98, 521, 521, 521, 521, 521, 521, 522, 12, - 521, 521, 521, 523, 521, 524, 12, 12, 521, 12, 12, 12, 525, 525, 525, 525, - 526, 12, 12, 12, 527, 527, 527, 527, 527, 528, 12, 12, 529, 529, 529, 529, - 529, 530, 12, 12, 272, 272, 531, 12, 532, 532, 532, 532, 532, 532, 532, 533, - 532, 532, 534, 535, 536, 536, 536, 536, 536, 536, 536, 537, 536, 536, 538, 12, - 539, 539, 539, 539, 539, 539, 539, 540, 539, 540, 12, 12, 541, 541, 541, 541, - 541, 542, 12, 12, 541, 541, 543, 541, 543, 541, 541, 541, 541, 541, 12, 544, - 545, 545, 545, 545, 545, 545, 546, 12, 547, 547, 547, 547, 547, 547, 548, 549, - 547, 547, 12, 549, 550, 551, 12, 12, 249, 12, 12, 12, 552, 552, 552, 552, - 552, 552, 12, 12, 553, 553, 553, 553, 553, 554, 12, 12, 552, 552, 555, 12, - 260, 556, 260, 557, 558, 255, 255, 255, 559, 12, 12, 12, 560, 12, 12, 12, - 256, 561, 12, 12, 12, 260, 12, 12, 562, 562, 562, 562, 562, 562, 562, 12, - 563, 563, 563, 563, 563, 563, 564, 12, 563, 563, 563, 565, 563, 563, 565, 12, - 563, 563, 566, 563, 0, 12, 12, 12, 7, 7, 7, 567, 7, 199, 12, 12, - 0, 246, 12, 12, 0, 232, 316, 0, 0, 568, 228, 0, 0, 0, 568, 7, - 213, 569, 7, 0, 0, 0, 570, 228, 8, 225, 12, 12, 0, 0, 234, 12, - 0, 0, 0, 229, 571, 572, 316, 229, 0, 0, 240, 316, 0, 316, 0, 0, - 0, 240, 232, 316, 0, 229, 0, 229, 0, 0, 240, 232, 0, 573, 239, 0, - 229, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 239, 574, 574, 574, 574, - 574, 574, 574, 12, 12, 12, 575, 574, 576, 574, 574, 574, 2, 2, 2, 273, - 12, 275, 273, 12, 241, 577, 241, 241, 241, 241, 578, 241, 579, 580, 577, 12, - 19, 19, 19, 581, 12, 12, 12, 582, 583, 583, 583, 583, 583, 583, 583, 584, - 583, 583, 583, 585, 583, 583, 585, 586, 587, 587, 587, 587, 587, 587, 587, 588, - 589, 589, 589, 589, 589, 589, 590, 591, 592, 592, 592, 592, 592, 592, 593, 12, - 151, 154, 151, 594, 151, 151, 151, 154, 595, 595, 595, 595, 595, 596, 595, 595, - 595, 597, 12, 12, 598, 598, 598, 598, 598, 598, 598, 12, 598, 598, 599, 600, - 0, 234, 12, 12, 29, 414, 29, 29, 601, 602, 414, 29, 50, 29, 603, 12, - 604, 310, 603, 414, 601, 602, 603, 603, 601, 602, 50, 29, 50, 29, 414, 605, - 29, 29, 606, 29, 29, 29, 29, 12, 414, 414, 606, 29, 51, 12, 12, 12, - 12, 239, 0, 0, 607, 12, 12, 12, 246, 12, 12, 12, 0, 0, 12, 0, - 0, 232, 131, 0, 0, 0, 12, 12, 0, 0, 0, 240, 0, 246, 12, 239, - 608, 12, 12, 12, 247, 247, 609, 12, 610, 12, 12, 12, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 939, 940, 941, 942, - 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, 0,1033,1040,1041, - 1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,1124,1125,1126,1127, - 1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193, 0,1219,1226,1227, - 1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303, 943,1128, 944,1129, - 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149, 0, 0, 973,1158, - 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, 991,1176, 993,1178, - 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199,1007, 0, 0, 0, - 1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0, 0, 0, 0,1032, - 1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231,1049,1235, 0, 0, - 1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,1069,1255,1077,1264, - 1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275,1089,1276,1096,1283, - 1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0,1053,1239, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093,1280, 0, 0, 0, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 705, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 706, + 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 0, 6, 7, 7, 7, 8, 9, 10, 11, 12, + 13, 13, 13, 13, 14, 13, 13, 13, 13, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 23, 23, 26, 23, 27, 28, 29, 23, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 23, 23, 39, 40, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 82, 86, 86, 87, 88, 89, 90, 91, 82, + 92, 92, 92, 92, 92, 93, 94, 95, 96, 96, 96, 96, 96, 96, 96, 96, + 97, 97, 98, 97, 99, 100, 101, 97, 102, 97, 103, 104, 105, 106, 106, 107, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 110, 110, 111, + 112, 113, 114, 115, 116, 116, 117, 118, 119, 120, 120, 121, 120, 122, 108, 123, + 124, 125, 126, 127, 128, 129, 130, 116, 131, 132, 133, 134, 135, 136, 137, 82, + 138, 138, 139, 138, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 4, 151, 152, 153, 4, 154, 7, 7, 155, 11, 156, 157, 11, 158, 159, 160, + 161, 0, 0, 162, 163, 0, 164, 165, 0, 166, 167, 4, 168, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 170, 0, 0, 0, 0, 0, + 171, 171, 171, 171, 171, 171, 171, 171, 0, 0, 0, 172, 173, 0, 0, 0, + 174, 174, 174, 4, 175, 175, 175, 176, 93, 177, 178, 179, 180, 181, 181, 13, + 0, 0, 182, 82, 183, 184, 184, 185, 184, 184, 184, 184, 184, 184, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 96, 96, 198, 199, 0, 200, + 201, 0, 0, 202, 0, 0, 203, 204, 194, 194, 205, 0, 0, 0, 0, 0, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 0, 0, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 207, 206, 208, 209, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 211, 13, 13, 13, 212, 212, 213, + 0, 214, 4, 4, 215, 4, 216, 217, 218, 219, 220, 221, 222, 222, 223, 40, + 224, 225, 226, 227, 228, 228, 229, 230, 231, 232, 233, 92, 234, 234, 235, 236, + 237, 238, 239, 240, 106, 106, 241, 242, 96, 96, 96, 96, 96, 243, 244, 245, + 82, 82, 82, 82, 82, 82, 82, 82, 184, 184, 184, 246, 184, 184, 247, 82, + 248, 249, 250, 23, 23, 23, 251, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 252, 23, 23, 253, 23, 254, 255, 256, 257, 258, 259, 23, 23, 23, 260, + 261, 1, 1, 262, 263, 201, 264, 265, 266, 267, 268, 82, 269, 269, 269, 270, + 271, 272, 11, 11, 273, 274, 187, 275, 82, 82, 82, 82, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 82, 287, 287, 288, 289, 290, 291, 292, 293, + 294, 295, 296, 297, 298, 299, 300, 301, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 303, 304, 305, 306, 307, 82, 82, 308, 309, 310, 311, 312, 313, 82, 314, + 315, 316, 82, 82, 317, 318, 319, 320, 321, 322, 323, 324, 325, 82, 326, 327, + 328, 329, 330, 331, 332, 333, 82, 82, 334, 334, 335, 82, 336, 337, 336, 338, + 339, 340, 341, 342, 343, 82, 82, 82, 82, 82, 82, 344, 345, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 357, 358, 359, 360, 360, 361, 362, + 363, 364, 365, 366, 367, 367, 367, 368, 369, 370, 371, 82, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 384, 384, 385, 386, 387, 387, 388, 82, + 82, 82, 82, 82, 389, 390, 391, 82, 392, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 401, 82, 82, 82, 82, 82, 402, 403, 82, 82, 82, 404, 404, 405, + 406, 407, 408, 82, 82, 409, 410, 411, 412, 412, 413, 414, 414, 415, 416, 417, + 418, 82, 82, 82, 82, 82, 419, 420, 421, 422, 423, 424, 425, 426, 82, 82, + 427, 428, 429, 430, 431, 432, 82, 82, 82, 82, 82, 82, 82, 82, 82, 433, + 434, 435, 436, 82, 82, 437, 438, 439, 440, 440, 440, 440, 440, 440, 440, 440, + 440, 440, 440, 440, 441, 82, 82, 82, 440, 440, 440, 442, 440, 440, 440, 440, + 440, 440, 443, 82, 82, 82, 82, 82, 82, 82, 82, 82, 444, 445, 445, 446, + 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 448, 447, 447, 447, 447, 447, + 447, 447, 447, 447, 447, 447, 447, 449, 450, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 451, 82, 82, 82, 82, 82, 452, 453, 82, 82, 82, 82, 82, 82, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 454, 455, 456, 457, 458, 459, 460, + 461, 461, 462, 463, 464, 82, 82, 82, 82, 82, 465, 466, 82, 82, 82, 82, + 82, 82, 467, 467, 468, 82, 82, 82, 469, 469, 470, 469, 471, 82, 82, 472, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 474, + 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 477, + 478, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 479, + 480, 191, 191, 191, 191, 191, 191, 191, 191, 481, 482, 483, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 485, 486, 486, 486, 487, 488, 489, 82, 82, + 0, 0, 0, 0, 0, 0, 0, 490, 0, 0, 0, 0, 0, 491, 82, 82, + 7, 492, 493, 0, 0, 0, 489, 82, 0, 0, 0, 0, 0, 0, 0, 494, + 0, 495, 0, 496, 497, 498, 0, 170, 11, 11, 499, 82, 82, 82, 491, 491, + 0, 0, 500, 501, 82, 82, 82, 82, 0, 0, 502, 0, 503, 504, 505, 0, + 506, 507, 508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 509, 0, 0, + 0, 0, 0, 0, 0, 0, 510, 0, 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 512, 513, 82, 82, 514, 515, 82, 82, 82, 82, 82, 82, + 516, 517, 13, 518, 519, 82, 82, 82, 520, 521, 522, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 523, 524, 525, 526, 82, 82, 82, 82, 82, 82, 527, 528, + 82, 82, 82, 82, 82, 82, 529, 530, 82, 82, 82, 82, 82, 82, 82, 531, + 532, 532, 532, 532, 532, 532, 533, 82, 534, 534, 535, 82, 82, 82, 82, 82, + 82, 82, 82, 536, 0, 537, 82, 82, 261, 182, 82, 82, 82, 82, 82, 82, + 538, 539, 540, 541, 542, 543, 82, 544, 0, 545, 0, 0, 491, 546, 547, 494, + 0, 0, 0, 0, 0, 548, 82, 549, 550, 551, 552, 553, 82, 82, 82, 82, + 0, 0, 0, 0, 0, 0, 554, 555, 0, 0, 0, 556, 0, 0, 490, 557, + 545, 0, 558, 0, 559, 560, 561, 82, 0, 0, 491, 562, 563, 0, 564, 565, + 0, 0, 0, 0, 258, 0, 0, 490, 184, 184, 184, 184, 184, 184, 184, 82, + 184, 247, 184, 184, 184, 184, 184, 184, 566, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 567, 184, 184, 184, 184, 184, 184, 184, 184, 184, 568, + 184, 184, 566, 82, 82, 82, 82, 82, 566, 82, 82, 82, 82, 82, 82, 82, + 184, 184, 569, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 570, 82, 82, + 571, 0, 0, 0, 82, 82, 82, 82, 7, 7, 7, 7, 7, 7, 7, 572, + 0, 0, 0, 0, 1, 2, 2, 3, 0, 4, 0, 4, 2, 2, 5, 2, + 2, 2, 2, 2, 2, 2, 2, 6, 7, 8, 0, 0, 9, 9, 9, 9, + 9, 9, 10, 11, 12, 13, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, + 16, 17, 14, 14, 18, 18, 18, 18, 19, 18, 18, 18, 18, 18, 20, 21, + 21, 21, 22, 20, 21, 21, 21, 21, 21, 23, 24, 25, 25, 25, 25, 25, + 25, 26, 25, 25, 25, 27, 28, 26, 29, 30, 31, 32, 31, 31, 31, 31, + 33, 34, 35, 31, 31, 31, 36, 31, 31, 31, 31, 29, 37, 38, 37, 37, + 37, 37, 37, 37, 37, 39, 31, 31, 40, 40, 40, 40, 40, 40, 41, 26, + 42, 42, 42, 42, 42, 42, 42, 43, 44, 44, 44, 44, 44, 45, 44, 46, + 47, 47, 47, 48, 37, 49, 31, 31, 31, 50, 51, 31, 52, 31, 31, 31, + 53, 53, 53, 53, 53, 53, 54, 53, 55, 53, 53, 53, 56, 57, 58, 59, + 59, 60, 61, 62, 57, 63, 64, 65, 66, 59, 59, 67, 68, 69, 70, 71, + 71, 72, 73, 74, 69, 75, 76, 77, 78, 71, 79, 26, 80, 81, 82, 83, + 83, 84, 85, 86, 81, 87, 88, 26, 89, 83, 90, 91, 92, 93, 94, 95, + 95, 96, 97, 98, 93, 99, 100, 101, 102, 95, 95, 26, 103, 104, 105, 106, + 107, 104, 108, 109, 104, 105, 110, 26, 111, 108, 108, 112, 113, 114, 115, 113, + 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122, + 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130, 26, 131, 132, 133, 131, + 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139, + 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145, 26, 146, 147, 147, 147, + 147, 147, 147, 148, 147, 147, 147, 149, 26, 26, 26, 26, 150, 151, 152, 152, + 153, 152, 152, 154, 155, 156, 152, 157, 158, 158, 158, 158, 158, 159, 158, 158, + 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161, 158, 161, 162, 163, + 164, 164, 164, 164, 165, 165, 165, 165, 166, 167, 165, 165, 165, 165, 165, 168, + 169, 169, 169, 169, 170, 170, 170, 170, 170, 171, 172, 171, 170, 171, 170, 170, + 170, 170, 171, 172, 171, 170, 172, 170, 170, 170, 171, 170, 170, 170, 170, 173, + 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176, 176, 176, 177, 177, + 178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181, 181, 182, 181, 183, + 184, 184, 185, 186, 187, 187, 188, 26, 189, 189, 190, 26, 191, 192, 193, 26, + 194, 194, 194, 194, 194, 194, 194, 195, 194, 196, 194, 196, 197, 198, 198, 199, + 198, 198, 198, 198, 198, 198, 198, 200, 198, 201, 178, 178, 178, 178, 202, 26, + 203, 203, 203, 204, 203, 205, 203, 205, 206, 203, 207, 207, 207, 208, 209, 26, + 210, 210, 210, 210, 210, 211, 210, 210, 210, 212, 210, 213, 214, 214, 214, 215, + 216, 216, 216, 216, 216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219, + 216, 220, 9, 9, 9, 221, 26, 26, 222, 222, 222, 222, 222, 223, 222, 222, + 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227, 228, 228, 228, 228, + 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231, 18, 232, 165, 165, + 165, 165, 165, 233, 224, 26, 234, 9, 235, 236, 237, 238, 239, 240, 2, 2, + 2, 2, 2, 241, 242, 243, 2, 244, 2, 2, 2, 245, 14, 14, 246, 246, + 246, 246, 14, 247, 14, 14, 14, 246, 14, 14, 248, 14, 248, 14, 249, 250, + 14, 14, 251, 252, 0, 253, 0, 0, 254, 0, 255, 256, 0, 257, 2, 258, + 259, 26, 9, 9, 9, 9, 260, 26, 261, 262, 4, 0, 0, 263, 0, 0, + 2, 264, 0, 0, 0, 265, 26, 26, 0, 266, 26, 26, 267, 267, 267, 267, + 0, 0, 268, 0, 0, 0, 269, 0, 270, 270, 270, 270, 17, 17, 17, 17, + 17, 17, 271, 272, 166, 167, 273, 273, 273, 273, 273, 273, 273, 274, 275, 274, + 170, 170, 172, 26, 172, 172, 172, 172, 0, 0, 0, 276, 277, 277, 277, 278, + 277, 277, 277, 277, 277, 277, 279, 26, 277, 277, 280, 26, 26, 26, 0, 0, + 281, 0, 0, 0, 282, 283, 0, 284, 285, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291, + 292, 293, 293, 293, 293, 293, 294, 169, 169, 295, 0, 0, 293, 293, 293, 293, + 276, 296, 290, 290, 169, 169, 169, 295, 169, 169, 169, 297, 0, 0, 290, 290, + 290, 290, 290, 298, 290, 290, 290, 0, 299, 299, 299, 299, 299, 300, 299, 299, + 301, 26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 304, 26, 26, + 305, 305, 305, 305, 305, 305, 305, 26, 306, 2, 2, 2, 2, 307, 2, 2, + 2, 308, 309, 258, 26, 26, 310, 2, 311, 311, 311, 311, 311, 312, 0, 265, + 313, 313, 313, 313, 313, 313, 313, 26, 314, 314, 314, 314, 315, 316, 314, 317, + 318, 318, 318, 318, 318, 319, 320, 320, 320, 320, 321, 322, 169, 169, 169, 323, + 324, 324, 324, 324, 324, 325, 324, 326, 164, 164, 164, 327, 328, 328, 328, 328, + 328, 328, 329, 26, 328, 330, 328, 331, 332, 332, 332, 332, 333, 26, 26, 334, + 335, 335, 336, 26, 337, 337, 337, 26, 172, 172, 2, 2, 2, 2, 2, 338, + 339, 340, 176, 176, 335, 335, 335, 335, 335, 341, 335, 342, 343, 26, 169, 169, + 295, 344, 169, 169, 169, 169, 169, 343, 277, 280, 277, 277, 277, 277, 277, 345, + 346, 26, 347, 348, 25, 25, 349, 350, 351, 25, 31, 31, 352, 26, 353, 31, + 31, 31, 31, 354, 31, 31, 355, 31, 31, 356, 26, 26, 26, 26, 31, 31, + 9, 9, 0, 265, 9, 357, 0, 0, 0, 0, 358, 0, 257, 359, 360, 31, + 31, 31, 31, 361, 362, 0, 0, 0, 363, 290, 289, 290, 290, 290, 290, 364, + 365, 365, 365, 366, 257, 257, 26, 367, 368, 369, 368, 368, 370, 368, 368, 371, + 368, 372, 368, 372, 368, 368, 368, 368, 368, 368, 368, 373, 374, 0, 0, 0, + 0, 0, 375, 0, 14, 252, 0, 376, 377, 26, 26, 26, 0, 0, 0, 378, + 379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382, 26, 383, 0, 0, 359, + 384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390, + 391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395, 26, 396, 396, 396, 396, + 396, 396, 397, 397, 397, 397, 397, 397, 398, 398, 398, 399, 398, 400, 401, 401, + 401, 401, 402, 401, 401, 401, 401, 402, 403, 403, 403, 403, 403, 26, 404, 404, + 404, 404, 404, 404, 405, 406, 407, 408, 407, 408, 409, 407, 410, 407, 410, 411, + 412, 412, 412, 412, 412, 412, 413, 26, 414, 414, 414, 414, 414, 414, 415, 26, + 414, 414, 416, 26, 414, 26, 26, 26, 417, 2, 2, 2, 2, 2, 418, 419, + 420, 421, 422, 422, 422, 422, 423, 424, 425, 425, 426, 425, 427, 427, 427, 427, + 428, 428, 428, 429, 430, 428, 26, 26, 431, 431, 432, 433, 434, 434, 434, 435, + 436, 436, 436, 437, 438, 438, 438, 438, 439, 439, 439, 440, 439, 439, 441, 439, + 439, 439, 439, 439, 442, 443, 444, 445, 446, 446, 447, 448, 446, 449, 446, 449, + 450, 450, 450, 450, 451, 451, 451, 451, 452, 452, 452, 452, 453, 454, 453, 26, + 455, 455, 455, 455, 455, 455, 456, 457, 458, 458, 459, 458, 460, 460, 461, 460, + 462, 462, 463, 464, 26, 465, 26, 26, 466, 466, 466, 466, 466, 467, 26, 26, + 468, 468, 468, 468, 468, 468, 469, 26, 468, 468, 469, 470, 471, 471, 471, 471, + 471, 26, 471, 472, 473, 473, 473, 473, 474, 475, 473, 473, 474, 476, 26, 26, + 31, 31, 31, 50, 477, 477, 477, 477, 477, 478, 479, 26, 480, 26, 26, 26, + 26, 26, 26, 481, 482, 482, 482, 482, 482, 26, 483, 483, 483, 483, 483, 484, + 26, 26, 485, 485, 485, 486, 26, 26, 26, 26, 487, 487, 487, 488, 26, 26, + 489, 489, 490, 26, 491, 491, 491, 491, 491, 492, 493, 491, 491, 491, 492, 494, + 495, 495, 495, 495, 496, 497, 498, 498, 498, 499, 498, 500, 501, 501, 501, 501, + 501, 501, 502, 501, 501, 26, 503, 503, 503, 503, 504, 26, 505, 505, 505, 505, + 506, 137, 507, 26, 508, 508, 509, 508, 508, 508, 508, 508, 510, 26, 26, 26, + 511, 512, 513, 514, 513, 515, 516, 516, 516, 516, 516, 516, 516, 517, 516, 518, + 519, 520, 521, 522, 522, 523, 524, 525, 520, 526, 527, 528, 529, 530, 530, 26, + 531, 532, 531, 531, 531, 531, 533, 531, 534, 535, 533, 536, 537, 26, 26, 26, + 538, 538, 538, 538, 538, 538, 538, 539, 540, 26, 26, 26, 541, 541, 541, 541, + 541, 26, 541, 542, 543, 543, 543, 543, 543, 543, 544, 543, 543, 543, 543, 544, + 545, 545, 545, 545, 546, 26, 545, 547, 198, 548, 26, 26, 549, 549, 549, 549, + 549, 549, 549, 550, 549, 550, 164, 164, 551, 26, 26, 26, 552, 552, 552, 553, + 552, 554, 552, 552, 555, 26, 26, 26, 556, 556, 556, 556, 556, 556, 556, 557, + 558, 558, 558, 558, 558, 558, 559, 560, 561, 562, 563, 564, 564, 564, 565, 566, + 561, 26, 564, 567, 568, 569, 568, 568, 568, 568, 568, 569, 570, 26, 26, 26, + 571, 571, 571, 571, 571, 26, 572, 572, 572, 572, 572, 572, 573, 26, 178, 178, + 574, 574, 574, 574, 574, 574, 574, 575, 53, 576, 26, 26, 577, 577, 577, 577, + 578, 26, 577, 578, 579, 580, 579, 579, 579, 579, 581, 579, 582, 26, 579, 579, + 579, 583, 584, 584, 584, 584, 585, 584, 584, 586, 587, 26, 588, 589, 590, 590, + 590, 590, 588, 591, 590, 26, 590, 592, 593, 594, 595, 595, 595, 596, 597, 598, + 595, 599, 26, 26, 600, 600, 600, 601, 602, 602, 603, 602, 602, 602, 602, 604, + 602, 602, 602, 605, 26, 26, 606, 26, 108, 108, 108, 108, 108, 108, 607, 608, + 609, 609, 609, 609, 609, 609, 609, 610, 609, 611, 612, 26, 613, 26, 26, 26, + 26, 26, 614, 614, 614, 614, 614, 614, 614, 614, 615, 26, 616, 616, 616, 616, + 616, 616, 617, 26, 616, 616, 616, 618, 619, 619, 619, 619, 620, 26, 26, 26, + 621, 621, 621, 621, 621, 621, 621, 622, 305, 305, 305, 623, 624, 624, 624, 625, + 624, 626, 627, 627, 627, 627, 627, 627, 627, 627, 627, 628, 627, 629, 630, 630, + 630, 631, 631, 26, 632, 632, 632, 632, 633, 26, 632, 634, 634, 632, 632, 635, + 632, 632, 26, 26, 636, 636, 636, 636, 636, 636, 636, 637, 638, 638, 638, 638, + 638, 638, 638, 639, 640, 640, 640, 640, 640, 641, 640, 640, 640, 642, 640, 640, + 643, 26, 345, 26, 644, 644, 644, 644, 644, 644, 644, 26, 645, 645, 645, 645, + 645, 645, 646, 26, 26, 26, 26, 647, 644, 648, 26, 26, 26, 26, 649, 650, + 651, 286, 286, 286, 652, 26, 653, 26, 26, 26, 654, 26, 655, 26, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 657, 658, 658, 658, 658, 658, 659, 658, 660, + 658, 661, 658, 662, 359, 26, 26, 26, 0, 0, 0, 265, 0, 0, 359, 26, + 9, 663, 9, 9, 221, 26, 0, 0, 0, 0, 276, 26, 257, 362, 0, 0, + 664, 665, 0, 666, 667, 668, 0, 0, 0, 669, 0, 0, 246, 26, 26, 26, + 0, 0, 257, 26, 0, 0, 0, 259, 0, 0, 254, 0, 0, 0, 0, 254, + 670, 671, 0, 672, 673, 0, 0, 0, 269, 674, 254, 254, 0, 0, 0, 675, + 676, 677, 678, 0, 276, 0, 0, 0, 0, 268, 0, 0, 679, 679, 679, 679, + 679, 680, 26, 681, 682, 679, 26, 26, 2, 2, 2, 346, 683, 419, 26, 26, + 684, 270, 270, 685, 686, 687, 18, 18, 18, 688, 26, 26, 26, 689, 26, 26, + 690, 690, 690, 690, 690, 691, 690, 692, 690, 693, 26, 26, 26, 26, 694, 694, + 694, 695, 26, 26, 696, 696, 696, 696, 696, 696, 696, 697, 26, 26, 698, 698, + 698, 698, 698, 699, 26, 26, 700, 700, 700, 700, 700, 701, 172, 702, 170, 172, + 703, 703, 703, 703, 704, 703, 705, 26, 706, 706, 706, 706, 706, 707, 706, 708, + 26, 26, 362, 0, 0, 0, 376, 26, 709, 31, 31, 31, 710, 711, 712, 713, + 714, 715, 710, 716, 710, 712, 712, 717, 31, 718, 31, 719, 720, 718, 31, 719, + 26, 26, 721, 26, 0, 359, 0, 0, 0, 257, 362, 0, 362, 0, 362, 0, + 0, 276, 26, 26, 722, 0, 0, 0, 723, 26, 0, 0, 0, 0, 0, 359, + 0, 259, 265, 26, 276, 26, 26, 26, 0, 0, 0, 724, 0, 376, 0, 376, + 0, 0, 257, 725, 0, 359, 259, 26, 0, 26, 0, 265, 0, 26, 0, 0, + 0, 276, 0, 359, 265, 26, 26, 26, 0, 276, 0, 376, 0, 726, 0, 0, + 257, 722, 0, 727, 0, 265, 0, 259, 277, 277, 277, 280, 345, 26, 277, 277, + 728, 26, 277, 277, 277, 729, 277, 277, 277, 277, 26, 26, 730, 26, 26, 26, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976, + 1001,1002,1003,1008, 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082, + 1086,1110, 0, 0,1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161, + 1187,1188,1189,1193, 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269, + 1273,1298, 0,1303, 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, + 961,1146, 964,1149, 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, + 988,1173, 990,1175, 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191, + 1006,1192,1014,1199,1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025, + 1211,1023,1209, 0, 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0, + 1044,1230,1045,1231,1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252, + 1067,1253,1072,1258,1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271, + 1085,1272,1088,1275,1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120, + 1309,1121,1310, 0,1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1093,1280, 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, 949,1134,1010,1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339, + 1366, 0,1320,1347,1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241, + 1416,1417,1415,1424,1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348, + 1322,1349,1338,1365, 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197, + 1051,1237,1052,1238,1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, + 0, 0, 997,1182, 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364, + 1335,1362,1046,1232,1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0, + 1450, 0,1455,1461,1514, 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,1446,1458, + 1468,1476,1480,1486,1517, 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,1489,1503, + 1494,1500,1508, 0, 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0, + 1536,1532,1539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, + 0, 0, 0, 0,1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0, + 1558,1554,1561, 0, 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571, + 1530,1552,1531,1553, 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573, + 1544,1566,1538,1560,1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, + 0, 0, 0, 0, 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, + 0, 0, 0, 0, 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617, + 1618,1619,1621,1622, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628, + 1629, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1625,1626, 0,1627, 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, + 0, 0,1633, 0, 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638, + 1640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1636,1637, 0, 0, 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644, + 1643, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, + 0, 0, 0, 0,1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653, + 1652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0, + 1655,1657,1656, 0, 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1660, 0, 0, 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0, + 1663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, + 0, 0, 0, 0, 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, + 0, 0, 0, 0, 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1669, 0, 0, 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0, + 1672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0, + 1679, 0,1680, 0, 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, + 0,1683, 0, 0,1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, + 965,1150, 968,1153, 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170, + 1420,1421, 986,1171, 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185, + 1015,1200,1329,1356,1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213, + 1026,1212,1028,1214,1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224, + 1334,1361,1336,1363,1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249, + 1689,1690,1065,1251,1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259, + 1075,1262,1079,1266,1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393, + 1099,1286,1100,1287,1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295, + 1108,1296,1114,1302,1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, + 0, 0, 0, 0, 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345, + 1693,1695,1371,1375,1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, + 972,1157,1326,1353,1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198, + 1054,1240,1048,1234,1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401, + 1395,1400,1398,1403,1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410, + 1408,1413,1407,1412,1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, + 0, 0, 0, 0,1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719, + 1716,1720,1717,1721,1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735, + 1734,1736, 0, 0,1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755, + 1752,1756,1753,1757,1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774, + 1772,1775,1773,1776,1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783, + 1782,1784, 0, 0,1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, + 0,1792, 0,1793,1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812, + 1809,1813,1810,1814,1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28, + 1507, 29, 0, 0,1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724, + 1725,1726,1727,1728,1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760, + 1761,1762,1763,1764,1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817, + 1818,1819,1820,1821,1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12, + 1432, 0, 26, 0, 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14, + 1441,1826,1827,1828,1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, + 0,1831,1832,1833,1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17, + 1453,1313, 11, 3, 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18, + 1464, 4, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 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, 949,1134,1010,1195,1050,1236,1090, - 1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347,1418,1419,1323,1350, - 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,1202, 0, 0, 0, - 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365, 950,1135, 951,1136, - 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,1061,1247,1062,1248, - 1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182, 0, 0, 0, 0, - 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,1422,1423,1113,1301, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 10, - 1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461,1514, 0, 0, 0, + 0, 0,1836, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1837,1839,1838, 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0, + 1842, 0, 0, 0, 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, + 0, 0, 0, 0, 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1849, 936, 938,1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, + 0, 0, 0, 0,1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486,1517, 0, 0, 0, + 1867,1868,1869,1870,1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872, + 1873,1874, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0, 0, 0, 0,1520, - 1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1526,1528, 0,1525, - 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0,1548,1550, 0,1547, - 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0, 0, 0, 0, 0, - 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0, 0,1529,1551, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1523,1545,1524,1546, - 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553, 0, 0,1533,1555, - 1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560,1540,1562,1541,1563, - 1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0, 0, 0,1606,1607, - 1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0,1613, 0,1611, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1612, + 1875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1877, 0,1878, 0,1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0, + 1885, 0,1886, 0,1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, + 0, 0, 0, 0,1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0, + 1900,1901, 0, 0, 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1902, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1904, 0,1905, 0,1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0, + 1912, 0,1913, 0,1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, + 0, 0, 0, 0,1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0, + 1927,1928, 0, 0, 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, + 0, 0,1933, 0, 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, + 241, 336, 524, 601, 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, + 180, 416, 482, 662, 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, + 740, 116, 146, 168, 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, + 553, 588, 642, 758, 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, + 412, 445, 457, 585, 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, + 411, 704, 105, 259, 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, + 228, 529, 650, 697, 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, + 624, 700, 750, 170, 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, + 420, 730, 287, 330, 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, + 154, 163, 198, 473, 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, + 314, 499, 506, 603, 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, + 260, 265, 373, 411, 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, + 502, 516, 537, 583, 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, + 771, 155, 190, 269, 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, + 452, 191, 480, 510, 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, + 707, 111, 636, 156, 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, + 128, 210, 0, 0, 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, + 783, 576, 604, 0, 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, + 795, 808, 741, 773, 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, + 270, 317, 327, 329, 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, + 545, 547, 546, 548, 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, + 620, 625, 625, 651, 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, + 869, 623, 0, 0, 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, + 227, 231, 240, 243, 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, + 341, 357, 360, 362, 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, + 477, 535, 485, 490, 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, + 565, 569, 574, 586, 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, + 705, 704, 702, 706, 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, + 790, 802, 825, 848, 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0, 0,1623, 0, 0, - 1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627, 0, 0, 0,1634, - 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0, 0, 0, 0, 0, - 1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0,1646, 0, 0, 0, - 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0, 0, 0, 0,1659, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0, 0, 0,1661, 0, - 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0, 0, 0, 0,1664, - 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0, 0,1666, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1668, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0, 0, 0,1670, 0, - 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0, 0, 0,1681, 0, + 0,1586, 0,1605, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603, + 1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589, + 1591, 0,1592, 0,1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582, + 1578,1590,1597, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1937, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, + 1939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1940, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0,1684,1685, 0,1686, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 953,1138, 955,1140, - 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, 966,1151, 967,1152, - 1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, 989,1174, 995,1180, - 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,1017,1203,1019,1205, - 1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,1029,1215,1030,1216, - 1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,1382,1384,1383,1385, - 1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,1068,1254,1070,1256, - 1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,1078,1265,1095,1282, - 1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,1101,1288,1102,1289, - 1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,1119,1308,1122,1311, - 1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0, 952,1137, 947,1132, - 1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,1370,1374,1373,1377, - 1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,1325,1352,1328,1355, - 1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,1331,1358,1330,1357, - 1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,1397,1402,1399,1404, - 1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,1409,1414,1109,1297, - 1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0,1471,1472,1701,1705, - 1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,1477,1478,1729,1731, - 1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0,1481,1482,1737,1741, - 1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,1490,1491,1765,1768, - 1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,1495,1496,1777,1779, - 1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0,1504,1505,1785,1788, - 1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793,1509,1510,1794,1798, - 1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,1467, 21,1475, 22, - 1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0,1704,1708,1709,1710, - 1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,1740,1744,1745,1746, - 1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,1797,1801,1802,1803, - 1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,1470,1469,1822,1474, - 1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0, 0,1315,1823,1484, - 1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828,1488,1487,1513, 19, - 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833,1502,1501,1516, 25, - 1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3, 0, 0,1824,1512, - 1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0, 30, 31, 0, 0, + 0, 0,1941,1942, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1943, + 1944, 0, 0, 0, 0, 0, 0,1945, 0,1946, 0, 0, 0, 0, 0, 0, + 0, 0,1947, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1950, 0,1949,1951, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1953, + 1952, 0,1954, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1955,1956, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1957, 0, 0, 0, + 0, 0, 0, 0, 0,1958,1961,1959,1965,1960,1962,1964,1963, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1967,1966,1968, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838, 0, 0, 0, 0, - 1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0, 0, 0, 0, 0, - 1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1845, 0, 0, - 1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0, 937, 0,1850, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938,1851,1852, 0, 0, - 1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0,1857,1858, 0, 0, - 1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870,1859,1860,1865,1866, - 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0,1879, 0,1880, 0, - 1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0,1887, 0,1888, 0, - 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0,1892,1893, 0,1894, - 1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0, 0, 0, 0, 0, - 1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0,1906, 0,1907, 0, - 1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0,1914, 0,1915, 0, - 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0,1919,1920, 0,1921, - 1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0, 0, 0, 0, 0, - 1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0, 710, 385, 724, 715, - 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, 663, 676, 688, 738, - 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, 810, 275, 462, 658, - 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, 368, 414, 481, 527, - 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, 811, 701, 233, 299, - 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, 594, 766, 167, 613, - 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, 313, 496, 518, 174, - 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, 424, 732, 428, 349, - 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, 193, 245, 297, 374, - 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, 337, 366, 459, 476, - 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, 683, 697, 292, 311, - 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, 608, 752, 778, 782, - 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, 479, 523, 655, 737, - 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, 791, 136, 340, 769, - 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, 377, 391, 406, 432, - 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, 659, 772, 805, 813, - 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, 153, 288, 346, 578, - 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0, 227, 0, 379, 0, - 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0, 661, 0, 703, 0, - 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773, 118, 127, 130, 166, - 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, 335, 369, 375, 381, - 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, 549, 550, 554, 555, - 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, 690, 695, 705, 706, - 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0, 102, 145, 134, 115, - 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, 250, 254, 294, 296, - 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, 370, 379, 388, 389, - 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, 493, 507, 512, 514, - 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, 591, 597, 607, 637, - 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, 709, 717, 728, 736, - 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, 847, 857, 55, 65, - 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580, - 1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0,1593,1594, 0,1595, - 1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950,1951,1952,1953,1954, - 1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959,1961, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 104, 107, 826, - 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, 132, 137, 827, 35, - 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, 157, 158, 159, 160, - 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, 181, 182, 182, 182, - 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, 197, 199, 200, 201, - 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, 153, 234, 221, 222, - 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, 836, 837, 247, 248, - 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259, 261, 839, 262, 263, - 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276, 278, 281, 282, 42, - 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934, 298, 845, 845, 621, - 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312, 316, 48, 47, 317, - 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, 335, 336, 338, 339, - 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, 358, 356, 49, 363, - 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381, 52, 51, 140, 141, - 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399, 396, 402, 404, 858, - 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417, 860, 418, 57, 419, - 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, 437, 441, 438, 439, - 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460, 866, 867, 461, 466, - 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870, 483, 485, 486, 871, - 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505, 507, 508, 511, 62, - 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64, 528, 880, 879, 881, - 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538, 541, 69, 885, 549, - 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567, 71, 890, 570, 571, - 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592, 596, 75, 895, 896, - 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, 853, 77, 615, 616, - 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627, 626, 628, 164, 629, - 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, 638, 643, 644, 645, - 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83, 909, 910, 84, 664, - 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85, 677, 678, 86, 681, - 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696, 702, 709, 711, 915, - 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, 918, 919, 739, 742, - 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90, 764, 922, 91, 775, - 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787, 789, 928, 792, 95, - 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807, 930, 99, 931, 932, - 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0, + 0, 0,1969,1970,1971,1972,1973,1974,1975, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1976, + 1977,1978,1980,1979,1981, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, + 34, 830, 130, 131, 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, + 924, 151, 152, 37, 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, + 176, 177, 178, 179, 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, + 196, 192, 194, 195, 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, + 213, 219, 214, 216, 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, + 237, 238, 239, 244, 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, + 838, 257, 258, 259, 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, + 274, 842, 277, 276, 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, + 290, 291, 293, 934, 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, + 306, 309, 310, 312, 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, + 333, 331, 332, 334, 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, + 354, 359, 850, 361, 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, + 386, 378, 53, 381, 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, + 392, 856, 54, 399, 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, + 859, 415, 56, 417, 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, + 429, 431, 427, 433, 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, + 453, 865, 447, 460, 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, + 475, 868, 478, 870, 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, + 61, 61, 504, 505, 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, + 877, 878, 63, 64, 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, + 68, 884, 536, 538, 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, + 888, 889, 889, 567, 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, + 587, 74, 590, 592, 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, + 900, 609, 901, 611, 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, + 622, 731, 80, 627, 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, + 635, 641, 646, 651, 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, + 657, 908, 82, 83, 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, + 672, 673, 675, 85, 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, + 914, 88, 89, 696, 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, + 723, 832, 725, 728, 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, + 761, 921, 762, 90, 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, + 94, 927, 787, 787, 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, + 806, 97, 98, 807, 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, + 821, 935, 0, 0, }; static const int16_t _hb_ucd_i16[92] = @@ -4403,12 +4615,12 @@ _hb_ucd_i16[92] = static inline uint_fast8_t _hb_ucd_gc (unsigned u) { - return u<1114110u?_hb_ucd_u8[6808+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; + return u<1114110u?_hb_ucd_u8[6472+(((_hb_ucd_u8[816+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>4>>4])<<4)+((u>>1>>3>>4)&15u))])<<4)+((u>>1>>3)&15u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; } static inline uint_fast8_t _hb_ucd_ccc (unsigned u) { - return u<125259u?_hb_ucd_u8[8800+(((_hb_ucd_u8[8244+(((_hb_ucd_u8[7784+(((_hb_ucd_u8[7432+(((_hb_ucd_u8[7186+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; + return u<125259u?_hb_ucd_u8[8504+(((_hb_ucd_u8[7936+(((_hb_ucd_u8[7460+(((_hb_ucd_u8[7100+(((_hb_ucd_u8[6854+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; } static inline unsigned _hb_ucd_b4 (const uint8_t* a, unsigned i) @@ -4418,55 +4630,55 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i) static inline int_fast16_t _hb_ucd_bmg (unsigned u) { - return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9692+(((_hb_ucd_u8[9460+(((_hb_ucd_u8[9364+(((_hb_ucd_b4(9300+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0; + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9396+(((_hb_ucd_u8[9164+(((_hb_ucd_u8[9068+(((_hb_ucd_b4(9004+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0; } static inline uint_fast8_t _hb_ucd_sc (unsigned u) { - return u<918000u?_hb_ucd_u8[11126+(((_hb_ucd_u16[4040+(((_hb_ucd_u16[2048+(((_hb_ucd_u8[10390+(((_hb_ucd_u8[9940+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; + return u<918000u?_hb_ucd_u8[10398+(((_hb_ucd_u16[3952+(((_hb_ucd_u16[2624+(((_hb_ucd_u8[9870+(((_hb_ucd_u8[9644+(u>>3>>2>>3>>4)])<<4)+((u>>3>>2>>3)&15u))])<<3)+((u>>3>>2)&7u))])<<2)+((u>>3)&3u))])<<3)+((u)&7u))]:2; } static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[6748+(((_hb_ucd_u8[13952+(((_hb_ucd_u8[13570+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[6244+(((_hb_ucd_u8[16628+(((_hb_ucd_u8[16246+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; } #else static const uint8_t -_hb_ucd_u8[13386] = +_hb_ucd_u8[13730] = { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 7, 11, 12, 12, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 21, 21, 21, 21, 23, 7, 7, - 7, 24, 21, 21, 21, 25, 26, 27, 21, 28, 29, 30, 31, 32, 33, 34, + 14, 15, 16, 17, 18, 19, 20, 7, 21, 22, 22, 22, 23, 24, 7, 7, + 7, 25, 22, 22, 22, 26, 27, 28, 22, 29, 30, 31, 32, 33, 34, 35, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 35, 21, 36, - 7, 7, 7, 7, 37, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 38, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 22, 36, + 7, 7, 7, 7, 37, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 38, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, @@ -4486,30 +4698,30 @@ _hb_ucd_u8[13386] = 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, 100,100, 34, 34, 34, 34,101,102, 34, 34,103,104,105,106,107,108, 34, 34,109,110,111,112,113,114,115,116,117,118, 34, 34, 34,119, - 120,121,122,123,124,125,126,127, 34,128,129,111,130,131,132,133, - 134,135,136,137,138,139,140,111,141,142,111,143,144,145,146,111, - 147,148,149,150,151,152,153,111,154,155,156,157,111,158,159,160, - 34, 34, 34, 34, 34, 34, 34, 34,161, 34, 34,111,111,111,111,111, - 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,162, - 34, 34, 34, 34, 34, 34, 34, 34,163,111,111,111,111,111,111,111, + 120,121,122,123,124,125,126,127, 34,128,129,130,131,132,133,134, + 135,136,137,138,139,140,141,142,143,144,111,145,146,147,148,111, + 149,150,151,152,153,154,155,156,157,158,159,160,111,161,162,163, + 34, 34, 34, 34, 34, 34, 34, 34,164, 34, 34,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,165, + 34, 34, 34, 34, 34, 34, 34, 34,166, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111, 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, - 111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34,111,111,111, - 34, 34, 34, 34,164,165,166, 34,111,111,111,111,167,168,169,170, + 111,111,167,111,111,111,111,111,111,111,111,111,111,111,111,111, + 34, 34, 34, 34,168,169,170, 34,111,111,171,111,172,173,174,175, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111, 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,119, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111, - 111,111,111,111,111,111,111,111, 34,171,111,111,111,111,111,111, - 111,111,111,111,111,111,111,111,111,111,111,111,111,111,172, 67, - 67, 67,173,174,175,130, 65,111,176,177,178,179,180,181,182,183, - 67, 67, 67, 67,184,185,111,111,111,111,111,111,111,111,186,111, - 187,188,189,111,111,190,111,111,111,191,111,111,111,111,111, 34, - 34,192,193,111,111,111,111,111,130,194,195,111, 34,196,111,111, - 67, 67,197, 67, 67,111, 67,198, 67, 67, 67, 67, 67, 67, 67, 67, - 67, 67, 67, 67, 67, 67, 67,199,111,111,111,111,111,111,111,111, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111, + 111,111,111,111,111,111,111,111, 34,176,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111, 67,177, 67, 67, 67, 67,178, 67, + 67, 67,179,180,181,131, 65,111,182,183,184,185,186,187,188,189, + 67, 67, 67, 67,190,191,111,111,111,111,111,111,111,111,192,111, + 193,194,195,111,111,196,111,111,111,197,111,198,111,111,111, 34, + 34,199,200,111,111,111,111,111,131,201,202,111, 34,203,111,111, + 67, 67,204, 67, 67,111, 67,205, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67,177,111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111, - 200,111,188,188,111,111,111,111,111,111,111,111,111,111,111,111, + 206,111,194,194,111,111,111,111,111,111,111,111,111,111,111,111, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2, 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, @@ -4544,8 +4756,8 @@ _hb_ucd_u8[13386] = 36, 36, 36, 36, 36, 64, 43, 43, 43, 43, 40, 21, 2, 40, 69, 20, 36, 36, 36, 43, 43, 69, 43, 43, 43, 43, 69, 43, 69, 43, 43, 43, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36, 64, 43, 43, 2, - 36, 36, 36, 36, 74, 36, 36, 36, 59, 59, 59, 59, 43, 43, 43, 43, - 36, 36, 36, 36, 75, 43, 43, 43, 43, 76, 43, 43, 43, 43, 43, 43, + 36, 36, 36, 36, 74, 36, 36, 36, 59, 59, 59, 75, 43, 43, 43, 43, + 36, 36, 36, 36, 76, 43, 43, 43, 43, 75, 43, 43, 43, 43, 43, 43, 43, 77, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 65, 78, 79, 43, 43, 43, 77, 78, 79, 78, 64, 43, 43, 43, 36, 36, 36, 36, 36, 43, 2, 7, 7, 7, 7, 7, 80, 36, 36, 36, 36, 36, 36, 36, @@ -4590,130 +4802,135 @@ _hb_ucd_u8[13386] = 36, 43, 77, 78, 78, 78, 78, 81, 36, 43, 97, 2, 2, 2, 2, 2, 36, 43, 43, 43, 43, 43, 43, 43, 36, 36, 43, 79, 43, 43, 43, 78, 78, 78, 78, 77, 79, 43, 43, 43, 43, 43, 2, 80, 2, 60, 64, 43, - 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 98, 2, 56, 43, 76, - 36, 75, 36, 36, 36, 36, 36, 36, 36, 36, 64, 65, 36, 36, 36, 36, + 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 98, 2, 56, 43, 75, + 36, 76, 36, 36, 36, 36, 36, 36, 36, 36, 64, 65, 36, 36, 36, 36, 36, 36, 36, 36, 64, 36, 36, 36, 43, 77, 78, 79, 77, 78, 78, 78, 78, 77, 78, 78, 79, 43, 43, 43, 61, 61, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 27, 27, 61, 36, 36, 36, 64, 77, 79, 43, 2, 36, 36, 82, 77, 43, 43, 43, 43, 77, 77, 79, 43, 43, 43, 77, 78, 78, 79, 43, 43, 43, 43, 43, 43, 2, 2, 2, 80, 2, 2, 2, 2, 43, 43, 43, 43, 43, 43, 43, 99, 43, 43, 81, 36, 36, 36, 36, 36, - 36, 36, 77, 43, 43, 77, 77, 78, 78, 77, 81, 36, 36, 36, 36, 36, + 36, 36, 77, 43, 43, 77, 77, 78, 78, 77, 81, 36, 36, 36, 36, 2, 89, 61, 61, 61, 61, 47, 43, 43, 43, 43, 61, 61, 61, 61, 21, 2, 43, 81, 36, 36, 36, 36, 36, 36, 82, 43, 43, 78, 43, 79, 43, 36, 36, 36, 36, 77, 43, 78, 79, 79, 43, 78, 78, 78, 78, 78, 2, 2, 36, 36, 78, 78, 78, 78, 43, 43, 43, 43, 78, 43, 43, 57, 2, 2, 7, 7, 7, 7, 7, 7, 86, 36, 36, 36, 36, 36, 40, 40, 40, 2, - 43, 57, 43, 43, 43, 43, 43, 43, 77, 43, 43, 43, 65, 36, 64, 36, - 36, 36, 65, 82, 43, 36, 36, 36, 16, 16, 16, 16, 16, 16, 40, 40, - 40, 40, 40, 40, 40, 44, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, - 16, 16, 16, 16, 16,100, 40, 40, 32, 32, 32, 16, 16, 16, 16, 32, - 16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 16, 34, 11, 11, 11, - 16, 16, 16, 16,101,101,101,101, 16, 16, 16, 16, 11, 11,102,103, - 41, 16, 16, 16, 11, 11,102, 41, 16, 16, 16, 16, 11, 11,104, 41, - 105,105,105,105,105,106, 59, 59, 51, 51, 51, 2,107,108,107,108, - 2, 2, 2, 2,109, 59, 59,110, 2, 2, 2, 2,111,112, 2,113, - 114, 2,115,116, 2, 2, 2, 2, 2, 9,114, 2, 2, 2, 2,117, - 59, 59, 59, 59, 59, 59, 59, 59,118, 40, 27, 27, 27, 8,115,119, - 27, 27, 27, 27, 27, 8,115, 94, 20, 20, 20, 20, 20, 20, 20, 20, - 43, 43, 43, 43, 43, 43,120, 48, 99, 48, 99, 43, 43, 43, 43, 43, - 61,121, 61,122, 61, 34, 11, 16, 11, 32,122, 61, 46, 11, 11, 61, - 61, 61,121,121,121, 11, 11,123, 11, 11, 35, 36, 39, 61, 16, 11, - 8, 8, 46, 16, 16, 26, 61,124, 95, 95, 95, 95, 95, 95, 95, 95, - 95,125,126, 95,127, 61, 61, 61, 8, 8,128, 61, 61, 8, 61, 61, - 128, 26, 61,128, 61, 61, 61,128, 61, 61, 61, 61, 61, 61, 61, 8, - 61,128,128, 61, 61, 61, 61, 61, 61, 61, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 61, 61, 61, 61, 4, 4, 61, 61, - 8, 61, 61, 61,129,130, 61, 61, 61, 61, 61, 61, 61, 61,128, 61, - 61, 61, 61, 61, 61, 26, 8, 8, 8, 8, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 8, 8, 8, 61, 61, 61, 61, 61, 61, 61, - 27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, - 61, 61, 61, 26, 61, 61, 61, 61, 26, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 8, 8, 8, 8, 61, 61, 61, 61, 61, 61, 61, 26, - 61, 61, 61, 61, 4, 4, 4, 4, 4, 4, 4, 27, 27, 27, 27, 27, - 27, 27, 61, 61, 61, 61, 61, 61, 8, 8,115,131, 8, 8, 8, 8, - 8, 8, 8, 4, 4, 4, 4, 4, 8,115,132,132,132,132,132,132, - 132,132,132,132,131, 8, 8, 8, 8, 8, 8, 8, 4, 4, 8, 8, - 8, 8, 8, 8, 8, 8, 4, 8, 8, 8,128, 26, 8, 8,128, 61, - 32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11, - 32, 32,124, 61, 61,122, 34,133, 43, 32, 16, 16, 50, 2, 90, 2, - 36, 36, 36, 36, 36, 36, 36, 75, 2, 2, 2, 2, 2, 2, 2, 56, - 2,107,107, 2,111,112,107, 2, 2, 2, 2, 6, 2, 98,107, 2, - 107, 4, 4, 4, 4, 2, 2, 80, 2, 2, 2, 2, 2, 51, 2, 2, - 98,134, 2, 2, 2, 2, 2, 2, 61, 2,135,132,132,132,136, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 1, 2,137,138, 4, 4, 4, 4, - 4, 61, 4, 4, 4, 4,139, 94,140, 95, 95, 95, 95, 43, 43, 78, - 141, 40, 40, 61, 95,142, 58, 61, 72, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 64,143,144, 63, 36, 36, 36, 36, 36, 58, 40, 63, - 61, 27, 27, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 61, 61, 61, - 61, 61, 61, 61, 27, 27, 27, 27,145, 27, 27, 27, 27, 27, 27, 27, - 36, 36, 75, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,146, 2, - 32, 32, 32, 32, 32, 32, 32, 64, 48,147, 43, 43, 43, 43, 43, 80, - 32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36, 95, 95, 95, 95, 95, - 43, 2, 2, 2, 2, 2, 2, 2, 41, 41, 41,144, 40, 40, 40, 40, - 41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, - 44, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,148, 34, 35, - 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32, - 11, 11, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 34, 16, 16, 16, - 32, 16, 16, 32, 32, 16, 16, 16, 16, 40,149, 35, 40, 35, 36, 36, - 36, 65, 36, 65, 36, 64, 36, 36, 36, 82, 79, 77, 61, 61, 43, 43, - 27, 27, 27, 61,150, 61, 61, 61, 36, 36, 2, 2, 2, 2, 2, 2, - 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 78, 78, 78, 78, 78, 78, - 78, 78, 43, 43, 43, 43, 43, 2, 43, 36, 36, 36, 2, 66, 66, 64, - 36, 36, 36, 43, 43, 43, 43, 2, 36, 36, 36, 64, 43, 43, 43, 43, - 43, 78, 78, 78, 78, 78, 78, 97, 36, 64, 78, 43, 43, 78, 43, 78, - 97, 2, 2, 2, 2, 2, 2, 80, 7, 7, 7, 7, 7, 7, 7, 2, - 36, 36, 64, 63, 36, 36, 36, 36, 36, 36, 36, 36, 64, 43, 43, 77, - 79, 77, 79, 43, 43, 43, 43, 43, 36, 64, 36, 36, 36, 36, 77, 78, - 7, 7, 7, 7, 7, 7, 2, 2, 63, 36, 36, 71, 61, 82, 77, 36, - 65, 43, 65, 64, 65, 36, 36, 43, 36, 36, 36, 36, 36, 36, 75, 2, - 36, 36, 36, 36, 36, 82, 43, 78, 2, 75,151, 43, 43, 43, 43, 43, - 16, 16, 16, 16, 16,103, 40, 40, 16, 16, 16, 16,100, 41, 41, 41, - 36, 82, 79, 78, 77, 97, 79, 43,152,152,152,152,152,152,152,152, - 153,153,153,153,153,153,153,153, 16, 16, 16, 16, 16, 16, 35, 65, - 36, 36, 36, 36,154, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41, - 41, 74, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,132, - 36, 36, 36, 36, 36, 36, 36, 71, 36, 36, 36, 36, 36, 36,150, 61, - 2, 2, 2,135,116, 2, 2, 2, 6,155,156,132,132,132,132,132, - 132,132,116,135,116, 2,113,157, 2, 2, 2, 2,139,132,132,116, - 2,158, 8, 8, 60, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36,159, - 2, 2, 3, 2, 4, 5, 6, 2, 16, 16, 16, 16, 16, 17, 18,115, - 116, 4, 2, 36, 36, 36, 36, 36, 63, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 40, 20,160, 53, 20, 26, 8,128, 61, - 61, 61, 61, 61,161, 59, 61, 61, 2, 2, 2, 90, 27, 27, 27, 27, - 27, 27, 27, 84, 61, 61, 61, 61, 95, 95,127, 27, 84, 61, 61, 61, - 61, 61, 61, 61, 61, 27, 61, 61, 61, 61, 61, 61, 61, 61, 47, 43, - 162,162,162,162,162,162,162,162,163, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 87, 36,138, 36, 36, 36, 36, 95, 95, 95, - 36, 36, 36, 36, 36, 36, 36, 58,164, 95, 95, 95, 95, 95, 95, 95, - 11, 11, 11, 32, 16, 16, 16, 16, 36, 36, 36, 58, 27, 27, 27, 27, - 36, 36, 36, 71,145, 27, 27, 27, 36, 36, 36,165, 27, 27, 27, 27, - 36, 36, 36, 36, 36,165, 27, 27, 36, 36, 36, 27, 27, 27, 27, 30, - 36, 36, 36, 36, 36, 36, 27, 36, 64, 43, 43, 43, 43, 43, 43, 43, - 36, 36, 36, 36, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36,165, 30, - 36, 36, 36, 36, 36, 36,165, 27, 36, 36, 36, 36, 72, 36, 36, 36, - 36, 36, 64, 43, 43,163, 27, 27, 36, 36, 36, 36, 58, 2, 2, 2, - 36, 36, 36, 36, 27, 27, 27, 27, 16, 16, 16, 16, 16, 27, 27, 27, - 36, 36, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 36, 64,166, 51, - 27, 27, 27, 87, 36, 36, 36, 36,163, 27, 30, 2, 2, 2, 2, 2, - 36, 43, 43, 2, 2, 2, 2, 2, 36, 36,165, 27, 27, 27, 27, 27, - 79, 81, 36, 36, 36, 36, 36, 36, 43, 43, 43, 57, 2, 2, 2, 2, - 2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 7, 7, 7, - 65, 64, 65, 36, 36, 36, 36, 64, 78, 79, 43, 77, 79, 57, 73, 2, - 2, 43, 43, 43, 43, 43, 67, 59, 36, 36, 36, 64, 43, 43, 79, 43, - 43, 43, 43, 7, 7, 7, 7, 7, 2, 2, 82, 81, 36, 36, 36, 36, - 36, 64, 2, 36, 36, 36, 36, 36, 36, 82, 78, 43, 43, 43, 43, 77, - 81, 36, 58, 2, 56, 43, 57, 79, 7, 7, 7, 7, 7, 58, 58, 2, - 90, 27, 27, 27, 27, 27, 27, 27, 36, 36, 36, 36, 36, 36, 78, 79, - 43, 78, 77, 43, 2, 2, 2, 65, 36, 36, 36, 36, 36, 36, 36, 64, - 77, 78, 78, 78, 78, 78, 78, 78, 36, 36, 36, 82, 78, 78, 81, 36, - 36, 78, 78, 43, 43, 43, 43, 43, 36, 36, 82, 78, 43, 43, 43, 43, - 78, 43, 77, 65, 36, 58, 2, 2, 7, 7, 7, 7, 7, 2, 2, 65, - 78, 79, 43, 43, 77, 77, 78, 79, 77, 43, 36, 66, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 82, 78, 43, 43, 43, 78, 78, 43, 79, - 57, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 43, - 78, 79, 43, 43, 43, 77, 79, 79, 57, 2, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 64, 79, 78, 43, 43, 43, 79, 58, 2, 2, 2, + 16, 16, 16, 16, 34, 16, 16, 16, 43, 57, 43, 43, 43, 43, 43, 43, + 77, 43, 43, 43, 65, 36, 64, 36, 36, 36, 65, 82, 43, 36, 36, 36, + 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 44, 16, 16, + 16, 16, 16, 16, 44, 16, 16, 16, 16, 16, 16, 16, 16,100, 40, 40, + 32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11, + 16, 16, 16, 16, 34, 11, 11, 11, 16, 16, 16, 16,101,101,101,101, + 16, 16, 16, 16, 11, 11,102,103, 41, 16, 16, 16, 11, 11,102, 41, + 16, 16, 16, 16, 11, 11,104, 41,105,105,105,105,105,106, 59, 59, + 51, 51, 51, 2,107,108,107,108, 2, 2, 2, 2,109, 59, 59,110, + 2, 2, 2, 2,111,112, 2,113,114, 2,115,116, 2, 2, 2, 2, + 2, 9,114, 2, 2, 2, 2,117, 59, 59, 59, 59, 59, 59, 59, 59, + 118, 40, 27, 27, 27, 8,115,119, 27, 27, 27, 27, 27, 8,115, 94, + 20, 20, 20, 20, 20, 20, 20, 20, 43, 43, 43, 43, 43, 43,120, 48, + 99, 48, 99, 43, 43, 43, 43, 43, 61,121, 61,122, 61, 34, 11, 16, + 11, 32,122, 61, 46, 11, 11, 61, 61, 61,121,121,121, 11, 11,123, + 11, 11, 35, 36, 39, 61, 16, 11, 8, 8, 46, 16, 16, 26, 61,124, + 95, 95, 95, 95, 95, 95, 95, 95, 95,125,126, 95,127, 61, 61, 61, + 8, 8,128, 61, 61, 8, 61, 61,128, 26, 61,128, 61, 61, 61,128, + 61, 61, 61, 61, 61, 61, 61, 8, 61,128,128, 61, 61, 61, 61, 61, + 61, 61, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 61, 61, 61, 61, 4, 4, 61, 61, 8, 61, 61, 61,129,130, 61, 61, + 61, 61, 61, 61, 61, 61,128, 61, 61, 61, 61, 61, 61, 26, 8, 8, + 8, 8, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 8, 8, + 8, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 27, 61, 61, + 61, 61, 61, 61, 61, 27, 27, 27, 61, 61, 61, 26, 61, 61, 61, 61, + 26, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 8, 8, 8, 8, + 61, 61, 61, 61, 61, 61, 61, 26, 61, 61, 61, 61, 4, 4, 4, 4, + 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, + 8, 8,115,131, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, + 8,115,132,132,132,132,132,132,132,132,132,132,131, 8, 8, 8, + 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, + 8, 8,128, 26, 8, 8,128, 61, 32, 11, 32, 34, 34, 34, 34, 11, + 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,124, 61, 61,122, 34,133, + 43, 32, 16, 16, 50, 2, 90, 2, 36, 36, 36, 36, 36, 36, 36, 76, + 2, 2, 2, 2, 2, 2, 2, 56, 2,107,107, 2,111,112,107, 2, + 2, 2, 2, 6, 2, 98,107, 2,107, 4, 4, 4, 4, 2, 2, 80, + 2, 2, 2, 2, 2, 51, 2, 2, 98,134, 2, 2, 2, 2, 2, 2, + 61, 2,135,132,132,132,136, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 1, 2,137,138, 4, 4, 4, 4, 4, 61, 4, 4, 4, 4,139, 94, + 140, 95, 95, 95, 95, 43, 43, 78,141, 40, 40, 61, 95,142, 58, 61, + 72, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64,143,144, 63, + 36, 36, 36, 36, 36, 58, 40, 63, 61, 27, 27, 61, 61, 61, 61, 61, + 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, 27, + 145, 27, 27, 27, 27, 27, 27, 27, 36, 36, 76, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36,146, 2, 32, 32, 32, 32, 32, 32, 32, 64, + 48,147, 43, 43, 43, 43, 43, 80, 32, 32, 32, 32, 32, 32, 40, 43, + 36, 36, 36, 95, 95, 95, 95, 95, 43, 2, 2, 2, 2, 2, 2, 2, + 41, 41, 41,144, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32, + 16, 32, 32, 32, 32, 32, 32, 32, 44, 16, 16, 16, 34, 34, 34, 32, + 32, 32, 32, 32, 42,148, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32, + 32, 32, 11, 11, 34, 34, 32, 16, 32, 16, 16, 32, 32, 32, 11, 11, + 11, 40,149, 35, 40, 35, 36, 36, 36, 65, 36, 65, 36, 64, 36, 36, + 36, 82, 79, 77, 61, 61, 43, 43, 27, 27, 27, 61,150, 61, 61, 61, + 36, 36, 2, 2, 2, 2, 2, 2, 78, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 78, 78, 78, 78, 78, 78, 78, 78, 43, 43, 43, 43, 43, 2, + 43, 36, 36, 36, 2, 66, 66, 64, 36, 36, 36, 43, 43, 43, 43, 2, + 36, 36, 36, 64, 43, 43, 43, 43, 43, 78, 78, 78, 78, 78, 78, 97, + 36, 64, 78, 43, 43, 78, 43, 78, 97, 2, 2, 2, 2, 2, 2, 80, + 7, 7, 7, 7, 7, 7, 7, 2, 36, 36, 64, 63, 36, 36, 36, 36, + 36, 36, 36, 36, 64, 43, 43, 77, 79, 77, 79, 43, 43, 43, 43, 43, + 36, 64, 36, 36, 36, 36, 77, 78, 7, 7, 7, 7, 7, 7, 2, 2, + 63, 36, 36, 71, 61, 82, 77, 36, 65, 43, 65, 64, 65, 36, 36, 43, + 36, 36, 36, 36, 36, 36, 76, 2, 36, 36, 36, 36, 36, 82, 43, 78, + 2, 76,151, 43, 43, 43, 43, 43, 16, 16, 16, 16, 16,103, 40, 40, + 16, 16, 16, 16,100, 41, 41, 41, 36, 82, 79, 78, 77, 97, 79, 43, + 152,152,152,152,152,152,152,152,153,153,153,153,153,153,153,153, + 16, 16, 16, 16, 16, 16, 35, 65, 36, 36, 36, 36,154, 36, 36, 36, + 36, 41, 41, 41, 41, 41, 41, 41, 41, 74, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36,132, 36, 36, 36, 36, 36, 36, 36, 71, + 36, 36, 36, 36, 36, 36,150, 61, 2, 2, 2,135,116, 2, 2, 2, + 6,155,156,132,132,132,132,132,132,132,116,135,116, 2,113,157, + 2, 2, 2, 2,139,132,132,116, 2,158, 8, 8, 60, 2, 2, 2, + 36, 36, 36, 36, 36, 36, 36,159, 2, 2, 3, 2, 4, 5, 6, 2, + 16, 16, 16, 16, 16, 17, 18,115,116, 4, 2, 36, 36, 36, 36, 36, + 63, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40, + 20,160, 53, 20, 26, 8,128, 61, 61, 61, 61, 61,161, 59, 61, 61, + 2, 2, 2, 90, 27, 27, 27, 27, 27, 27, 27, 84, 61, 61, 61, 61, + 95, 95,127, 27, 84, 61, 61, 61, 61, 61, 61, 61, 61, 27, 61, 61, + 61, 61, 61, 61, 61, 61, 47, 43,162,162,162,162,162,162,162,162, + 163, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 87, 36, + 138, 36, 36, 36, 36, 95, 95, 95, 36, 36, 36, 36, 36, 36, 36, 58, + 164, 95, 95, 95, 95, 95, 95, 95, 11, 11, 11, 32, 16, 16, 16, 16, + 36, 36, 36, 58, 27, 27, 27, 27, 36, 36, 36, 71,145, 27, 27, 27, + 36, 36, 36,165, 27, 27, 27, 27, 36, 36, 36, 36, 36,165, 27, 27, + 36, 36, 36, 27, 27, 27, 27, 30, 36, 36, 36, 36, 36, 36, 27, 36, + 64, 43, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 43, 43, 43, 43, + 36, 36, 36, 36, 36, 36,165, 30, 36, 36, 36, 36, 36, 36,165, 27, + 36, 36, 36, 36, 72, 36, 36, 36, 36, 36, 64, 43, 43,163, 27, 27, + 36, 36, 36, 36, 58, 2, 2, 2, 36, 36, 36, 36, 27, 27, 27, 27, + 16, 16, 16, 16, 16, 27, 27, 27, 36, 36, 43, 43, 43, 43, 43, 43, + 7, 7, 7, 7, 7, 36, 36, 63, 11, 11, 11, 11,166, 43, 43,141, + 16, 16, 16, 16, 16, 16, 16, 8, 36, 36, 36, 36, 36, 64,167, 51, + 36, 36, 36, 36, 36, 36, 43, 43, 27, 27, 27, 87, 36, 36, 36, 36, + 163, 27, 30, 2, 2, 2, 2, 2, 36, 43, 43, 2, 2, 2, 2, 2, + 36, 36,165, 27, 27, 27, 27, 27, 79, 81, 36, 36, 36, 36, 36, 36, + 43, 43, 43, 57, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 7, 7, 7, 7, 7, 65, 64, 65, 36, 36, 36, 36, 64, + 78, 79, 43, 77, 79, 57, 73, 2, 2, 43, 43, 43, 43, 43, 67, 59, + 36, 36, 36, 64, 43, 43, 79, 43, 43, 43, 43, 7, 7, 7, 7, 7, + 2, 2, 82, 81, 36, 36, 36, 36, 36, 64, 2, 36, 36, 36, 36, 36, + 36, 82, 78, 43, 43, 43, 43, 77, 81, 36, 58, 2, 56, 43, 57, 79, + 7, 7, 7, 7, 7, 58, 58, 2, 90, 27, 27, 27, 27, 27, 27, 27, + 36, 36, 36, 36, 36, 36, 78, 79, 43, 78, 77, 43, 2, 2, 2, 65, + 36, 36, 36, 36, 36, 36, 36, 64, 77, 78, 78, 78, 78, 78, 78, 78, + 36, 36, 36, 82, 78, 78, 81, 36, 36, 78, 78, 43, 43, 43, 43, 43, + 36, 36, 36, 36, 78, 79, 43, 43, 43, 78, 78, 78, 78, 78, 78, 77, + 65, 65, 2, 2, 2, 2, 2, 2, 56, 43, 43, 43, 43, 43, 43, 43, + 36, 36, 82, 78, 43, 43, 43, 43, 78, 43, 77, 65, 36, 58, 2, 2, + 7, 7, 7, 7, 7, 2, 2, 65, 78, 79, 43, 43, 77, 77, 78, 79, + 77, 43, 36, 66, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 82, + 78, 43, 43, 43, 78, 78, 43, 79, 57, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 36, 36, 43, 43, 78, 79, 43, 43, 43, 77, 79, 79, + 57, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 79, 78, + 43, 43, 43, 79, 58, 2, 2, 2, 36, 36, 36, 36, 36, 36, 64, 79, 78, 43, 43, 79, 43, 43, 43, 43, 7, 7, 7, 7, 7, 27, 2, 89, 43, 43, 43, 43, 79, 57, 2, 2, 27, 27, 27, 27, 27, 27, 27, 87, 78, 78, 78, 78, 78, 79, 77, 65, 81, 79, 2, 2, 2, 2, 2, 2, @@ -4721,39 +4938,41 @@ _hb_ucd_u8[13386] = 78, 78, 78, 78, 78, 78, 78, 78, 64, 43, 43, 43, 43, 65, 36, 36, 36, 64, 43, 43, 77, 64, 43, 57, 2, 2, 2, 56, 43, 43, 43, 43, 64, 43, 43, 77, 79, 43, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, - 43, 43, 43, 77, 43, 2, 66, 2, 43, 43, 43, 43, 43, 43, 43, 79, - 58, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, + 43, 43, 43, 77, 43, 2, 66, 2, 58, 2, 2, 2, 2, 2, 2, 2, + 43, 43, 43, 43, 43, 43, 43, 79, 2, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 77, 43, 43, 43, 77, 43, 79, 43, 43, 43, 43, 43, 43, 43, 43, 64, 43, 43, 43, 43, 36, 36, 36, 36, 36, 78, 78, 78, 43, 77, 79, 79, 36, 36, 36, 36, 36, 64, 77, 97, 2, 2, 2, 2, 43, 82, 36, 36, 36, 36, 36, 36, 36, 36, 78, 43, 43, 43, 43, 78, - 77, 57, 2, 2, 2, 2, 2, 2, 27, 27, 84, 61, 61, 61, 53, 20, - 150, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 21, - 65, 36, 36, 64, 43, 43, 43, 43, 43, 43, 57, 2, 2, 2, 2, 2, - 43, 43, 43, 57, 2, 2, 61, 61, 40, 40, 89, 61, 61, 61, 61, 61, - 7, 7, 7, 7, 7,167, 27, 27, 27, 87, 36, 36, 36, 36, 36, 36, - 27, 27, 27, 30, 2, 2, 2, 2, 82, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 79, 43, 68, 40, 40, 40, 40, 40, 40, - 40, 80, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36, 47, 57, - 61, 61,168, 79, 43, 61,168, 78, 78,169, 59, 59, 59, 76, 43, 43, - 43, 70, 47, 43, 43, 43, 61, 61, 61, 61, 61, 61, 61, 43, 43, 61, - 61, 43, 70, 61, 61, 61, 61, 61, 11, 11, 11, 11, 11, 16, 16, 16, - 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, - 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11, - 11, 11, 11, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, - 11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, - 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, - 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, - 16, 33, 16, 16, 16, 32, 16, 7, 43, 43, 43, 70, 61, 47, 43, 43, - 43, 43, 43, 43, 43, 43, 70, 61, 61, 61, 47, 61, 61, 61, 61, 61, - 61, 61, 70, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 43, 43, - 16, 16, 16, 16, 16, 39, 16, 16, 43, 43, 43, 68, 40, 40, 40, 40, - 7, 7, 7, 7, 7, 7, 7, 71, 36, 36, 36, 36, 36, 36, 36, 43, - 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 7, 7,170, - 36, 36, 36, 36, 36, 75, 43, 43, 16, 16, 43, 43, 43, 68, 40, 40, - 27, 27, 27, 27, 27, 27,145, 27,171, 27, 27, 27, 27, 27, 27, 27, + 77, 57, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 43, 43, 43, + 27, 27, 84, 61, 61, 61, 53, 20,150, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 21, 65, 36, 36, 64, 43, 43, 43, 43, + 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 78, 79, 43, + 43, 43, 57, 2, 2, 2, 2, 2, 43, 43, 43, 57, 2, 2, 61, 61, + 40, 40, 89, 61, 61, 61, 61, 61, 7, 7, 7, 7, 7,168, 27, 27, + 27, 87, 36, 36, 36, 36, 36, 36, 40, 63, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 76,146, 2, 27, 27, 27, 30, 2, 2, 2, 2, + 82, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, + 43, 68, 40, 40, 40, 40, 40, 40, 40, 80, 43, 43, 43, 43, 43, 43, + 36, 36, 36, 36, 36, 36, 47, 57, 61, 61,169, 79, 43, 61,169, 78, + 78,170, 59, 59, 59, 75, 43, 43, 43, 70, 47, 43, 43, 43, 61, 61, + 61, 61, 61, 61, 61, 43, 43, 61, 61, 43, 70, 61, 61, 61, 61, 61, + 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, + 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, + 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, + 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, + 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 16, 7, + 43, 43, 43, 70, 61, 47, 43, 43, 43, 43, 43, 43, 43, 43, 70, 61, + 61, 61, 47, 61, 61, 61, 61, 61, 61, 61, 70, 21, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 56, 43, 43, 16, 16, 16, 16, 16, 39, 16, 16, + 43, 43, 43, 68, 40, 40, 40, 40, 7, 7, 7, 7, 7, 7, 7, 71, + 7, 7, 7, 7, 7, 7, 7,171, 36, 36, 36, 36, 36, 76, 43, 43, + 172, 7, 7, 7, 7, 7, 7, 85, 16, 16, 43, 43, 43, 68, 40, 40, + 27, 27, 27, 27, 27, 27,145, 27,173, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,145, 27, 27, 27, 27, 27, 27, 84, 61, 61, 61, 61, 61, 61, 25, 41, 41, 0, 0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9, @@ -4764,8 +4983,8 @@ _hb_ucd_u8[13386] = 6, 5, 9, 21, 25, 9, 26, 12, 11, 11, 9, 6, 5, 21, 17, 17, 17, 26, 26, 23, 23, 12, 17, 12, 21, 12, 12, 21, 7, 21, 1, 1, 21, 23, 26, 26, 1, 21, 6, 7, 7, 12, 12, 7, 21, 7, 12, 1, - 12, 6, 6, 12, 12, 26, 7, 26, 26, 7, 21, 1, 24, 7, 7, 6, - 1, 12, 12, 10, 10, 10, 10, 12, 21, 6, 10, 7, 7, 10, 23, 7, + 12, 6, 6, 12, 12, 26, 7, 26, 26, 7, 21, 1, 24, 7, 1, 12, + 7, 6, 12, 10, 10, 10, 10, 12, 21, 6, 10, 7, 7, 10, 23, 7, 15, 26, 13, 21, 13, 7, 15, 7, 12, 23, 21, 26, 21, 15, 17, 7, 29, 7, 7, 22, 18, 18, 14, 14, 14, 7, 10, 21, 17, 21, 11, 12, 5, 6, 8, 8, 8, 24, 5, 24, 9, 24, 29, 29, 29, 1, 20, 19, @@ -4776,247 +4995,250 @@ _hb_ucd_u8[13386] = 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, 26, 15, 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3, 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 7, 1, 25, 24, 26, 1, 2, 2, 12, 15, - 21, 14, 7, 15, 12, 17, 13, 15, 26, 10, 10, 1, 13, 23, 23, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 0, - 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 21, 14, 7, 15, 9, 12, 12, 17, 13, 15, 26, 10, 10, 1, 13, 23, + 7, 13, 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, + 11, 12, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 18, 19, 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, 17, 18, 19, 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, 0, 0, 0, 20, 0, 21, - 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 0, 20, 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 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, 35, 0, 0, 0, 0, 36, 0, 37, 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, 35, 0, 36, 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, 0, 0, 37, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 0, 0, - 40, 41, 42, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 5, 6, 7, - 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, 16, 18, 16, 19, - 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, 0, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, 0, 0, - 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, 45, 46, 0, - 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, - 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, 0, 0, 0, 55, - 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, 62, 63, 0, 0, - 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, 0, 0, 68, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, - 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0, 0, 0, - 0, 0, 74, 0, 0, 0, 0, 0, 75, 76, 0, 77, 78, 0, 0, 79, - 80, 0, 81, 62, 0, 82, 83, 0, 0, 84, 85, 86, 0, 0, 0, 87, - 0, 88, 0, 0, 51, 89, 51, 0, 90, 0, 91, 0, 0, 0, 80, 0, - 0, 0, 92, 93, 0, 94, 95, 96, 97, 0, 0, 0, 0, 0, 51, 0, - 0, 0, 0, 98, 99, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 0, - 0,101,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,103, 0, 0, - 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,106, 0, 0,107, - 0, 0, 0, 0, 0, 0,108, 0,109, 0,102, 0, 0, 0, 0, 0, - 110,111, 0, 0, 0, 0, 0, 0, 0,112, 0, 0, 0, 0, 0, 0, - 0,113, 0,114, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, - 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, - 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, - 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, 0, 27, - 0, 0, 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, 33, 0, - 0, 35, 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, 38, 0, - 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, 42, 0, - 0, 0, 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, 47, 0, - 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, 0, 51, - 0, 52, 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, 0, 56, - 0, 0, 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, 0, 0, - 0, 61, 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, 0, 0, - 0, 67, 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, 0, 0, - 77, 78, 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, 0, 81, - 0, 0, 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, 84, 0, - 85, 0, 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, 0, 0, - 0, 88, 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, 0, 0, - 33, 0, 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, 0, 0, - 93, 0, 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, 0, 0, - 98, 0, 0, 0, 99, 0, 0, 0, 0,100,101, 93, 0, 0,102, 0, - 0, 0, 84, 0, 0,103, 0, 0, 0,104,105, 0, 0,106,107, 0, - 0, 0, 0, 0, 0,108, 0, 0,109, 0, 0, 0, 0,110, 33, 0, - 111,112,113, 35, 0, 0,114, 0, 0, 0,115, 0, 0, 0, 0, 0, - 0,116, 0, 0,117, 0, 0, 0, 0,118, 88, 0, 0, 0, 0, 0, - 57, 0, 0, 0, 0, 52,119, 0, 0, 0, 0,120, 0, 0,121, 0, - 0, 0, 0,119, 0, 0,122, 0, 0, 0, 0, 0, 0,123, 0, 0, - 0,124, 0, 0, 0,125, 0,126, 0, 0, 0, 0,127,128,129, 0, - 130, 0,131, 0, 0, 0,132,133,134, 0, 77, 0, 0, 0, 0, 0, - 35, 0, 0, 0,135, 0, 0, 0,136, 0, 0,137, 0, 0,138, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, - 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, - 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, - 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, - 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, 42, 0, - 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, 21, 0, - 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, 0, 0, - 52, 1, 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, - 35, 1, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, - 0, 59, 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, - 64, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, - 68, 0, 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, 0, 77, - 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, 0, 80, - 0, 0, 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, - 83, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, 1, 52, - 15, 86, 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, 1, 0, - 0, 0, 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, 0, 78, - 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, 21, 1, - 21, 92, 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, 81, 99, - 100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, - 0, 61, 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50, 0, 0, - 0, 38, 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68, 61, 0, - 0, 0, 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, 0, 0, - 0,107, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, 0, 0, - 0,108, 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, + 0, 0, 0, 0, 41, 42, 43, 0, 44, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, + 4, 5, 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, + 16, 18, 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, + 0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 35, 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, + 0, 0, 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, + 0, 0, 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, + 62, 63, 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, + 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 69, 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, + 0, 0, 0, 0, 0, 0, 74, 75, 0, 0, 0, 0, 76, 77, 0, 78, + 79, 0, 0, 80, 81, 0, 82, 62, 0, 83, 84, 0, 0, 85, 86, 87, + 0, 88, 0, 89, 0, 90, 0, 0, 51, 91, 51, 0, 92, 0, 93, 0, + 0, 0, 81, 0, 0, 0, 94, 95, 0, 96, 97, 98, 99, 0, 0, 0, + 0, 0, 51, 0, 0, 0, 0,100,101, 0, 0, 0, 0, 0, 0,102, + 0, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 0, 0,104,105, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,106, 0, 0,107, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,108,109, 0, 0,110, 0, 0, 0, 0, + 0, 0,111, 0,112, 0,105, 0, 0, 0, 0, 0,113,114, 0, 0, + 0, 0, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0,117, 0,118, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 0, + 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, 14, 15, + 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, 0, 0, 0, 0, + 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, 0, 27, 0, 0, 28, 29, + 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, 33, 0, 0, 35, 33, 0, + 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0, 0, + 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 43, + 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, + 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, 0, 51, 0, 52, 0, 53, + 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, 0, 56, 0, 0, 0, 0, + 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, 0, 0, 0, 61, 52, 0, + 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, 0, 0, 0, 67, 0, 68, + 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, 0, 0, 77, 78, 0, 0, + 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, 0, 81, 0, 0, 0, 0, + 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, 84, 0, 85, 0, 52, 0, + 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, 0, 0, 0, 88, 57, 0, + 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, 0, 0, 33, 0, 0, 91, + 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, 0, 0, 93, 0, 0, 0, + 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, + 99, 0, 0, 0,100, 0, 0, 0, 0,101,102, 93, 0, 0,103, 0, + 0, 0, 84, 0, 0,104, 0, 0, 0,105,106, 0, 0,107,108, 0, + 0, 0, 0, 0, 0,109, 0, 0,110, 0, 0, 0, 0,111, 33, 0, + 112,113,114, 57, 0, 0,115, 35, 0, 0,116, 0, 0, 0,117, 0, + 0, 0, 0, 0, 0,118, 0, 0,119, 0, 0, 0, 0,120, 88, 0, + 0, 0, 0, 0, 57, 0, 0, 0, 0, 52,121, 0, 0, 0, 0,122, + 0, 0,123, 0, 0, 0, 0,121, 0, 0,124, 0, 0, 0, 0, 0, + 79, 0, 0, 0, 0,125, 0, 0, 0,126, 0, 0, 0,127, 0,128, + 0, 0, 0, 0,129,130,131, 0,132, 0,133, 0, 0, 0,134,135, + 136, 0, 77, 0, 0, 0, 0, 0, 35, 0, 0, 0,137, 0, 0, 0, + 138, 0, 0, 0,139, 0, 0,140, 0, 0,141, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, 4, 8, + 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 19, 1, + 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, 29, 30, + 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, 37, 0, + 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, 42, 0, 0, 0, 43, 36, + 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, 21, 0, 0, 47, 0, 38, + 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, 0, 19, 52, 1, 0, 0, + 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, 0, 0, + 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 59, 0, 60, + 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, + 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 69, + 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, 0, 77, 0, 0, 0, 78, + 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, 0, 80, 0, 0, 0, 62, + 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 19, + 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, 1, 52, 15, 86, 36, 10, + 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, + 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, 0, 78, 0, 0, 87, 9, + 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, 21, 1, 21, 92, 93, 1, + 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, 81, 99,100, 4, 58, 0, + 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 61, 0, 0, + 101,102, 0, 0,103, 0, 0, 1, 1, 50, 0, 0, 0, 38, 0, 63, + 0, 0, 0, 0, 0, 62, 0, 0,104, 68, 61, 0, 0, 0, 78, 0, + 0, 0,105,106, 58, 38, 81, 0, 0, 0, 0, 0, 0,107, 1, 14, + 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, 0, 0, + 109, 61, 0,110, 0, 0, 0, 1, 0, 0, 0, 0, 49, 50, 0, 0, 19, 58, 0, 0, 0, 51, 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61, 0, 0,113, 0, 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0, 78, 55, 0, 38, - 1, 58, 1, 58, 0, 0, 63, 89, 0, 0,115, 0, 0, 0, 55, 0, - 0, 0, 0,115, 0, 0, 0, 0, 61, 0, 0, 0, 0, 79, 0, 61, - 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 79, 0, 0, 0, 8, 91, - 0, 0, 1, 87, 0, 0,116, 0, 0, 0, 0, 0, 0,117, 0,118, - 119,120,121, 0,104, 4,122, 49, 23, 0, 0, 0, 38, 50, 38, 58, - 0, 0, 1, 87, 1, 1, 1, 1, 39, 1, 48,105, 87, 0, 0, 0, - 0, 1, 0, 0, 0,123, 4,122, 0, 0, 0, 1,124, 0, 0, 0, - 0, 0,230,230,230,230,230,232,220,220,220,220,232,216,220,220, - 220,220,220,202,202,220,220,220,220,202,202,220,220,220, 1, 1, - 1, 1, 1,220,220,220,220,230,230,230,230,240,230,220,220,220, - 230,230,230,220,220, 0,230,230,230,220,220,220,220,230,232,220, - 220,230,233,234,234,233,234,234,233,230, 0, 0, 0,230, 0,220, - 230,230,230,230,220,230,230,230,222,220,230,230,220,220,230,222, - 228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, - 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, 0, 0, - 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,220,230, - 230,220, 35, 0, 0, 0, 0, 0,230,230,230, 0, 0,230,230, 0, - 220,230,230,220, 0, 0, 0, 36, 0, 0,230,220,230,230,220,220, - 230,220,220,230,220,230,220,230,230, 0, 0,220, 0, 0,230,230, - 0,230, 0,230,230,230,230,230, 0, 0, 0,220,220,220,230,220, - 220,220,230,230, 0,220, 27, 28, 29,230, 7, 0, 0, 0, 0, 9, - 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0,230, 0, 0, 84, - 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 9, 0,103,103, - 9, 0,107,107,107,107,118,118, 9, 0,122,122,122,122,220,220, - 0, 0, 0,220, 0,220, 0,216, 0, 0, 0,129,130, 0,132, 0, - 0, 0, 0, 0,130,130,130,130, 0, 0,130, 0,230,230, 9, 0, - 230,230, 0, 0,220, 0, 0, 0, 0, 7, 0, 9, 9, 0, 9, 9, - 0, 0, 0,230, 0, 0, 0,228, 0, 0, 0,222,230,220,220, 0, - 0, 0,230, 0, 0,220,230,220, 0,220,230,230,230, 0, 0, 0, - 9, 9, 0, 0, 7, 0,230, 0, 1, 1, 1, 0, 0, 0,230,234, - 214,220,202,230,230,230,230,230,232,228,228,220,218,230,233,220, - 230,220,230,230, 1, 1, 1, 1, 1,230, 0, 1, 1,230,220,230, - 1, 1, 0, 0,218,228,232,222,224,224, 0, 8, 8, 0, 0, 0, - 0,220,230, 0,230,230,220, 0, 0,230, 0, 0, 26, 0, 0,220, - 0,230,230, 1,220, 0, 0,230,220, 0, 0, 0,220,220, 0, 0, - 230,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, - 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, 0, 0, 0,226, - 216,216,216,216,216, 0,220,220,220, 0,232,232,220,230,230,230, - 7, 0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145, 26, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 1, 58, 1, 58, 0, 0, 0, 0, 0, 88, 63, 89, 0, 0,115, 0, + 0, 0, 55, 0, 0, 0, 0,115, 0, 0, 0, 0, 61, 0, 0, 0, + 0, 79, 0, 61, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 79, 0, + 0, 0, 8, 91, 0, 0, 1, 87, 0, 0,116, 0, 0, 0, 0, 0, + 0,117, 0,118,119,120,121, 0,104, 4,122, 49, 23, 0, 0, 0, + 38, 50, 38, 58, 0, 0, 1, 87, 1, 1, 1, 1, 39, 1, 48,105, + 87, 0, 0, 0, 0, 1, 0, 0, 0,123, 0, 0, 0,112, 4,122, + 0, 0, 0, 1,124, 0, 0, 0, 0, 0,230,230,230,230,230,232, + 220,220,220,220,232,216,220,220,220,220,220,202,202,220,220,220, + 220,202,202,220,220,220, 1, 1, 1, 1, 1,220,220,220,220,230, + 230,230,230,240,230,220,220,220,230,230,230,220,220, 0,230,230, + 230,220,220,220,220,230,232,220,220,230,233,234,234,233,234,234, + 233,230, 0, 0, 0,230, 0,220,230,230,230,230,220,230,230,230, + 222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0,230,220, + 0, 18, 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, + 34,230,230,220,220,230,220,230,230,220, 35, 0, 0, 0, 0, 0, + 230,230,230, 0, 0,230,230, 0,220,230,230,220, 0, 0, 0, 36, + 0, 0,230,220,230,230,220,220,230,220,220,230,220,230,220,230, + 230, 0, 0,220, 0, 0,230,230, 0,230, 0,230,230,230,230,230, + 0, 0, 0,220,220,220,230,220,220,220,230,230, 0,220, 27, 28, + 29,230, 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230,230, 0, + 0, 0, 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, + 0, 0, 0, 0, 9, 0,103,103, 9, 0,107,107,107,107,118,118, + 9, 0,122,122,122,122,220,220, 0, 0, 0,220, 0,220, 0,216, + 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,130,130, + 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, 0, 0, + 0, 7, 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0, 0,228, + 0, 0, 0,222,230,220,220, 0, 0, 0,230, 0, 0,220,230,220, + 0,220,230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0,230, 0, + 1, 1, 1, 0, 0, 0,230,234,214,220,202,230,230,230,230,230, + 232,228,228,220,218,230,233,220,230,220,230,230, 1, 1, 1, 1, + 1,230, 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228,232,222, + 224,224, 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230,220, 0, + 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, 0,230, + 220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, 0, 7, + 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, 0,216, + 216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0,220,220, + 220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 33, 17, 49, + 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17,177, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 5, 3, 3, 3, - 3, 3, 6, 7, 8, 3, 3, 3, 3, 3, 9, 10, 11, 12, 13, 3, - 3, 3, 3, 3, 3, 3, 3, 14, 3, 15, 3, 3, 3, 3, 3, 3, - 16, 17, 18, 19, 20, 21, 3, 3, 3, 22, 23, 24, 3, 3, 3, 3, - 3, 3, 25, 3, 3, 3, 3, 3, 3, 3, 3, 26, 3, 3, 27, 28, - 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, - 0, 3, 0, 0, 0, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, - 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 0, - 0, 14, 15, 16, 6, 0, 17, 18, 19, 19, 19, 20, 21, 22, 23, 24, - 19, 25, 0, 26, 27, 19, 19, 28, 29, 30, 0, 31, 0, 0, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 19, 28, 0, 32, 33, 9, 34, 35, 19, - 0, 0, 36, 37, 38, 39, 40, 19, 0, 41, 42, 43, 44, 31, 0, 1, - 45, 42, 0, 0, 0, 0, 0, 32, 14, 14, 0, 0, 0, 0, 14, 0, - 0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51, 52, 53, - 43, 21, 0, 0, 0, 0, 0, 0, 0, 54, 6, 55, 0, 14, 19, 1, - 0, 0, 0, 0, 56, 57, 0, 0, 0, 0, 0, 19, 58, 31, 0, 0, - 0, 0, 0, 0, 0, 59, 14, 0, 0, 0, 0, 1, 0, 2, 0, 0, - 0, 3, 0, 0, 0, 60, 61, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 2, 3, 0, 4, 5, 0, 0, 6, 0, 0, 0, 7, - 0, 0, 0, 1, 1, 0, 0, 8, 9, 0, 8, 9, 0, 0, 0, 0, - 8, 9, 10, 11, 12, 0, 0, 0, 13, 0, 0, 0, 0, 14, 15, 16, - 17, 0, 0, 0, 1, 0, 0, 18, 19, 0, 0, 0, 20, 0, 0, 0, - 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 8, 21, 9, - 0, 0, 22, 0, 0, 0, 0, 1, 0, 23, 24, 25, 0, 0, 26, 0, - 0, 0, 8, 21, 27, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 28, - 29, 30, 0, 31, 32, 20, 1, 1, 0, 0, 0, 8, 21, 9, 1, 4, - 5, 0, 0, 0, 33, 9, 0, 1, 1, 1, 0, 8, 21, 21, 21, 21, - 34, 1, 35, 21, 21, 21, 9, 36, 0, 0, 37, 38, 1, 0, 39, 0, - 0, 0, 1, 0, 1, 0, 0, 0, 0, 8, 21, 9, 1, 0, 0, 0, - 40, 0, 8, 21, 21, 21, 21, 21, 21, 21, 21, 9, 0, 1, 1, 1, - 1, 8, 21, 21, 21, 9, 0, 0, 0, 41, 0, 42, 43, 0, 0, 0, - 1, 44, 0, 0, 0, 45, 8, 9, 1, 0, 0, 0, 8, 21, 21, 21, - 9, 0, 1, 0, 1, 1, 8, 21, 21, 9, 0, 4, 5, 8, 9, 1, - 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 3, 3, 3, 3, 3, 3, 3, 15, 3, 16, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17,177, 0, 1, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, + 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 6, 7, 8, 3, 3, 3, + 3, 3, 9, 10, 11, 12, 13, 3, 3, 3, 3, 3, 3, 3, 3, 14, + 3, 15, 3, 3, 3, 3, 3, 3, 16, 17, 18, 19, 20, 21, 3, 3, + 3, 22, 23, 24, 3, 3, 3, 3, 3, 3, 25, 3, 3, 3, 3, 3, + 3, 3, 3, 26, 3, 3, 27, 28, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 9, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 0, 0, 0, + 0, 0, 0, 10, 11, 12, 13, 0, 0, 14, 15, 16, 6, 0, 17, 18, + 19, 19, 19, 20, 21, 22, 23, 24, 19, 25, 0, 26, 27, 19, 19, 28, + 29, 30, 0, 31, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 19, + 28, 0, 32, 33, 9, 34, 35, 19, 0, 0, 36, 37, 38, 39, 40, 19, + 0, 41, 42, 43, 44, 31, 0, 1, 45, 42, 0, 0, 0, 0, 0, 32, + 14, 14, 0, 0, 0, 0, 14, 0, 0, 46, 47, 47, 47, 47, 48, 49, + 47, 47, 47, 47, 50, 51, 52, 53, 43, 21, 0, 0, 0, 0, 0, 0, + 0, 54, 6, 55, 0, 14, 19, 1, 0, 0, 0, 0, 56, 57, 0, 0, + 0, 0, 0, 19, 58, 31, 0, 0, 0, 0, 0, 0, 0, 59, 14, 0, + 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 60, 61, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, 0, 4, + 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0, 0, 8, + 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, 0, 0, + 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0, 0, 18, + 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0, 0, 1, + 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20, 1, 1, + 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9, 0, 1, + 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21, 9, 36, + 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21, 21, 21, + 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9, 0, 0, + 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45, 8, 9, + 1, 0, 0, 0, 8, 21, 21, 21, 9, 0, 1, 0, 1, 1, 8, 21, + 21, 9, 0, 4, 5, 8, 9, 1, 0, 0, 0, 1, 2, 3, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 3, 3, 3, 3, 3, 3, + 3, 15, 3, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 18, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 17, 17, 18, 17, 19, 20, 21, 22, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 25, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 52, 53, 31, 31, 31, 31, 54, 55, 55, 56, 31, - 31, 31, 31, 31, 31, 31, 57, 58, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 59, 60, 31, 61, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 64, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 65, 66, 67, 31, 31, - 31, 31, 68, 31, 31, 31, 31, 31, 31, 31, 31, 69, 70, 71, 17, 17, - 72, 73, 31, 74, 75, 76, 77, 78, 79, 31, 80, 81, 17, 82, 17, 17, - 17, 17, 31, 31, 23, 23, 23, 23, 23, 23, 23, 83, 31, 31, 31, 31, - 23, 83, 31, 31, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 0, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, + 18, 17, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 25, 25, 26, 27, + 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 31, + 31, 31, 31, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 57, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 58, 31, 31, 31, + 59, 60, 61, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 64, 65, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 66, 67, 68, 31, 31, 31, 31, 69, 31, 31, 31, 31, 31, + 31, 31, 17, 70, 71, 72, 17, 17, 73, 74, 31, 75, 76, 77, 78, 79, + 80, 31, 81, 82, 17, 83, 17, 17, 17, 17, 31, 31, 23, 23, 23, 23, + 23, 23, 23, 84, 31, 31, 31, 31, 23, 84, 31, 31, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 84, 0, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, - 4, 5, 6, 7, 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6, - 7, 8, 9, 10, 11, 11, 12, 11, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 19, 27, 28, 29, 30, 30, 31, 31, 32, 32, - 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 40, 41, 41, - 42, 42, 42, 43, 44, 44, 45, 46, 47, 47, 47, 47, 48, 48, 48, 48, - 48, 48, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 53, - 54, 55, 56, 56, 57, 58, 59, 51, 60, 61, 62, 63, 64, 65, 66, 7, - 67, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 7, 4, 4, 4, 4, - 77, 77, 77, 77, 78, 79, 80, 81, 82, 83, 84, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 85, 85, 85, 85, 0, 0, 0, 0, 86, 87, 88, 88, - 89, 90, 48, 91, 0, 0, 92, 92, 92, 92, 92, 93, 94, 95, 96, 97, - 98, 47, 99,100,101,102, 0,103,104,105, 0, 0, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0,106,106,106,106, - 106,106,106,106,106,106,106,107,108,108,108,108,108, 11,109,110, - 111, 4,112, 4,113,114,115,116,117,118,119,120,121,122,123,124, - 125,126, 50,127, 47, 47, 47, 47, 47, 47, 47, 47,128,128,128,128, - 128,128,128,128,128,128,128,128, 92, 92, 92, 92, 92, 92, 92, 92, - 129,130, 19, 19, 19, 19, 19, 19,131, 19, 19, 19,132,133, 19,134, - 135,136,137,101,138,138,138,138, 0, 77,139,140,128,128,141,142, - 143,144,145,146,147,148,149,150,151,152,153,153,154,154,154,154, - 154,154, 4, 4,155,156,157,158,159,160,161,162,163,164,165,166, - 167,168,169,169,170,170,171,171,172,172,128,128, 19, 19,173,174, - 175,176,177,178,179,179,180,181,182,183,184,185,186,186,187,188, - 189,190,128,128,191,191,192,192,128,128,193,193,194,195,196,196, - 197,197,128,128,198,198,199,199,200,200,201,201,202,203,204,205, - 28, 28,128,128,206,207,208,208,209,210,211,211,128,128,212,212, - 213,213,214, 34,215,215,215,215,215,215,215,215,215,215,215,215, - 215,215,128,128,128,128,128,128,128,128,216,216,217,217,217,217, - 217,217,217,217,217,217,128,128,128,128,128,128,218,218,218,218, - 218,218,218,218,218,218,128,128,128,128,128,128,110,110,110,110, - 110,110,110,110,110,219,220,221,222,222,222,222,223,223,223,223, - 224,224,224,225,226,226,226,226,226,226,226,226,226,226,226,226, - 227,227,227,227,227,227,227,227,226,226,128,128,128,128,128,128, - 128,128,104,104,228,229,229,229,230,231,232,232,232,232,232,232, - 128,128,128,128,233,233,234, 0,128,128,128,128,128,128,128,128, - 7,235, 0, 0, 0, 0, 0, 0, 0,236,237, 0, 77, 77, 0, 0, - 0, 0,128,128,238,238,238,238,238,238,238,238,238,238,238,238, - 128,128,128,128,128,128,128,128, 4, 4,128,128,239, 11, 11, 11, - 240,240,128,128,128,128,241,242,128,128,128,128,128,128,243,243, - 128,128,128,128,128,128,128,128,128,128, 48, 48,244,244,244,244, - 245,245,128,128, 0, 0, 0, 0, 0, 0,128,128, 19, 19, 19, 19, - 128,128,128,128,246, 0,128,128, 0, 0, 0, 0, 92, 92,128,128, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 85, 0, 0, 1, + 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, + 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 11, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 19, 27, + 28, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, + 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 42, 43, 44, 44, 45, 46, + 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 49, 50, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 51, + 60, 61, 62, 63, 64, 65, 66, 7, 67, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 7, 4, 4, 4, 4, 77, 77, 77, 77, 78, 79, 80, 81, + 82, 83, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, + 0, 0, 0, 0, 86, 87, 88, 88, 89, 90, 48, 91, 0, 0, 92, 92, + 92, 92, 92, 93, 94, 95, 96, 97, 98, 47, 99,100,101,102, 0,103, + 104,105, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 0,106,106,106,106,106,106,106,106,106,106,106,107, + 108,108,108,108,108, 11,109,110,111, 4,112, 4,113,114,115,116, + 117,118,119,120,121,122,123,124,125,126, 50,127, 47, 47, 47, 47, + 47, 47, 47, 47,128,128,128,128,128,128,128,128,128,128,128,128, + 92, 92, 92, 92, 92, 92, 92, 92,129,130, 19, 19, 19, 19, 19, 19, + 131, 19, 19, 19,132,133, 19,134,135,136,137,101,138,138,138,138, + 0, 77,139,140,128,128,141,142,143,144,145,146,147,148,149,150, + 151,152,153,154,155,155,155,155,155,155, 4, 4,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,170,171,171,172,172, + 173,174,174,174, 19, 19,175,176,177,178,179,180,181,181,182,183, + 184,185,186,187,188,188,189,190,191,192,193,193,194,194,195,195, + 128,128,196,196,197,198,199,200,201,201,128,128,202,202,203,203, + 204,204,205,205,206,207,208,209, 28, 28,210,210,211,212,213,213, + 214,215,216,216,128,128,217,217,218,218,219, 34,220,220,220,220, + 220,220,220,220,220,220,220,220,220,220,128,128,128,128,128,128, + 128,128,221,221,222,222,222,222,222,222,222,222,223,223,223,223, + 223,223,223,223,223,223,128,128,128,128,128,128,128,128,128,128, + 224,224,128,128,110,110,110,110,110,110,110,110,110,225,226,227, + 228,228,228,228,128,128,128,128,229,229,128,128,230,230,230,230, + 231,231,231,232,233,233,233,233,233,233,233,233,233,233,233,233, + 234,234,234,234,234,234,234,234,233,233,128,128,128,128,128,128, + 128,128,104,104,235,236,236,236,237,238,239,239,239,239,239,239, + 128,128,128,128,240,240,241, 0,128,128,128,128, 0, 0, 0, 0, + 7,242, 0, 0, 0, 0, 0, 0, 0,243,244, 0, 77, 77, 0, 0, + 0, 0,128,128,245,245,245,245,245,245,245,245,245,245,245,245, + 128,128,128,128,128,128,128,128, 4, 4,128,128,246, 11, 11, 11, + 247,247,128,128,128,128,248,249,128,128,128,128,128,128,250,250, + 128,128,251,251,128,128,128,128,128,128, 48, 48,252,252,252,252, + 253,253,128,128, 0, 0, 0, 0, 0, 0,128,128, 19, 19, 19, 19, + 128,128,128,128,254, 0,128,128, 0, 0, 0, 0, 92, 92,128,128, 128,128,128,128, 0, 0,128,128, 7, 7, 7, 7, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, @@ -5056,30 +5278,32 @@ _hb_ucd_u8[13386] = 137,137,138,138,138,138,139, 0,140,140,140,141,141,142,142,142, 143,143,144,144,144,144,144,144,145,145,145,145,145,146,146,146, 147,147,147,148,148,148,148,148,149,149,149,150,150,150,150,151, - 151,151,151,151,152,152,152,152,153,153,153,153,154,154,155,155, - 156,156,156,156,156,156,157,157,158,158,159,159,159,159,159,159, - 160,160,161,161,161,161,161,161,162,162,162,162,162,162,163,163, - 164,164,164,164,165,165,165,165,166,166,166,166,167,167,168,168, - 169,169,169,169,170,170,170,170,171,171,171,171,172,172,172,172, - 173,173,173,173,173,173,173,174,175,175,175,176,176,176,176,177, - 177,177,177,178,178,178,179,179,180,180,180,180,181,181,181,181, - 181,182,182,182,183,183,183,183,183,184,184,184,185,185,185,185, - 185,185,186, 43,187,187,187,187,188,188,188,189,189,189,189,189, - 190,190,190,191,190,190,190,190,192,192,192,192,193,193,193,193, - 194,194,194,194,195,195,195,195,195,195, 66, 66,196,196,196,196, - 197,197,197,197,198,198,198,198,199,199,199,199,200,200,200,200, - 201,201,201,201,202,202,202,202,202,203,203,203,203,203,203, 55, - 204,204,204,204,205,205,205,205,205,205,205,206,206,206,206,206, - 207,207,207,207,207,207,208,208,208,208,208,208,209,209,209,209, - 210,210,210,210,110,110,110,110,211,211,211,211,212,212,212,212, - 213,213,213,213,214,214,214,214,215,215,215,216,216,216,216,216, - 216,217,217,217,218,218,218,218,219,219,219,219,220,220,220,220, - 220,220,221, 94,222,222,222,222,223,223,223,223,224, 99, 99, 99, - 99, 99, 99, 99, 99, 99,102,225, 99,226,102,227,227,227,227,227, - 228,228,228,228,228,228, 0, 0, 8, 0, 0, 0, 0, 0,229,230, - 231, 0,232, 0,233,233,233,233, 91, 91, 91, 13,234,234,234,234, - 235,235,235,235,236,236,236,236,237,237,237,237,238,238,238,238, - 239,239,239,239,240, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, + 151,151,151,151,152,152,152,152,153,153,153,153,154,154,154,154, + 155,155,156,156,157,157,157,157,157,157,158,158,159,159,160,160, + 160,160,160,160,161,161,162,162,162,162,162,162,163,163,163,163, + 163,163,164,164,165,165,165,165,166,166,166,166,167,167,167,167, + 168,168,169,169,170,170,170,170,171,171,171,171,172,172,172,172, + 173,173,173,173,174,174,174,174,175,175,175,175,176, 21, 21, 21, + 177,177,177,178,178,178,178,179,179,179,179,180,180,180,181,181, + 182,182,182,182,183,183,183,183,183,184,184,184,185,185,185,185, + 185,186,186,186,187,187,187,187,187,187,188, 43,189,189,189,189, + 190,190,190,191,191,191,191,191,192,192,192,193,192,192,192,192, + 194,194,194,194,195,195,195,195,196,196,196,196,197,197,197,197, + 198,198,198,198,198,198, 66, 66,199,199,199,199,199, 49, 49, 49, + 200,200,200,200,201,201,201,201,202,202,202,202,203,203,203,203, + 204,204,204,204,205,205,205,205,205,206,206,206,206,206,206, 55, + 207,207,207,207,208,208,208,208,209,209,209,209,209,209,209,210, + 210,210,210,210,211,211,211,211,211,211,212,212,212,212,212,212, + 213,213,213,213,214,214,214,214,110,110,110,110,215,215,215,215, + 216,216,216,216,217,217,217,217,218,218,218,218,219,219,219,219, + 220,220,220,221,221,221,221,221,221,222,222,222,223,223,223,223, + 224,224,224,224,225,225,225,225,226,226,226,226,226,226,227, 94, + 228,228,228,228,229,229,229,229,230, 99, 99, 99, 99, 99, 99, 99, + 99, 99,102,231, 99,232,102,233,233,233,233,233,234,234,234,234, + 234,234, 0, 0, 8, 0, 0, 0, 0, 0,235,236,237, 0,238, 0, + 239,239,239,239, 91, 91, 91, 13,240,240,240,240,241,241,241,241, + 242,242,242,242,243,243,243,243,244,244,244,244,245,245,245,245, + 246,246,246,246,247, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0, 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8, 8, 8, 8, 8, 12, 13, 13, 13, 14, 14, 14, 14, @@ -5123,98 +5347,102 @@ _hb_ucd_u8[13386] = 163,163,163,163,164,164,164,164,165,165,165,165,166,166,166,166, 167,167,167,167,168,168,168,168,169,169,169,169,170,170,170,170, 171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,174, - 174,174,174,175,176,176,176,176,177,177,177,177,178,178,178,178, + 175,175,175,175,176,176,176,176,177, 20, 20, 20,178,178,178,178, 179,179,179,179,180,180,180,180,181,181,181,181,182,182,182,182, 183,183,183,183,184,184,184,184,185,185,185,185,186,186,186,186, - 187, 45, 45, 45,188,188,188,188,189,189,189,189,190,190,190,190, - 191,191,191,191,191,191,192,191,193,193,193,193,194,194,194,194, + 187,187,187,187,188,188,188,188,189, 45, 45, 45,190,190,190,190, + 191,191,191,191,192,192,192,192,193,193,193,193,193,193,194,193, 195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198, 199,199,199,199,200,200,200,200,201,201,201,201,202,202,202,202, 203,203,203,203,204,204,204,204,205,205,205,205,206,206,206,206, 207,207,207,207,208,208,208,208,209,209,209,209,210,210,210,210, 211,211,211,211,212,212,212,212,213,213,213,213,214,214,214,214, 215,215,215,215,216,216,216,216,217,217,217,217,218,218,218,218, - 219,219,219,219,220,220,220,220,221,221,221,221,222,223,223,223, - 224,224,224,224,223,223,223,223,225,106,106,106,226,106,106,106, - 106,227,109,109,228,228,228,228,229,229,229,229, 0,230, 86, 0, - 0, 0,230, 7, 82,138, 7, 0, 0, 0,231, 86,232,232,232,232, - 233,233,233,233,234,234,234,234,235,235,235,235,236,236,236,236, - 237,237,237,237,238,238,238,238,239, 0, 0, 0, 0, 0, 0, 0, - 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, - 19, 0, 0, 0, 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, - 55, 55, 55, 55, 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, - 4, 4, 4, 4, 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, - 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, - 1, 1, 3, 3, 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38, - 64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3, - 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, - 5, 5, 5, 5, 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, - 22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, - 36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18, - 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33, - 8, 8, 8, 8, 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, - 29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, - 35, 35, 35, 0, 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, - 44, 0, 0, 0, 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, - 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, - 52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, - 62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, - 73, 73, 73, 73, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, - 0, 1, 0, 0, 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6, - 19, 9, 9, 9, 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, - 19, 19, 19, 9, 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19, - 27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13, - 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, - 0, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12, - 12, 12, 12, 0, 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, - 79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, - 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84, - 84, 84, 84, 0, 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, - 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 19, 19, 19, 4, - 3, 3, 0, 0, 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, - 49, 49, 49, 49, 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, - 42, 42, 42, 42, 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, - 59, 59, 59, 59, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50, - 135,135,135,135,106,106,106,106,104,104,104,104,161,161,161,161, + 219,219,219,219,220,220,220,220,221,221,221,221,222,222,222,222, + 223,223,223,223,224,224,224,224,225,225,225,225,226,226,226,226, + 227,227,227,227,228,229,229,229,230,230,230,230,229,229,229,229, + 231,106,106,106,232,106,106,106,106,233,109,109,234,234,234,234, + 235,235,235,235, 0,236, 86, 0, 0, 0,236, 7, 82,138, 7, 0, + 0, 0,237, 86,238,238,238,238,239,239,239,239,240,240,240,240, + 241,241,241,241,242,242,242,242,243,243,243,243,244,244,244,244, + 245,245,245,245,246, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0, + 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55, + 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4, + 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3, + 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3, + 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64, + 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7, + 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, + 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22, + 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36, + 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25, + 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8, + 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29, + 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0, + 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0, + 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0, + 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52, + 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62, + 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73, + 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9, + 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9, + 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, + 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13, + 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15, + 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0, + 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79, + 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69, + 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0, + 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19, + 19, 19, 0, 0, 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0, + 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49, + 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42, + 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59, + 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135, + 106,106,106,106,104,104,104,104,161,161,161,161,170,170,170,170, 110,110,110,110, 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120, 116,116,116,116,128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88, 117,117,117,117,112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,122,122,122,122, 89, 89, 89, 89,130,130,130,130, - 144,144,144,144,156,156,156,156,156, 3, 3, 3,147,147,147,147, - 148,148,148,148,158,158,158,158,153,153,153,153,149,149,149,149, - 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101, 96, 96, 96, 96, - 111,111,111,111,100,100,100,100,100, 36, 36, 36,108,108,108,108, - 129,129,129,129,109,109,109,109,107,107,107,107,107,107,107, 1, - 137,137,137,137,124,124,124,124,123,123,123,123,114,114,114,114, - 102,102,102,102,126,126,126,126,142,142,142,142,125,125,125,125, - 154,154,154,154,150,150,150,150,141,141,141,141,140,140,140,140, - 121,121,121,121,133,133,133,133,134,134,134,134,138,138,138,138, - 143,143,143,143,145,145,145,145,163,163,163,163, 63, 63, 63, 63, - 157,157,157,157, 80, 80, 80, 80,127,127,127,127,115,115,115,115, - 159,159,159,159,103,103,103,103,119,119,119,119,146,146,146,146, - 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,136,136,136,136, - 17, 15, 15, 15, 17, 17, 15, 15, 15, 17, 17, 17,139,139,139,139, - 105,105,105,105, 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131, - 151,151,151,151,160,160,160,160,152,152,152,152,164,164,164,164, - 113,113,113,113,132,132,132,132, 15, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, 9, 9, - 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 144,144,144,144,165,165,165,165,156,156,156,156,156,156, 3, 3, + 147,147,147,147,148,148,148,148,158,158,158,158,153,153,153,153, + 149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101, + 96, 96, 96, 96,111,111,111,111,100,100,100,100,100, 36, 36, 36, + 108,108,108,108,129,129,129,129,109,109,109,109,107,107,107,107, + 107,107,107, 1,171,171,171,171,137,137,137,137,124,124,124,124, + 123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126, + 142,142,142,142,125,125,125,125,154,154,154,154,150,150,150,150, + 141,141,141,141,140,140,140,140,121,121,121,121,169,169,169,169, + 133,133,133,133,134,134,134,134,138,138,138,138,143,143,143,143, + 145,145,145,145,163,163,163,163, 63, 63, 63, 63,157,157,157,157, + 80, 80, 80, 80,127,127,127,127,166,166,166,166,115,115,115,115, + 159,159,159,159,103,103,103,103,119,119,119,119,167,167,167,167, + 146,146,146,146, 99, 99, 99, 99,136,139, 13, 13,155,155,155,155, + 136,136,136,136, 17, 15, 15, 15, 17, 17, 15, 15, 15, 17, 17, 17, + 139,139,139,139,105,105,105,105, 0, 0, 0, 1, 0, 0, 1, 1, + 131,131,131,131,151,151,151,151,160,160,160,160,152,152,152,152, + 164,164,164,164,168,168,168,168,113,113,113,113,132,132,132,132, + 15, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, + 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 16, 17, 9, 9, 9, 9, 18, 9, 9, 9, 9, 9, 19, 20, 21, 9, + 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 23, 9, 9, 9, 9, 9, 24, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, @@ -5223,60 +5451,66 @@ _hb_ucd_u8[13386] = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, - 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, - 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, + 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, + 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, + 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, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, + 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, + 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 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, 43, 44, 0, 45, - 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, - 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, - 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, - 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, - 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, + 0, 0, 0, 0, 66, 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, 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, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, - 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0, - 111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, + 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100, + 101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, + 0, 0,108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0, + 115, 0, 0, 0,116, 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,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119, - 120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126, + 0,127, 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, 0, 0, 0, 0,128,129,130,131,132,133, - 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149, - 150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160,161, 0, + 0, 0,128,129,130,131,132,133,134,135,136,137,138,139,140,141, + 142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157, + 0, 0, 0,158,159,160,161, 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,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162, 0, + 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,164,165, 0, 0, 0, + 0, 0, 0, 0,166, 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, 0, 0, 0, 0, 0,165, 0, + 0, 0, 0, 0, 0, 0,167, 0, 0, 0,168,169, 0, 0,170, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,171, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 0, 0, + 0, 0, 0, 0, 0,173, 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, 0, 0, 0, 0, 0,169, - 170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176,177,178, - 179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194, - 195,196,197,198,199,200,201,202,203,204,205,206, 0, 0, 0, 0, + 0, 0, 0, 0,174, 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, 1, 2, 3, 4, + 0, 0, 0, 0, 0, 0, 0, 0,175, 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,176,177, 0, 0, 0, 0,178,179, 0, + 0, 0,180,181,182,183,184,185,186,187,188,189,190,191,192,193, + 194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, + 210,211,212,213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 3, 4, }; static const uint16_t -_hb_ucd_u16[4920] = +_hb_ucd_u16[5080] = { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, @@ -5303,82 +5537,85 @@ _hb_ucd_u16[4920] = 47, 47, 165, 166, 167, 47, 47, 47, 47, 47, 47, 47, 47, 168, 146, 146, 47, 169, 47, 47, 47, 170, 171, 172, 160, 160, 173, 174, 32, 32, 32, 32, 175, 47, 47, 176, 177, 122, 178, 179, 180, 47, 181, 61, 47, 47, 182, 183, - 47, 47, 184, 185, 186, 61, 47, 187, 11, 9, 9, 9, 66, 188, 189, 190, - 11, 11, 191, 27, 27, 27, 192, 193, 11, 194, 27, 27, 32, 32, 32, 32, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 195, 13, 13, 13, 13, 13, 13, - 196, 196, 196, 196, 196, 197, 196, 11, 198, 198, 198, 199, 200, 201, 201, 200, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 27, 211, 211, 211, 212, 213, 32, - 214, 215, 216, 217, 218, 145, 219, 219, 220, 221, 222, 146, 223, 224, 146, 225, - 226, 226, 226, 226, 226, 226, 226, 226, 227, 146, 228, 146, 146, 146, 146, 229, - 146, 230, 226, 231, 146, 232, 233, 146, 146, 146, 146, 146, 146, 146, 145, 145, - 145, 234, 146, 146, 146, 146, 235, 145, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 236, 237, 146, 146, 238, 146, 146, 146, 146, 146, 146, 239, 146, - 146, 146, 146, 146, 146, 146, 240, 241, 145, 242, 146, 146, 243, 226, 244, 226, - 245, 246, 226, 226, 226, 247, 226, 248, 146, 146, 146, 226, 249, 146, 146, 146, - 9, 9, 9, 11, 11, 11, 250, 251, 13, 13, 13, 13, 13, 13, 252, 253, - 11, 11, 11, 47, 47, 47, 254, 255, 47, 47, 47, 47, 47, 47, 32, 32, - 256, 257, 258, 259, 260, 261, 262, 262, 263, 264, 265, 266, 267, 47, 47, 47, - 47, 268, 148, 47, 47, 47, 47, 269, 47, 270, 47, 47, 146, 146, 146, 47, - 146, 146, 271, 146, 272, 273, 146, 146, 271, 146, 146, 273, 146, 146, 146, 146, - 47, 47, 47, 47, 146, 146, 146, 146, 47, 274, 47, 47, 47, 47, 47, 47, - 47, 146, 146, 146, 146, 47, 47, 187, 275, 47, 61, 47, 13, 13, 276, 277, - 13, 278, 47, 47, 47, 47, 279, 280, 31, 281, 282, 283, 13, 13, 13, 284, - 285, 286, 287, 288, 289, 290, 11, 291, 292, 47, 293, 294, 47, 47, 47, 295, - 296, 47, 47, 297, 298, 160, 32, 299, 61, 47, 300, 47, 301, 302, 47, 47, - 72, 47, 47, 303, 304, 305, 306, 61, 47, 47, 307, 308, 309, 310, 47, 311, - 47, 47, 47, 312, 58, 313, 314, 315, 47, 47, 47, 11, 11, 316, 317, 11, - 11, 11, 11, 11, 47, 47, 318, 160, 319, 319, 319, 319, 319, 319, 319, 319, - 320, 320, 320, 320, 320, 320, 320, 320, 11, 321, 322, 47, 47, 47, 47, 47, - 47, 47, 47, 323, 31, 324, 47, 47, 47, 47, 47, 325, 146, 47, 47, 47, - 47, 47, 47, 47, 326, 146, 146, 327, 32, 328, 32, 329, 330, 331, 332, 47, - 47, 47, 47, 47, 47, 47, 47, 333, 334, 2, 3, 4, 5, 335, 336, 337, - 47, 338, 47, 47, 47, 47, 339, 340, 341, 145, 145, 342, 219, 219, 219, 343, - 344, 146, 146, 146, 146, 146, 146, 345, 346, 346, 346, 346, 346, 346, 346, 346, - 47, 47, 47, 47, 47, 47, 347, 145, 47, 47, 348, 47, 349, 47, 47, 60, - 47, 350, 47, 47, 47, 351, 219, 219, 9, 9, 147, 11, 11, 47, 47, 47, - 47, 47, 160, 9, 9, 147, 11, 11, 47, 47, 47, 47, 47, 47, 350, 9, - 9, 352, 11, 11, 11, 11, 11, 11, 27, 27, 27, 27, 27, 27, 27, 27, - 47, 47, 47, 47, 47, 353, 47, 354, 47, 47, 355, 145, 145, 145, 47, 356, - 47, 357, 47, 350, 66, 66, 66, 66, 47, 47, 47, 358, 145, 145, 145, 145, - 359, 47, 47, 360, 145, 66, 47, 361, 47, 362, 145, 145, 363, 47, 364, 66, - 47, 47, 47, 365, 47, 366, 47, 366, 47, 365, 144, 145, 145, 145, 145, 145, - 9, 9, 9, 9, 11, 11, 11, 367, 47, 47, 368, 160, 160, 160, 160, 160, - 145, 145, 145, 145, 145, 145, 145, 145, 47, 47, 369, 47, 47, 47, 47, 143, - 47, 362, 370, 47, 60, 371, 66, 47, 372, 66, 66, 47, 373, 145, 47, 47, - 374, 47, 47, 360, 375, 376, 377, 378, 180, 47, 47, 379, 380, 47, 47, 160, - 97, 47, 381, 382, 383, 47, 47, 384, 180, 47, 47, 385, 386, 387, 388, 145, - 47, 47, 389, 390, 359, 32, 32, 32, 47, 47, 365, 47, 47, 391, 172, 160, - 92, 47, 47, 113, 392, 393, 394, 32, 47, 47, 47, 395, 396, 397, 47, 47, - 47, 47, 47, 398, 399, 160, 160, 160, 47, 47, 400, 401, 402, 403, 32, 32, - 47, 47, 47, 404, 405, 160, 66, 66, 47, 47, 406, 407, 160, 160, 160, 160, - 47, 143, 408, 409, 47, 47, 47, 47, 47, 47, 389, 410, 66, 66, 66, 66, - 9, 9, 9, 9, 11, 11, 128, 411, 47, 47, 47, 412, 413, 160, 160, 160, - 47, 47, 47, 47, 47, 414, 415, 416, 417, 47, 47, 418, 419, 420, 47, 47, - 421, 422, 66, 47, 47, 47, 47, 47, 66, 66, 66, 66, 66, 66, 66, 66, - 47, 47, 400, 423, 424, 128, 145, 425, 47, 156, 426, 427, 32, 32, 32, 32, - 47, 47, 47, 359, 428, 160, 47, 47, 429, 430, 160, 160, 160, 160, 160, 160, - 47, 47, 47, 47, 47, 47, 47, 431, 432, 47, 47, 433, 434, 160, 160, 160, - 47, 47, 47, 47, 145, 435, 436, 437, 219, 219, 219, 219, 219, 219, 219, 66, - 47, 47, 47, 47, 47, 47, 47, 424, 47, 47, 47, 208, 438, 32, 32, 32, - 47, 47, 47, 47, 47, 47, 305, 47, 47, 47, 47, 47, 160, 47, 47, 439, - 47, 47, 47, 440, 441, 442, 443, 47, 9, 9, 9, 9, 9, 9, 11, 11, - 145, 444, 66, 66, 66, 66, 66, 66, 47, 47, 47, 47, 391, 445, 416, 416, - 446, 447, 27, 27, 27, 27, 448, 416, 47, 449, 208, 208, 208, 208, 208, 208, - 32, 32, 32, 32, 32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 450, 451, - 452, 146, 453, 146, 146, 146, 146, 146, 146, 146, 146, 146, 454, 146, 146, 146, - 9, 455, 11, 456, 457, 11, 196, 9, 458, 459, 9, 460, 11, 9, 455, 11, - 456, 457, 11, 196, 9, 458, 459, 9, 460, 11, 9, 455, 11, 456, 457, 11, - 196, 9, 458, 459, 9, 460, 11, 9, 455, 11, 196, 9, 461, 462, 463, 464, - 11, 465, 9, 466, 467, 468, 469, 11, 470, 9, 471, 11, 472, 160, 160, 160, - 32, 32, 32, 473, 32, 32, 474, 475, 476, 477, 32, 32, 32, 32, 32, 32, - 478, 11, 11, 11, 11, 11, 11, 11, 32, 32, 32, 27, 27, 27, 27, 27, - 32, 32, 32, 32, 32, 32, 32, 32, 47, 47, 47, 479, 480, 146, 146, 146, - 47, 47, 481, 32, 47, 47, 482, 483, 47, 47, 47, 47, 47, 47, 484, 160, - 47, 47, 47, 47, 355, 32, 32, 32, 9, 9, 458, 11, 485, 305, 66, 66, - 145, 145, 486, 487, 145, 145, 145, 145, 145, 145, 488, 145, 145, 145, 145, 145, - 47, 47, 47, 47, 47, 47, 47, 226, 489, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 490, 146, 146, 146, 146, 146, 146, 146, 160, - 208, 208, 208, 208, 208, 208, 208, 208, 0, 0, 0, 0, 0, 0, 0, 0, + 47, 47, 184, 185, 186, 61, 47, 187, 188, 9, 9, 9, 66, 189, 190, 191, + 11, 11, 192, 27, 27, 27, 193, 194, 11, 195, 27, 27, 32, 32, 32, 32, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 196, 13, 13, 13, 13, 13, 13, + 197, 197, 197, 197, 197, 198, 197, 11, 199, 199, 199, 200, 201, 202, 202, 201, + 203, 204, 205, 206, 207, 208, 209, 210, 211, 27, 212, 212, 212, 213, 214, 32, + 215, 216, 217, 218, 219, 145, 220, 220, 221, 222, 223, 146, 224, 225, 146, 226, + 227, 227, 227, 227, 227, 227, 227, 227, 228, 146, 229, 146, 146, 146, 146, 230, + 146, 231, 227, 232, 146, 233, 234, 146, 146, 146, 146, 146, 146, 146, 145, 145, + 145, 235, 146, 146, 146, 146, 236, 145, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 237, 238, 146, 146, 239, 146, 146, 146, 146, 146, 146, 240, 146, + 146, 146, 146, 146, 146, 146, 241, 242, 145, 243, 146, 146, 244, 227, 245, 227, + 246, 247, 227, 227, 227, 248, 227, 249, 146, 146, 146, 227, 250, 146, 146, 146, + 9, 9, 9, 11, 11, 11, 251, 252, 13, 13, 13, 13, 13, 13, 253, 254, + 11, 11, 11, 47, 47, 47, 255, 256, 47, 47, 47, 47, 47, 47, 32, 32, + 257, 258, 259, 260, 261, 262, 263, 263, 264, 265, 266, 267, 268, 47, 47, 47, + 47, 269, 148, 47, 47, 47, 47, 270, 47, 271, 47, 47, 146, 146, 146, 47, + 146, 146, 272, 146, 273, 274, 146, 146, 272, 146, 146, 274, 146, 146, 146, 146, + 47, 47, 47, 47, 146, 146, 146, 146, 47, 275, 47, 47, 47, 47, 47, 47, + 47, 146, 146, 146, 146, 47, 47, 187, 276, 47, 61, 47, 13, 13, 277, 278, + 13, 279, 47, 47, 47, 47, 280, 281, 31, 282, 283, 284, 13, 13, 13, 285, + 286, 287, 288, 289, 290, 291, 9, 292, 293, 47, 294, 295, 47, 47, 47, 296, + 297, 47, 47, 298, 299, 160, 32, 300, 61, 47, 301, 47, 302, 303, 47, 47, + 72, 47, 47, 304, 305, 306, 307, 61, 47, 47, 308, 309, 310, 311, 47, 312, + 47, 47, 47, 313, 58, 314, 315, 316, 47, 47, 47, 11, 11, 317, 318, 11, + 11, 11, 11, 11, 47, 47, 319, 160, 320, 320, 320, 320, 320, 320, 320, 320, + 321, 321, 321, 321, 321, 321, 321, 321, 11, 322, 323, 47, 47, 47, 47, 47, + 47, 47, 47, 324, 31, 325, 47, 47, 47, 47, 47, 326, 146, 47, 47, 47, + 47, 47, 47, 47, 327, 146, 146, 328, 32, 329, 32, 330, 331, 332, 333, 47, + 47, 47, 47, 47, 47, 47, 47, 334, 335, 2, 3, 4, 5, 336, 337, 338, + 47, 339, 47, 47, 47, 47, 340, 341, 342, 145, 145, 343, 220, 220, 220, 344, + 345, 146, 146, 146, 146, 146, 146, 346, 347, 347, 347, 347, 347, 347, 347, 347, + 47, 47, 47, 47, 47, 47, 348, 145, 47, 47, 349, 47, 350, 47, 47, 60, + 47, 351, 47, 47, 47, 352, 220, 220, 9, 9, 147, 11, 11, 47, 47, 47, + 47, 47, 160, 9, 9, 147, 11, 11, 47, 47, 47, 47, 47, 47, 351, 9, + 9, 353, 11, 11, 47, 47, 47, 47, 27, 27, 27, 27, 27, 27, 27, 27, + 47, 47, 47, 47, 47, 354, 47, 355, 47, 47, 356, 145, 145, 145, 47, 357, + 47, 358, 47, 351, 66, 66, 66, 66, 47, 47, 47, 359, 145, 145, 145, 145, + 360, 47, 47, 361, 145, 66, 47, 362, 47, 363, 145, 145, 364, 47, 365, 66, + 47, 47, 47, 366, 47, 367, 47, 367, 47, 366, 144, 145, 145, 145, 145, 145, + 9, 9, 9, 9, 11, 11, 11, 368, 47, 47, 369, 160, 370, 9, 371, 11, + 372, 227, 227, 227, 227, 227, 227, 227, 145, 145, 145, 145, 145, 145, 145, 145, + 47, 47, 373, 47, 47, 47, 47, 374, 47, 363, 375, 47, 60, 376, 66, 47, + 377, 66, 66, 47, 378, 145, 47, 47, 379, 47, 47, 361, 380, 381, 382, 383, + 180, 47, 47, 384, 385, 47, 47, 160, 97, 47, 386, 387, 388, 47, 47, 389, + 180, 47, 47, 390, 391, 392, 393, 145, 47, 47, 394, 395, 360, 32, 32, 32, + 47, 47, 366, 47, 47, 396, 172, 160, 92, 47, 47, 113, 397, 398, 399, 32, + 47, 47, 47, 400, 401, 402, 403, 32, 47, 47, 47, 404, 405, 406, 47, 47, + 47, 47, 47, 407, 408, 160, 160, 160, 47, 47, 409, 410, 411, 412, 32, 32, + 47, 47, 47, 413, 414, 160, 66, 66, 47, 47, 415, 416, 160, 160, 160, 160, + 47, 417, 418, 419, 47, 47, 47, 47, 47, 47, 394, 420, 66, 66, 66, 66, + 9, 9, 9, 9, 11, 11, 128, 421, 47, 47, 47, 422, 423, 160, 160, 160, + 47, 47, 47, 47, 47, 424, 425, 426, 427, 47, 47, 428, 429, 430, 47, 47, + 431, 432, 66, 47, 47, 47, 47, 47, 66, 66, 66, 66, 66, 66, 66, 66, + 47, 47, 47, 47, 47, 47, 433, 160, 47, 47, 409, 434, 433, 128, 145, 435, + 47, 156, 436, 437, 32, 32, 32, 32, 47, 47, 47, 360, 438, 160, 47, 47, + 439, 440, 160, 160, 160, 160, 160, 160, 47, 47, 47, 47, 47, 47, 47, 441, + 442, 47, 47, 443, 444, 445, 32, 32, 47, 47, 47, 47, 145, 446, 447, 448, + 220, 220, 220, 220, 220, 220, 220, 66, 47, 47, 47, 47, 47, 47, 47, 433, + 47, 47, 47, 209, 449, 32, 47, 47, 47, 450, 451, 160, 160, 160, 160, 160, + 47, 47, 47, 47, 47, 47, 306, 47, 47, 47, 47, 47, 160, 47, 47, 452, + 47, 47, 47, 453, 454, 455, 456, 47, 27, 27, 27, 27, 457, 47, 458, 160, + 9, 9, 9, 9, 9, 9, 11, 11, 145, 459, 66, 66, 66, 66, 66, 66, + 47, 47, 47, 47, 396, 460, 426, 426, 461, 462, 27, 27, 27, 27, 463, 426, + 47, 464, 209, 209, 209, 209, 209, 209, 146, 146, 146, 146, 146, 146, 146, 160, + 32, 32, 32, 32, 32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 465, 466, + 467, 146, 468, 146, 146, 146, 146, 146, 146, 146, 146, 146, 469, 146, 146, 146, + 9, 470, 11, 471, 472, 11, 197, 9, 473, 474, 9, 475, 11, 9, 470, 11, + 471, 472, 11, 197, 9, 473, 474, 9, 475, 11, 9, 470, 11, 471, 472, 11, + 197, 9, 473, 474, 9, 475, 11, 9, 470, 11, 197, 9, 476, 477, 478, 479, + 11, 480, 9, 481, 482, 483, 484, 11, 485, 9, 486, 11, 487, 160, 160, 160, + 32, 32, 32, 488, 32, 32, 489, 490, 491, 492, 32, 32, 32, 32, 32, 32, + 493, 11, 11, 11, 11, 11, 11, 11, 32, 32, 32, 27, 27, 27, 27, 27, + 32, 32, 32, 32, 32, 32, 32, 32, 47, 47, 47, 494, 495, 146, 146, 146, + 47, 47, 450, 32, 47, 47, 374, 496, 47, 47, 47, 47, 47, 47, 497, 160, + 47, 47, 47, 47, 47, 47, 450, 498, 47, 47, 47, 47, 356, 32, 32, 32, + 9, 9, 473, 11, 499, 306, 66, 66, 145, 145, 500, 501, 145, 145, 145, 145, + 145, 145, 502, 145, 145, 145, 145, 145, 47, 47, 47, 47, 47, 47, 47, 227, + 503, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 504, + 209, 209, 209, 209, 209, 209, 209, 209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,1124,1125,1126,1127,1131,1133, 0,1147, @@ -5541,16 +5778,23 @@ _hb_ucd_u16[4920] = 0, 0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584, 0, 1585,1587,1588,1589,1591, 0,1592, 0,1593,1594, 0,1595,1596, 0,1598,1599, 1600,1601,1604,1582,1578,1590,1597, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1936, 0,1937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1938, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1939,1940, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1941,1942, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1944,1943, 0,1945, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,1946,1947, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,1949,1950,1951,1952,1953,1954,1955, 0, 0, 0, + 0,1936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1937, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1938, 0,1939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1940, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1943,1944, 0, 0, 0, 0, 0, 0,1945, 0,1946, 0, 0, + 0, 0, 0, 0, 0, 0,1947, 0, 0,1948, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1950, 0,1949, + 1951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1953,1952, 0,1954, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1955,1956, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1957, 0, 0, 0, 0, 0, 0, 0, 0,1958,1961,1959,1965,1960,1962,1964, + 1963, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1967,1966,1968, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1969,1970,1971,1972,1973,1974,1975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,1956,1957,1958,1960,1959,1961, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1976,1977,1978,1980,1979,1981, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, 157, 158, 159, 160, 38, 165, 166, 169, @@ -5601,12 +5845,12 @@ _hb_ucd_i16[92] = static inline uint_fast8_t _hb_ucd_gc (unsigned u) { - return u<1114112u?_hb_ucd_u8[5096+(((_hb_ucd_u8[1168+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; + return u<1114112u?_hb_ucd_u8[5208+(((_hb_ucd_u8[1168+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; } static inline uint_fast8_t _hb_ucd_ccc (unsigned u) { - return u<125259u?_hb_ucd_u8[7054+(((_hb_ucd_u8[6498+(((_hb_ucd_u8[6038+(((_hb_ucd_u8[5686+(((_hb_ucd_u8[5440+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; + return u<125259u?_hb_ucd_u8[7206+(((_hb_ucd_u8[6638+(((_hb_ucd_u8[6162+(((_hb_ucd_u8[5802+(((_hb_ucd_u8[5556+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; } static inline unsigned _hb_ucd_b4 (const uint8_t* a, unsigned i) @@ -5616,17 +5860,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i) static inline int_fast16_t _hb_ucd_bmg (unsigned u) { - return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7946+(((_hb_ucd_u8[7714+(((_hb_ucd_u8[7618+(((_hb_ucd_b4(7554+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0; + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[8098+(((_hb_ucd_u8[7866+(((_hb_ucd_u8[7770+(((_hb_ucd_b4(7706+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0; } static inline uint_fast8_t _hb_ucd_sc (unsigned u) { - return u<918016u?_hb_ucd_u8[11244+(((_hb_ucd_u8[10280+(((_hb_ucd_u8[9292+(((_hb_ucd_u8[8612+(((_hb_ucd_u8[8308+(((_hb_ucd_u8[8194+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; + return u<918016u?_hb_ucd_u8[11464+(((_hb_ucd_u8[10472+(((_hb_ucd_u8[9452+(((_hb_ucd_u8[8764+(((_hb_ucd_u8[8460+(((_hb_ucd_u8[8346+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; } static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[1608+(((_hb_ucd_u8[12586+(((_hb_ucd_u8[12204+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[1656+(((_hb_ucd_u8[12834+(((_hb_ucd_u8[12452+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0; } #endif diff --git a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh index e607e8ca82..4bc8d64c28 100644 --- a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh +++ b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh @@ -7,13 +7,13 @@ * on file with this header: * * # emoji-data.txt - * # Date: 2023-02-01, 02:22:54 GMT - * # © 2023 Unicode®, Inc. + * # Date: 2024-05-01, 21:25:24 GMT + * # © 2024 Unicode®, Inc. * # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. - * # For terms of use, see https://www.unicode.org/terms_of_use.html + * # For terms of use and license, see https://www.unicode.org/terms_of_use.html * # * # Emoji Data for UTS #51 - * # Used with Emoji Version 15.1 and subsequent minor revisions (if any) + * # Used with Emoji Version 16.0 and subsequent minor revisions (if any) * # * # For documentation and usage, see https://www.unicode.org/reports/tr51 */ diff --git a/thirdparty/harfbuzz/src/hb-unicode.hh b/thirdparty/harfbuzz/src/hb-unicode.hh index 39aaee5baa..2b1921c28f 100644 --- a/thirdparty/harfbuzz/src/hb-unicode.hh +++ b/thirdparty/harfbuzz/src/hb-unicode.hh @@ -34,6 +34,9 @@ #include "hb.hh" +// Hack. See: https://github.com/harfbuzz/harfbuzz/pull/4529#discussion_r1769638033 +#define _HB_UNICODE_GENERAL_CATEGORY_VARIATION_SELECTOR ((hb_unicode_general_category_t) 30) + extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256]; /* diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index abffbdae9c..404c515d24 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -41,26 +41,26 @@ HB_BEGIN_DECLS * * The major component of the library version available at compile-time. */ -#define HB_VERSION_MAJOR 8 +#define HB_VERSION_MAJOR 10 /** * HB_VERSION_MINOR: * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 5 +#define HB_VERSION_MINOR 0 /** * HB_VERSION_MICRO: * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 0 +#define HB_VERSION_MICRO 1 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "8.5.0" +#define HB_VERSION_STRING "10.0.1" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh index 0ceeb99f50..fe466fe1f8 100644 --- a/thirdparty/harfbuzz/src/hb.hh +++ b/thirdparty/harfbuzz/src/hb.hh @@ -84,6 +84,7 @@ #pragma GCC diagnostic error "-Wredundant-decls" #pragma GCC diagnostic error "-Wreorder" #pragma GCC diagnostic error "-Wsign-compare" +#pragma GCC diagnostic error "-Wstrict-flex-arrays" #pragma GCC diagnostic error "-Wstrict-prototypes" #pragma GCC diagnostic error "-Wstring-conversion" #pragma GCC diagnostic error "-Wswitch-enum" diff --git a/thirdparty/mbedtls/include/godot_module_mbedtls_config.h b/thirdparty/mbedtls/include/godot_module_mbedtls_config.h index 2011827b7a..58bf1d9d54 100644 --- a/thirdparty/mbedtls/include/godot_module_mbedtls_config.h +++ b/thirdparty/mbedtls/include/godot_module_mbedtls_config.h @@ -59,18 +59,6 @@ // Disable deprecated #define MBEDTLS_DEPRECATED_REMOVED -// mbedTLS 3.6 finally enabled TLSv1.3 by default, but it requires some mobule -// changes, and to enable PSA crypto (new "standard" API specification). -// Disable it for now. -#undef MBEDTLS_SSL_PROTO_TLS1_3 - -// Disable PSA Crypto. -#undef MBEDTLS_PSA_CRYPTO_CONFIG -#undef MBEDTLS_PSA_CRYPTO_C -#undef MBEDTLS_PSA_CRYPTO_STORAGE_C -#undef MBEDTLS_PSA_ITS_FILE_C -#undef MBEDTLS_LMS_C - #endif // GODOT_MBEDTLS_INCLUDE_H #endif // GODOT_MODULE_MBEDTLS_CONFIG_H diff --git a/thirdparty/mbedtls/library/psa_crypto.c b/thirdparty/mbedtls/library/psa_crypto.c new file mode 100644 index 0000000000..c4f41db10b --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto.c @@ -0,0 +1,9233 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" +#include "psa_crypto_core_common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#include "check_crypto_config.h" +#endif + +#include "psa/crypto.h" +#include "psa/crypto_values.h" + +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_invasive.h" +#include "psa_crypto_driver_wrappers.h" +#include "psa_crypto_driver_wrappers_no_static.h" +#include "psa_crypto_ecp.h" +#include "psa_crypto_ffdh.h" +#include "psa_crypto_hash.h" +#include "psa_crypto_mac.h" +#include "psa_crypto_rsa.h" +#include "psa_crypto_ecp.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif +#include "psa_crypto_slot_management.h" +/* Include internal declarations that are useful for implementing persistently + * stored keys. */ +#include "psa_crypto_storage.h" + +#include "psa_crypto_random_impl.h" + +#include <stdlib.h> +#include <string.h> +#include "mbedtls/platform.h" + +#include "mbedtls/aes.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/bignum.h" +#include "mbedtls/camellia.h" +#include "mbedtls/chacha20.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/ccm.h" +#include "mbedtls/cmac.h" +#include "mbedtls/constant_time.h" +#include "mbedtls/des.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" +#include "mbedtls/md5.h" +#include "mbedtls/pk.h" +#include "pk_wrap.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/psa_util.h" +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) +#define BUILTIN_ALG_ANY_HKDF 1 +#endif + +/****************************************************************/ +/* Global data, support functions and library management */ +/****************************************************************/ + +static int key_type_is_raw_bytes(psa_key_type_t type) +{ + return PSA_KEY_TYPE_IS_UNSTRUCTURED(type); +} + +/* Values for psa_global_data_t::rng_state */ +#define RNG_NOT_INITIALIZED 0 +#define RNG_INITIALIZED 1 +#define RNG_SEEDED 2 + +/* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized + * variables as arguments. */ +typedef enum { + PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1, + PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS, + PSA_CRYPTO_SUBSYSTEM_RNG, + PSA_CRYPTO_SUBSYSTEM_TRANSACTION, +} mbedtls_psa_crypto_subsystem; + +/* Initialization flags for global_data::initialized */ +#define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED 0x01 +#define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED 0x02 +#define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED 0x04 + +#define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED ( \ + PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \ + PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \ + PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) + +typedef struct { + uint8_t initialized; + uint8_t rng_state; + mbedtls_psa_random_context_t rng; +} psa_global_data_t; + +static psa_global_data_t global_data; + +static uint8_t psa_get_initialized(void) +{ + uint8_t initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = global_data.rng_state == RNG_SEEDED; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = + (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED)); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + return initialized; +} + +static uint8_t psa_get_drivers_initialized(void) +{ + uint8_t initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + return initialized; +} + +#define GUARD_MODULE_INITIALIZED \ + if (psa_get_initialized() == 0) \ + return PSA_ERROR_BAD_STATE; + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + +/* Declare a local copy of an input buffer and a variable that will be used + * to store a pointer to the start of the buffer. + * + * Note: This macro must be called before any operations which may jump to + * the exit label, so that the local input copy object is safe to be freed. + * + * Assumptions: + * - input is the name of a pointer to the buffer to be copied + * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope + * - input_copy_name is a name that is unused in the current scope + */ +#define LOCAL_INPUT_DECLARE(input, input_copy_name) \ + psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \ + const uint8_t *input_copy_name = NULL; + +/* Allocate a copy of the buffer input and set the pointer input_copy to + * point to the start of the copy. + * + * Assumptions: + * - psa_status_t status exists + * - An exit label is declared + * - input is the name of a pointer to the buffer to be copied + * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called + */ +#define LOCAL_INPUT_ALLOC(input, length, input_copy) \ + status = psa_crypto_local_input_alloc(input, length, \ + &LOCAL_INPUT_COPY_OF_##input); \ + if (status != PSA_SUCCESS) { \ + goto exit; \ + } \ + input_copy = LOCAL_INPUT_COPY_OF_##input.buffer; + +/* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC() + * + * Assumptions: + * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC() + * - input is the name of the original buffer that was copied + */ +#define LOCAL_INPUT_FREE(input, input_copy) \ + input_copy = NULL; \ + psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input); + +/* Declare a local copy of an output buffer and a variable that will be used + * to store a pointer to the start of the buffer. + * + * Note: This macro must be called before any operations which may jump to + * the exit label, so that the local output copy object is safe to be freed. + * + * Assumptions: + * - output is the name of a pointer to the buffer to be copied + * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope + * - output_copy_name is a name that is unused in the current scope + */ +#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ + psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \ + uint8_t *output_copy_name = NULL; + +/* Allocate a copy of the buffer output and set the pointer output_copy to + * point to the start of the copy. + * + * Assumptions: + * - psa_status_t status exists + * - An exit label is declared + * - output is the name of a pointer to the buffer to be copied + * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called + */ +#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ + status = psa_crypto_local_output_alloc(output, length, \ + &LOCAL_OUTPUT_COPY_OF_##output); \ + if (status != PSA_SUCCESS) { \ + goto exit; \ + } \ + output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer; + +/* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC() + * after first copying back its contents to the original buffer. + * + * Assumptions: + * - psa_status_t status exists + * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC() + * - output is the name of the original buffer that was copied + */ +#define LOCAL_OUTPUT_FREE(output, output_copy) \ + output_copy = NULL; \ + do { \ + psa_status_t local_output_status; \ + local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \ + if (local_output_status != PSA_SUCCESS) { \ + /* Since this error case is an internal error, it's more serious than \ + * any existing error code and so it's fine to overwrite the existing \ + * status. */ \ + status = local_output_status; \ + } \ + } while (0) +#else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ +#define LOCAL_INPUT_DECLARE(input, input_copy_name) \ + const uint8_t *input_copy_name = NULL; +#define LOCAL_INPUT_ALLOC(input, length, input_copy) \ + input_copy = input; +#define LOCAL_INPUT_FREE(input, input_copy) \ + input_copy = NULL; +#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ + uint8_t *output_copy_name = NULL; +#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ + output_copy = output; +#define LOCAL_OUTPUT_FREE(output, output_copy) \ + output_copy = NULL; +#endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ + + +int psa_can_do_hash(psa_algorithm_t hash_alg) +{ + (void) hash_alg; + return psa_get_drivers_initialized(); +} + +int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg) +{ + (void) key_type; + (void) cipher_alg; + return psa_get_drivers_initialized(); +} + + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) +static int psa_is_dh_key_size_valid(size_t bits) +{ + switch (bits) { +#if defined(PSA_WANT_DH_RFC7919_2048) + case 2048: + return 1; +#endif /* PSA_WANT_DH_RFC7919_2048 */ +#if defined(PSA_WANT_DH_RFC7919_3072) + case 3072: + return 1; +#endif /* PSA_WANT_DH_RFC7919_3072 */ +#if defined(PSA_WANT_DH_RFC7919_4096) + case 4096: + return 1; +#endif /* PSA_WANT_DH_RFC7919_4096 */ +#if defined(PSA_WANT_DH_RFC7919_6144) + case 6144: + return 1; +#endif /* PSA_WANT_DH_RFC7919_6144 */ +#if defined(PSA_WANT_DH_RFC7919_8192) + case 8192: + return 1; +#endif /* PSA_WANT_DH_RFC7919_8192 */ + default: + return 0; + } +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || + PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */ + +psa_status_t mbedtls_to_psa_error(int ret) +{ + /* Mbed TLS error codes can combine a high-level error code and a + * low-level error code. The low-level error usually reflects the + * root cause better, so dispatch on that preferably. */ + int low_level_ret = -(-ret & 0x007f); + switch (low_level_ret != 0 ? low_level_ret : ret) { + case 0: + return PSA_SUCCESS; + +#if defined(MBEDTLS_AES_C) + case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: + case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_AES_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_ASN1_WRITE_C) + case MBEDTLS_ERR_ASN1_OUT_OF_DATA: + case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: + case MBEDTLS_ERR_ASN1_INVALID_LENGTH: + case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: + case MBEDTLS_ERR_ASN1_INVALID_DATA: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_ASN1_ALLOC_FAILED: + return PSA_ERROR_INSUFFICIENT_MEMORY; + case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: + case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: + return PSA_ERROR_NOT_SUPPORTED; +#endif + +#if defined(MBEDTLS_CCM_C) + case MBEDTLS_ERR_CCM_BAD_INPUT: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_CCM_AUTH_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; +#endif + +#if defined(MBEDTLS_CHACHA20_C) + case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: + return PSA_ERROR_BAD_STATE; + case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; +#endif + +#if defined(MBEDTLS_CIPHER_C) + case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: + return PSA_ERROR_INSUFFICIENT_MEMORY; + case MBEDTLS_ERR_CIPHER_INVALID_PADDING: + return PSA_ERROR_INVALID_PADDING; + case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_CIPHER_AUTH_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; + case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: + return PSA_ERROR_CORRUPTION_DETECTED; +#endif + +#if !(defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) || \ + defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)) + /* Only check CTR_DRBG error codes if underlying mbedtls_xxx + * functions are passed a CTR_DRBG instance. */ + case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: + return PSA_ERROR_INSUFFICIENT_ENTROPY; + case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: + case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR: + return PSA_ERROR_INSUFFICIENT_ENTROPY; +#endif + +#if defined(MBEDTLS_DES_C) + case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: + return PSA_ERROR_NOT_SUPPORTED; +#endif + + case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: + case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: + case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: + return PSA_ERROR_INSUFFICIENT_ENTROPY; + +#if defined(MBEDTLS_GCM_C) + case MBEDTLS_ERR_GCM_AUTH_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; + case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; + case MBEDTLS_ERR_GCM_BAD_INPUT: + return PSA_ERROR_INVALID_ARGUMENT; +#endif + +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \ + defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) + /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx + * functions are passed a HMAC_DRBG instance. */ + case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED: + return PSA_ERROR_INSUFFICIENT_ENTROPY; + case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG: + case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR: + return PSA_ERROR_INSUFFICIENT_ENTROPY; +#endif + +#if defined(MBEDTLS_MD_LIGHT) + case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_MD_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_MD_ALLOC_FAILED: + return PSA_ERROR_INSUFFICIENT_MEMORY; +#if defined(MBEDTLS_FS_IO) + case MBEDTLS_ERR_MD_FILE_IO_ERROR: + return PSA_ERROR_STORAGE_FAILURE; +#endif +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#if defined(MBEDTLS_FS_IO) + case MBEDTLS_ERR_MPI_FILE_IO_ERROR: + return PSA_ERROR_STORAGE_FAILURE; +#endif + case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_MPI_INVALID_CHARACTER: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; + case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_MPI_ALLOC_FAILED: + return PSA_ERROR_INSUFFICIENT_MEMORY; +#endif + +#if defined(MBEDTLS_PK_C) + case MBEDTLS_ERR_PK_ALLOC_FAILED: + return PSA_ERROR_INSUFFICIENT_MEMORY; + case MBEDTLS_ERR_PK_TYPE_MISMATCH: + case MBEDTLS_ERR_PK_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || defined(MBEDTLS_FS_IO) || \ + defined(MBEDTLS_PSA_ITS_FILE_C) + case MBEDTLS_ERR_PK_FILE_IO_ERROR: + return PSA_ERROR_STORAGE_FAILURE; +#endif + case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: + case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: + case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: + return PSA_ERROR_NOT_PERMITTED; + case MBEDTLS_ERR_PK_INVALID_PUBKEY: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_PK_INVALID_ALG: + case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: + case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: + return PSA_ERROR_INVALID_SIGNATURE; + case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; +#endif + + case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: + return PSA_ERROR_HARDWARE_FAILURE; + case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: + return PSA_ERROR_NOT_SUPPORTED; + +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_RSA_INVALID_PADDING: + return PSA_ERROR_INVALID_PADDING; + case MBEDTLS_ERR_RSA_KEY_GEN_FAILED: + return PSA_ERROR_HARDWARE_FAILURE; + case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_RSA_PUBLIC_FAILED: + case MBEDTLS_ERR_RSA_PRIVATE_FAILED: + return PSA_ERROR_CORRUPTION_DETECTED; + case MBEDTLS_ERR_RSA_VERIFY_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; + case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: + return PSA_ERROR_BUFFER_TOO_SMALL; + case MBEDTLS_ERR_RSA_RNG_FAILED: + return PSA_ERROR_INSUFFICIENT_ENTROPY; +#endif + +#if defined(MBEDTLS_ECP_LIGHT) + case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_INVALID_KEY: + return PSA_ERROR_INVALID_ARGUMENT; + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; + case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH: + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; + case MBEDTLS_ERR_ECP_ALLOC_FAILED: + return PSA_ERROR_INSUFFICIENT_MEMORY; + case MBEDTLS_ERR_ECP_RANDOM_FAILED: + return PSA_ERROR_INSUFFICIENT_ENTROPY; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + case MBEDTLS_ERR_ECP_IN_PROGRESS: + return PSA_OPERATION_INCOMPLETE; +#endif +#endif + + case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: + return PSA_ERROR_CORRUPTION_DETECTED; + + default: + return PSA_ERROR_GENERIC_ERROR; + } +} + +/** + * \brief For output buffers which contain "tags" + * (outputs that may be checked for validity like + * hashes, MACs and signatures), fill the unused + * part of the output buffer (the whole buffer on + * error, the trailing part on success) with + * something that isn't a valid tag (barring an + * attack on the tag and deliberately-crafted + * input), in case the caller doesn't check the + * return status properly. + * + * \param output_buffer Pointer to buffer to wipe. May not be NULL + * unless \p output_buffer_size is zero. + * \param status Status of function called to generate + * output_buffer originally + * \param output_buffer_size Size of output buffer. If zero, \p output_buffer + * could be NULL. + * \param output_buffer_length Length of data written to output_buffer, must be + * less than \p output_buffer_size + */ +static void psa_wipe_tag_output_buffer(uint8_t *output_buffer, psa_status_t status, + size_t output_buffer_size, size_t output_buffer_length) +{ + size_t offset = 0; + + if (output_buffer_size == 0) { + /* If output_buffer_size is 0 then we have nothing to do. We must not + call memset because output_buffer may be NULL in this case */ + return; + } + + if (status == PSA_SUCCESS) { + offset = output_buffer_length; + } + + memset(output_buffer + offset, '!', output_buffer_size - offset); +} + + +psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type, + size_t bits) +{ + /* Check that the bit size is acceptable for the key type */ + switch (type) { + case PSA_KEY_TYPE_RAW_DATA: + case PSA_KEY_TYPE_HMAC: + case PSA_KEY_TYPE_DERIVE: + case PSA_KEY_TYPE_PASSWORD: + case PSA_KEY_TYPE_PASSWORD_HASH: + break; +#if defined(PSA_WANT_KEY_TYPE_AES) + case PSA_KEY_TYPE_AES: + if (bits != 128 && bits != 192 && bits != 256) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_ARIA) + case PSA_KEY_TYPE_ARIA: + if (bits != 128 && bits != 192 && bits != 256) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_CAMELLIA) + case PSA_KEY_TYPE_CAMELLIA: + if (bits != 128 && bits != 192 && bits != 256) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_DES) + case PSA_KEY_TYPE_DES: + if (bits != 64 && bits != 128 && bits != 192) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) + case PSA_KEY_TYPE_CHACHA20: + if (bits != 256) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif + default: + return PSA_ERROR_NOT_SUPPORTED; + } + if (bits % 8 != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + +/** Check whether a given key type is valid for use with a given MAC algorithm + * + * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH + * when called with the validated \p algorithm and \p key_type is well-defined. + * + * \param[in] algorithm The specific MAC algorithm (can be wildcard). + * \param[in] key_type The key type of the key to be used with the + * \p algorithm. + * + * \retval #PSA_SUCCESS + * The \p key_type is valid for use with the \p algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The \p key_type is not valid for use with the \p algorithm + */ +MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do( + psa_algorithm_t algorithm, + psa_key_type_t key_type) +{ + if (PSA_ALG_IS_HMAC(algorithm)) { + if (key_type == PSA_KEY_TYPE_HMAC) { + return PSA_SUCCESS; + } + } + + if (PSA_ALG_IS_BLOCK_CIPHER_MAC(algorithm)) { + /* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher + * key. */ + if ((key_type & PSA_KEY_TYPE_CATEGORY_MASK) == + PSA_KEY_TYPE_CATEGORY_SYMMETRIC) { + /* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and + * the block length (larger than 1) for block ciphers. */ + if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1) { + return PSA_SUCCESS; + } + } + } + + return PSA_ERROR_INVALID_ARGUMENT; +} + +psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot, + size_t buffer_length) +{ + if (slot->key.data != NULL) { + return PSA_ERROR_ALREADY_EXISTS; + } + + slot->key.data = mbedtls_calloc(1, buffer_length); + if (slot->key.data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + slot->key.bytes = buffer_length; + return PSA_SUCCESS; +} + +psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status = psa_allocate_buffer_to_slot(slot, + data_length); + if (status != PSA_SUCCESS) { + return status; + } + + memcpy(slot->key.data, data, data_length); + return PSA_SUCCESS; +} + +psa_status_t psa_import_key_into_slot( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = attributes->type; + + /* zero-length keys are never supported. */ + if (data_length == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (key_type_is_raw_bytes(type)) { + *bits = PSA_BYTES_TO_BITS(data_length); + + status = psa_validate_unstructured_key_bit_size(attributes->type, + *bits); + if (status != PSA_SUCCESS) { + return status; + } + + /* Copy the key material. */ + memcpy(key_buffer, data, data_length); + *key_buffer_length = data_length; + (void) key_buffer_size; + + return PSA_SUCCESS; + } else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) + if (PSA_KEY_TYPE_IS_DH(type)) { + if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + return mbedtls_psa_ffdh_import_key(attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits); + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + if (PSA_KEY_TYPE_IS_ECC(type)) { + return mbedtls_psa_ecp_import_key(attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits); + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ +#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + if (PSA_KEY_TYPE_IS_RSA(type)) { + return mbedtls_psa_rsa_import_key(attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits); + } +#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + } + + return PSA_ERROR_NOT_SUPPORTED; +} + +/** Calculate the intersection of two algorithm usage policies. + * + * Return 0 (which allows no operation) on incompatibility. + */ +static psa_algorithm_t psa_key_policy_algorithm_intersection( + psa_key_type_t key_type, + psa_algorithm_t alg1, + psa_algorithm_t alg2) +{ + /* Common case: both sides actually specify the same policy. */ + if (alg1 == alg2) { + return alg1; + } + /* If the policies are from the same hash-and-sign family, check + * if one is a wildcard. If so the other has the specific algorithm. */ + if (PSA_ALG_IS_SIGN_HASH(alg1) && + PSA_ALG_IS_SIGN_HASH(alg2) && + (alg1 & ~PSA_ALG_HASH_MASK) == (alg2 & ~PSA_ALG_HASH_MASK)) { + if (PSA_ALG_SIGN_GET_HASH(alg1) == PSA_ALG_ANY_HASH) { + return alg2; + } + if (PSA_ALG_SIGN_GET_HASH(alg2) == PSA_ALG_ANY_HASH) { + return alg1; + } + } + /* If the policies are from the same AEAD family, check whether + * one of them is a minimum-tag-length wildcard. Calculate the most + * restrictive tag length. */ + if (PSA_ALG_IS_AEAD(alg1) && PSA_ALG_IS_AEAD(alg2) && + (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg1, 0) == + PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg2, 0))) { + size_t alg1_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg1); + size_t alg2_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg2); + size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; + + /* If both are wildcards, return most restrictive wildcard */ + if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && + ((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { + return PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( + alg1, restricted_len); + } + /* If only one is a wildcard, return specific algorithm if compatible. */ + if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && + (alg1_len <= alg2_len)) { + return alg2; + } + if (((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && + (alg2_len <= alg1_len)) { + return alg1; + } + } + /* If the policies are from the same MAC family, check whether one + * of them is a minimum-MAC-length policy. Calculate the most + * restrictive tag length. */ + if (PSA_ALG_IS_MAC(alg1) && PSA_ALG_IS_MAC(alg2) && + (PSA_ALG_FULL_LENGTH_MAC(alg1) == + PSA_ALG_FULL_LENGTH_MAC(alg2))) { + /* Validate the combination of key type and algorithm. Since the base + * algorithm of alg1 and alg2 are the same, we only need this once. */ + if (PSA_SUCCESS != psa_mac_key_can_do(alg1, key_type)) { + return 0; + } + + /* Get the (exact or at-least) output lengths for both sides of the + * requested intersection. None of the currently supported algorithms + * have an output length dependent on the actual key size, so setting it + * to a bogus value of 0 is currently OK. + * + * Note that for at-least-this-length wildcard algorithms, the output + * length is set to the shortest allowed length, which allows us to + * calculate the most restrictive tag length for the intersection. */ + size_t alg1_len = PSA_MAC_LENGTH(key_type, 0, alg1); + size_t alg2_len = PSA_MAC_LENGTH(key_type, 0, alg2); + size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; + + /* If both are wildcards, return most restrictive wildcard */ + if (((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) && + ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { + return PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg1, restricted_len); + } + + /* If only one is an at-least-this-length policy, the intersection would + * be the other (fixed-length) policy as long as said fixed length is + * equal to or larger than the shortest allowed length. */ + if ((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { + return (alg1_len <= alg2_len) ? alg2 : 0; + } + if ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { + return (alg2_len <= alg1_len) ? alg1 : 0; + } + + /* If none of them are wildcards, check whether they define the same tag + * length. This is still possible here when one is default-length and + * the other specific-length. Ensure to always return the + * specific-length version for the intersection. */ + if (alg1_len == alg2_len) { + return PSA_ALG_TRUNCATED_MAC(alg1, alg1_len); + } + } + /* If the policies are incompatible, allow nothing. */ + return 0; +} + +static int psa_key_algorithm_permits(psa_key_type_t key_type, + psa_algorithm_t policy_alg, + psa_algorithm_t requested_alg) +{ + /* Common case: the policy only allows requested_alg. */ + if (requested_alg == policy_alg) { + return 1; + } + /* If policy_alg is a hash-and-sign with a wildcard for the hash, + * and requested_alg is the same hash-and-sign family with any hash, + * then requested_alg is compliant with policy_alg. */ + if (PSA_ALG_IS_SIGN_HASH(requested_alg) && + PSA_ALG_SIGN_GET_HASH(policy_alg) == PSA_ALG_ANY_HASH) { + return (policy_alg & ~PSA_ALG_HASH_MASK) == + (requested_alg & ~PSA_ALG_HASH_MASK); + } + /* If policy_alg is a wildcard AEAD algorithm of the same base as + * the requested algorithm, check the requested tag length to be + * equal-length or longer than the wildcard-specified length. */ + if (PSA_ALG_IS_AEAD(policy_alg) && + PSA_ALG_IS_AEAD(requested_alg) && + (PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, 0) == + PSA_ALG_AEAD_WITH_SHORTENED_TAG(requested_alg, 0)) && + ((policy_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { + return PSA_ALG_AEAD_GET_TAG_LENGTH(policy_alg) <= + PSA_ALG_AEAD_GET_TAG_LENGTH(requested_alg); + } + /* If policy_alg is a MAC algorithm of the same base as the requested + * algorithm, check whether their MAC lengths are compatible. */ + if (PSA_ALG_IS_MAC(policy_alg) && + PSA_ALG_IS_MAC(requested_alg) && + (PSA_ALG_FULL_LENGTH_MAC(policy_alg) == + PSA_ALG_FULL_LENGTH_MAC(requested_alg))) { + /* Validate the combination of key type and algorithm. Since the policy + * and requested algorithms are the same, we only need this once. */ + if (PSA_SUCCESS != psa_mac_key_can_do(policy_alg, key_type)) { + return 0; + } + + /* Get both the requested output length for the algorithm which is to be + * verified, and the default output length for the base algorithm. + * Note that none of the currently supported algorithms have an output + * length dependent on actual key size, so setting it to a bogus value + * of 0 is currently OK. */ + size_t requested_output_length = PSA_MAC_LENGTH( + key_type, 0, requested_alg); + size_t default_output_length = PSA_MAC_LENGTH( + key_type, 0, + PSA_ALG_FULL_LENGTH_MAC(requested_alg)); + + /* If the policy is default-length, only allow an algorithm with + * a declared exact-length matching the default. */ + if (PSA_MAC_TRUNCATED_LENGTH(policy_alg) == 0) { + return requested_output_length == default_output_length; + } + + /* If the requested algorithm is default-length, allow it if the policy + * length exactly matches the default length. */ + if (PSA_MAC_TRUNCATED_LENGTH(requested_alg) == 0 && + PSA_MAC_TRUNCATED_LENGTH(policy_alg) == default_output_length) { + return 1; + } + + /* If policy_alg is an at-least-this-length wildcard MAC algorithm, + * check for the requested MAC length to be equal to or longer than the + * minimum allowed length. */ + if ((policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { + return PSA_MAC_TRUNCATED_LENGTH(policy_alg) <= + requested_output_length; + } + } + /* If policy_alg is a generic key agreement operation, then using it for + * a key derivation with that key agreement should also be allowed. This + * behaviour is expected to be defined in a future specification version. */ + if (PSA_ALG_IS_RAW_KEY_AGREEMENT(policy_alg) && + PSA_ALG_IS_KEY_AGREEMENT(requested_alg)) { + return PSA_ALG_KEY_AGREEMENT_GET_BASE(requested_alg) == + policy_alg; + } + /* If it isn't explicitly permitted, it's forbidden. */ + return 0; +} + +/** Test whether a policy permits an algorithm. + * + * The caller must test usage flags separately. + * + * \note This function requires providing the key type for which the policy is + * being validated, since some algorithm policy definitions (e.g. MAC) + * have different properties depending on what kind of cipher it is + * combined with. + * + * \retval PSA_SUCCESS When \p alg is a specific algorithm + * allowed by the \p policy. + * \retval PSA_ERROR_INVALID_ARGUMENT When \p alg is not a specific algorithm + * \retval PSA_ERROR_NOT_PERMITTED When \p alg is a specific algorithm, but + * the \p policy does not allow it. + */ +static psa_status_t psa_key_policy_permits(const psa_key_policy_t *policy, + psa_key_type_t key_type, + psa_algorithm_t alg) +{ + /* '0' is not a valid algorithm */ + if (alg == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* A requested algorithm cannot be a wildcard. */ + if (PSA_ALG_IS_WILDCARD(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (psa_key_algorithm_permits(key_type, policy->alg, alg) || + psa_key_algorithm_permits(key_type, policy->alg2, alg)) { + return PSA_SUCCESS; + } else { + return PSA_ERROR_NOT_PERMITTED; + } +} + +/** Restrict a key policy based on a constraint. + * + * \note This function requires providing the key type for which the policy is + * being restricted, since some algorithm policy definitions (e.g. MAC) + * have different properties depending on what kind of cipher it is + * combined with. + * + * \param[in] key_type The key type for which to restrict the policy + * \param[in,out] policy The policy to restrict. + * \param[in] constraint The policy constraint to apply. + * + * \retval #PSA_SUCCESS + * \c *policy contains the intersection of the original value of + * \c *policy and \c *constraint. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key_type, \c *policy and \c *constraint are incompatible. + * \c *policy is unchanged. + */ +static psa_status_t psa_restrict_key_policy( + psa_key_type_t key_type, + psa_key_policy_t *policy, + const psa_key_policy_t *constraint) +{ + psa_algorithm_t intersection_alg = + psa_key_policy_algorithm_intersection(key_type, policy->alg, + constraint->alg); + psa_algorithm_t intersection_alg2 = + psa_key_policy_algorithm_intersection(key_type, policy->alg2, + constraint->alg2); + if (intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + policy->usage &= constraint->usage; + policy->alg = intersection_alg; + policy->alg2 = intersection_alg2; + return PSA_SUCCESS; +} + +/** Get the description of a key given its identifier and policy constraints + * and lock it. + * + * The key must have allow all the usage flags set in \p usage. If \p alg is + * nonzero, the key must allow operations with this algorithm. If \p alg is + * zero, the algorithm is not checked. + * + * In case of a persistent key, the function loads the description of the key + * into a key slot if not already done. + * + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to then unregister + * once they have finished reading the contents of the slot. + * The caller unregisters by calling psa_unregister_read() or + * psa_unregister_read_under_mutex(). psa_unregister_read() must be called + * if and only if the caller already holds the global key slot mutex + * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates + * the unregister with mutex lock and unlock operations. + */ +static psa_status_t psa_get_and_lock_key_slot_with_policy( + mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + status = psa_get_and_lock_key_slot(key, p_slot); + if (status != PSA_SUCCESS) { + return status; + } + slot = *p_slot; + + /* Enforce that usage policy for the key slot contains all the flags + * required by the usage parameter. There is one exception: public + * keys can always be exported, so we treat public key objects as + * if they had the export flag. */ + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) { + usage &= ~PSA_KEY_USAGE_EXPORT; + } + + if ((slot->attr.policy.usage & usage) != usage) { + status = PSA_ERROR_NOT_PERMITTED; + goto error; + } + + /* Enforce that the usage policy permits the requested algorithm. */ + if (alg != 0) { + status = psa_key_policy_permits(&slot->attr.policy, + slot->attr.type, + alg); + if (status != PSA_SUCCESS) { + goto error; + } + } + + return PSA_SUCCESS; + +error: + *p_slot = NULL; + psa_unregister_read_under_mutex(slot); + + return status; +} + +/** Get a key slot containing a transparent key and lock it. + * + * A transparent key is a key for which the key material is directly + * available, as opposed to a key in a secure element and/or to be used + * by a secure element. + * + * This is a temporary function that may be used instead of + * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support + * for a cryptographic operation. + * + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to then unregister + * once they have finished reading the contents of the slot. + * The caller unregisters by calling psa_unregister_read() or + * psa_unregister_read_under_mutex(). psa_unregister_read() must be called + * if and only if the caller already holds the global key slot mutex + * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates + * psa_unregister_read() with mutex lock and unlock operations. + */ +static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( + mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg) +{ + psa_status_t status = psa_get_and_lock_key_slot_with_policy(key, p_slot, + usage, alg); + if (status != PSA_SUCCESS) { + return status; + } + + if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) { + psa_unregister_read_under_mutex(*p_slot); + *p_slot = NULL; + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} + +psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot) +{ + if (slot->key.data != NULL) { + mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes); + } + + slot->key.data = NULL; + slot->key.bytes = 0; + + return PSA_SUCCESS; +} + +/** Completely wipe a slot in memory, including its policy. + * Persistent storage is not affected. */ +psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) +{ + psa_status_t status = psa_remove_key_data_from_memory(slot); + + /* + * As the return error code may not be handled in case of multiple errors, + * do our best to report an unexpected amount of registered readers or + * an unexpected state. + * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for + * wiping. + * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the + * function is called as part of the execution of a test suite, the + * execution of the test suite is stopped in error if the assertion fails. + */ + switch (slot->state) { + case PSA_SLOT_FULL: + /* In this state psa_wipe_key_slot() must only be called if the + * caller is the last reader. */ + case PSA_SLOT_PENDING_DELETION: + /* In this state psa_wipe_key_slot() must only be called if the + * caller is the last reader. */ + if (slot->var.occupied.registered_readers != 1) { + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 1); + status = PSA_ERROR_CORRUPTION_DETECTED; + } + break; + case PSA_SLOT_FILLING: + /* In this state registered_readers must be 0. */ + if (slot->var.occupied.registered_readers != 0) { + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 0); + status = PSA_ERROR_CORRUPTION_DETECTED; + } + break; + case PSA_SLOT_EMPTY: + /* The slot is already empty, it cannot be wiped. */ + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY); + status = PSA_ERROR_CORRUPTION_DETECTED; + break; + default: + /* The slot's state is invalid. */ + status = PSA_ERROR_CORRUPTION_DETECTED; + } + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + size_t slice_index = slot->slice_index; +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + + + /* Multipart operations may still be using the key. This is safe + * because all multipart operation objects are independent from + * the key slot: if they need to access the key after the setup + * phase, they have a copy of the key. Note that this means that + * key material can linger until all operations are completed. */ + /* At this point, key material and other type-specific content has + * been wiped. Clear remaining metadata. We can call memset and not + * zeroize because the metadata is not particularly sensitive. + * This memset also sets the slot's state to PSA_SLOT_EMPTY. */ + memset(slot, 0, sizeof(*slot)); + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + /* If the slot is already corrupted, something went deeply wrong, + * like a thread still using the slot or a stray pointer leading + * to the slot's memory being used for another object. Let the slot + * leak rather than make the corruption worse. */ + if (status == PSA_SUCCESS) { + status = psa_free_key_slot(slice_index, slot); + } +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + + return status; +} + +psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) +{ + psa_key_slot_t *slot; + psa_status_t status; /* status of the last operation */ + psa_status_t overall_status = PSA_SUCCESS; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_se_drv_table_entry_t *driver; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if (mbedtls_svc_key_id_is_null(key)) { + return PSA_SUCCESS; + } + + /* + * Get the description of the key in a key slot, and register to read it. + * In the case of a persistent key, this will load the key description + * from persistent memory if not done yet. + * We cannot avoid this loading as without it we don't know if + * the key is operated by an SE or not and this information is needed by + * the current implementation. */ + status = psa_get_and_lock_key_slot(key, &slot); + if (status != PSA_SUCCESS) { + return status; + } + +#if defined(MBEDTLS_THREADING_C) + /* We cannot unlock between setting the state to PENDING_DELETION + * and destroying the key in storage, as otherwise another thread + * could load the key into a new slot and the key will not be + * fully destroyed. */ + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); + + if (slot->state == PSA_SLOT_PENDING_DELETION) { + /* Another thread has destroyed the key between us locking the slot + * and us gaining the mutex. Unregister from the slot, + * and report that the key does not exist. */ + status = psa_unregister_read(slot); + + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); + return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status; + } +#endif + /* Set the key slot containing the key description's state to + * PENDING_DELETION. This stops new operations from registering + * to read the slot. Current readers can safely continue to access + * the key within the slot; the last registered reader will + * automatically wipe the slot when they call psa_unregister_read(). + * If the key is persistent, we can now delete the copy of the key + * from memory. If the key is opaque, we require the driver to + * deal with the deletion. */ + overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL, + PSA_SLOT_PENDING_DELETION); + + if (overall_status != PSA_SUCCESS) { + goto exit; + } + + if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) { + /* Refuse the destruction of a read-only key (which may or may not work + * if we attempt it, depending on whether the key is merely read-only + * by policy or actually physically read-only). + * Just do the best we can, which is to wipe the copy in memory + * (done in this function's cleanup code). */ + overall_status = PSA_ERROR_NOT_PERMITTED; + goto exit; + } + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + driver = psa_get_se_driver_entry(slot->attr.lifetime); + if (driver != NULL) { + /* For a key in a secure element, we need to do three things: + * remove the key file in internal storage, destroy the + * key inside the secure element, and update the driver's + * persistent data. Start a transaction that will encompass these + * three actions. */ + psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_DESTROY_KEY); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number(slot); + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction(); + if (status != PSA_SUCCESS) { + (void) psa_crypto_stop_transaction(); + /* We should still try to destroy the key in the secure + * element and the key metadata in storage. This is especially + * important if the error is that the storage is full. + * But how to do it exactly without risking an inconsistent + * state after a reset? + * https://github.com/ARMmbed/mbed-crypto/issues/215 + */ + overall_status = status; + goto exit; + } + + status = psa_destroy_se_key(driver, + psa_key_slot_get_slot_number(slot)); + if (overall_status == PSA_SUCCESS) { + overall_status = status; + } + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { + /* Destroy the copy of the persistent key from storage. + * The slot will still hold a copy of the key until the last reader + * unregisters. */ + status = psa_destroy_persistent_key(slot->attr.id); + if (overall_status == PSA_SUCCESS) { + overall_status = status; + } + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if (driver != NULL) { + status = psa_save_se_persistent_data(driver); + if (overall_status == PSA_SUCCESS) { + overall_status = status; + } + status = psa_crypto_stop_transaction(); + if (overall_status == PSA_SUCCESS) { + overall_status = status; + } + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +exit: + /* Unregister from reading the slot. If we are the last active reader + * then this will wipe the slot. */ + status = psa_unregister_read(slot); + /* Prioritize CORRUPTION_DETECTED from unregistering over + * a storage error. */ + if (status != PSA_SUCCESS) { + overall_status = status; + } + +#if defined(MBEDTLS_THREADING_C) + /* Don't overwrite existing errors if the unlock fails. */ + status = overall_status; + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + + return overall_status; +} + +/** Retrieve all the publicly-accessible attributes of a key. + */ +psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, + psa_key_attributes_t *attributes) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + psa_reset_key_attributes(attributes); + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0); + if (status != PSA_SUCCESS) { + return status; + } + + *attributes = slot->attr; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) { + psa_set_key_slot_number(attributes, + psa_key_slot_get_slot_number(slot)); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + return psa_unregister_read_under_mutex(slot); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number) +{ + if (attributes->has_slot_number) { + *slot_number = attributes->slot_number; + return PSA_SUCCESS; + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +static psa_status_t psa_export_key_buffer_internal(const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + if (key_buffer_size > data_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + memcpy(data, key_buffer, key_buffer_size); + memset(data + key_buffer_size, 0, + data_size - key_buffer_size); + *data_length = key_buffer_size; + return PSA_SUCCESS; +} + +psa_status_t psa_export_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length) +{ + psa_key_type_t type = attributes->type; + + if (key_type_is_raw_bytes(type) || + PSA_KEY_TYPE_IS_RSA(type) || + PSA_KEY_TYPE_IS_ECC(type) || + PSA_KEY_TYPE_IS_DH(type)) { + return psa_export_key_buffer_internal( + key_buffer, key_buffer_size, + data, data_size, data_length); + } else { + /* This shouldn't happen in the reference implementation, but + it is valid for a special-purpose implementation to omit + support for exporting certain key types. */ + return PSA_ERROR_NOT_SUPPORTED; + } +} + +psa_status_t psa_export_key(mbedtls_svc_key_id_t key, + uint8_t *data_external, + size_t data_size, + size_t *data_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + LOCAL_OUTPUT_DECLARE(data_external, data); + + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if (data_size == 0) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Export requires the EXPORT flag. There is an exception for public keys, + * which don't require any flag, but + * psa_get_and_lock_key_slot_with_policy() takes care of this. + */ + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_EXPORT, 0); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_OUTPUT_ALLOC(data_external, data_size, data); + + status = psa_driver_wrapper_export_key(&slot->attr, + slot->key.data, slot->key.bytes, + data, data_size, data_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_OUTPUT_FREE(data_external, data); + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_export_public_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_key_type_t type = attributes->type; + + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && + (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) || + PSA_KEY_TYPE_IS_DH(type))) { + /* Exporting public -> public */ + return psa_export_key_buffer_internal( + key_buffer, key_buffer_size, + data, data_size, data_length); + } else if (PSA_KEY_TYPE_IS_RSA(type)) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + return mbedtls_psa_rsa_export_public_key(attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length); +#else + /* We don't know how to convert a private RSA key to public. */ + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + } else if (PSA_KEY_TYPE_IS_ECC(type)) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + return mbedtls_psa_ecp_export_public_key(attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length); +#else + /* We don't know how to convert a private ECC key to public */ + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ + } else if (PSA_KEY_TYPE_IS_DH(type)) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) + return mbedtls_psa_ffdh_export_public_key(attributes, + key_buffer, + key_buffer_size, + data, data_size, + data_length); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ + } else { + (void) key_buffer; + (void) key_buffer_size; + (void) data; + (void) data_size; + (void) data_length; + return PSA_ERROR_NOT_SUPPORTED; + } +} + +psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, + uint8_t *data_external, + size_t data_size, + size_t *data_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_OUTPUT_DECLARE(data_external, data); + + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if (data_size == 0) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Exporting a public key doesn't require a usage flag. */ + status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_OUTPUT_ALLOC(data_external, data_size, data); + + if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_driver_wrapper_export_public_key( + &slot->attr, slot->key.data, slot->key.bytes, + data, data_size, data_length); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_OUTPUT_FREE(data_external, data); + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +/** Validate that a key policy is internally well-formed. + * + * This function only rejects invalid policies. It does not validate the + * consistency of the policy with respect to other attributes of the key + * such as the key type. + */ +static psa_status_t psa_validate_key_policy(const psa_key_policy_t *policy) +{ + if ((policy->usage & ~(PSA_KEY_USAGE_EXPORT | + PSA_KEY_USAGE_COPY | + PSA_KEY_USAGE_ENCRYPT | + PSA_KEY_USAGE_DECRYPT | + PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_VERIFY_MESSAGE | + PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_VERIFY_HASH | + PSA_KEY_USAGE_VERIFY_DERIVATION | + PSA_KEY_USAGE_DERIVE)) != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + +/** Validate the internal consistency of key attributes. + * + * This function only rejects invalid attribute values. If does not + * validate the consistency of the attributes with any key data that may + * be involved in the creation of the key. + * + * Call this function early in the key creation process. + * + * \param[in] attributes Key attributes for the new key. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + */ +static psa_status_t psa_validate_key_attributes( + const psa_key_attributes_t *attributes, + psa_se_drv_table_entry_t **p_drv) +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_lifetime_t lifetime = psa_get_key_lifetime(attributes); + mbedtls_svc_key_id_t key = psa_get_key_id(attributes); + + status = psa_validate_key_location(lifetime, p_drv); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_validate_key_persistence(lifetime); + if (status != PSA_SUCCESS) { + return status; + } + + if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { + if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key) != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } else { + if (!psa_is_valid_key_id(psa_get_key_id(attributes), 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + + status = psa_validate_key_policy(&attributes->policy); + if (status != PSA_SUCCESS) { + return status; + } + + /* Refuse to create overly large keys. + * Note that this doesn't trigger on import if the attributes don't + * explicitly specify a size (so psa_get_key_bits returns 0), so + * psa_import_key() needs its own checks. */ + if (psa_get_key_bits(attributes) > PSA_MAX_KEY_BITS) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} + +/** Prepare a key slot to receive key material. + * + * This function allocates a key slot and sets its metadata. + * + * If this function fails, call psa_fail_key_creation(). + * + * This function is intended to be used as follows: + * -# Call psa_start_key_creation() to allocate a key slot, prepare + * it with the specified attributes, and in case of a volatile key assign it + * a volatile key identifier. + * -# Populate the slot with the key material. + * -# Call psa_finish_key_creation() to finalize the creation of the slot. + * In case of failure at any step, stop the sequence and call + * psa_fail_key_creation(). + * + * On success, the key slot's state is PSA_SLOT_FILLING. + * It is the responsibility of the caller to change the slot's state to + * PSA_SLOT_EMPTY/FULL once key creation has finished. + * + * \param method An identification of the calling function. + * \param[in] attributes Key attributes for the new key. + * \param[out] p_slot On success, a pointer to the prepared slot. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + * \retval #PSA_SUCCESS + * The key slot is ready to receive key material. + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_start_key_creation( + psa_key_creation_method_t method, + const psa_key_attributes_t *attributes, + psa_key_slot_t **p_slot, + psa_se_drv_table_entry_t **p_drv) +{ + psa_status_t status; + + (void) method; + *p_drv = NULL; + + status = psa_validate_key_attributes(attributes, p_drv); + if (status != PSA_SUCCESS) { + return status; + } + + int key_is_volatile = PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime); + psa_key_id_t volatile_key_id; + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + status = psa_reserve_free_key_slot( + key_is_volatile ? &volatile_key_id : NULL, + p_slot); +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + if (status != PSA_SUCCESS) { + return status; + } + psa_key_slot_t *slot = *p_slot; + + /* We're storing the declared bit-size of the key. It's up to each + * creation mechanism to verify that this information is correct. + * It's automatically correct for mechanisms that use the bit-size as + * an input (generate, device) but not for those where the bit-size + * is optional (import, copy). In case of a volatile key, assign it the + * volatile key identifier associated to the slot returned to contain its + * definition. */ + + slot->attr = *attributes; + if (key_is_volatile) { +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + slot->attr.id = volatile_key_id; +#else + slot->attr.id.key_id = volatile_key_id; +#endif + } + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* For a key in a secure element, we need to do three things + * when creating or registering a persistent key: + * create the key file in internal storage, create the + * key inside the secure element, and update the driver's + * persistent data. This is done by starting a transaction that will + * encompass these three actions. + * For registering a volatile key, we just need to find an appropriate + * slot number inside the SE. Since the key is designated volatile, creating + * a transaction is not required. */ + /* The first thing to do is to find a slot number for the new key. + * We save the slot number in persistent storage as part of the + * transaction data. It will be needed to recover if the power + * fails during the key creation process, to clean up on the secure + * element side after restarting. Obtaining a slot number from the + * secure element driver updates its persistent state, but we do not yet + * save the driver's persistent state, so that if the power fails, + * we can roll back to a state where the key doesn't exist. */ + if (*p_drv != NULL) { + psa_key_slot_number_t slot_number; + status = psa_find_se_slot_for_key(attributes, method, *p_drv, + &slot_number); + if (status != PSA_SUCCESS) { + return status; + } + + if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) { + psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = slot_number; + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction(); + if (status != PSA_SUCCESS) { + (void) psa_crypto_stop_transaction(); + return status; + } + } + + status = psa_copy_key_material_into_slot( + slot, (uint8_t *) (&slot_number), sizeof(slot_number)); + if (status != PSA_SUCCESS) { + return status; + } + } + + if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) { + /* Key registration only makes sense with a secure element. */ + return PSA_ERROR_INVALID_ARGUMENT; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + return PSA_SUCCESS; +} + +/** Finalize the creation of a key once its key material has been set. + * + * This entails writing the key to persistent storage. + * + * If this function fails, call psa_fail_key_creation(). + * See the documentation of psa_start_key_creation() for the intended use + * of this function. + * + * If the finalization succeeds, the function sets the key slot's state to + * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the + * key creation process. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + * \param[out] key On success, identifier of the key. Note that the + * key identifier is also stored in the key slot. + * + * \retval #PSA_SUCCESS + * The key was successfully created. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_finish_key_creation( + psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver, + mbedtls_svc_key_id_t *key) +{ + psa_status_t status = PSA_SUCCESS; + (void) slot; + (void) driver; + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if (driver != NULL) { + psa_se_key_data_storage_t data; + psa_key_slot_number_t slot_number = + psa_key_slot_get_slot_number(slot); + + MBEDTLS_STATIC_ASSERT(sizeof(slot_number) == + sizeof(data.slot_number), + "Slot number size does not match psa_se_key_data_storage_t"); + + memcpy(&data.slot_number, &slot_number, sizeof(slot_number)); + status = psa_save_persistent_key(&slot->attr, + (uint8_t *) &data, + sizeof(data)); + } else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + /* Key material is saved in export representation in the slot, so + * just pass the slot buffer for storage. */ + status = psa_save_persistent_key(&slot->attr, + slot->key.data, + slot->key.bytes); + } + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Finish the transaction for a key creation. This does not + * happen when registering an existing key. Detect this case + * by checking whether a transaction is in progress (actual + * creation of a persistent key in a secure element requires a transaction, + * but registration or volatile key creation doesn't use one). */ + if (driver != NULL && + psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY) { + status = psa_save_se_persistent_data(driver); + if (status != PSA_SUCCESS) { + psa_destroy_persistent_key(slot->attr.id); + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; + } + status = psa_crypto_stop_transaction(); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if (status == PSA_SUCCESS) { + *key = slot->attr.id; + status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, + PSA_SLOT_FULL); + if (status != PSA_SUCCESS) { + *key = MBEDTLS_SVC_KEY_ID_INIT; + } + } + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; +} + +/** Abort the creation of a key. + * + * You may call this function after calling psa_start_key_creation(), + * or after psa_finish_key_creation() fails. In other circumstances, this + * function may not clean up persistent storage. + * See the documentation of psa_start_key_creation() for the intended use + * of this function. Sets the slot's state to PSA_SLOT_EMPTY. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + */ +static void psa_fail_key_creation(psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver) +{ + (void) driver; + + if (slot == NULL) { + return; + } + +#if defined(MBEDTLS_THREADING_C) + /* If the lock operation fails we still wipe the slot. + * Operations will no longer work after a failed lock, + * but we still need to wipe the slot of confidential data. */ + mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex); +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* TODO: If the key has already been created in the secure + * element, and the failure happened later (when saving metadata + * to internal storage), we need to destroy the key in the secure + * element. + * https://github.com/ARMmbed/mbed-crypto/issues/217 + */ + + /* Abort the ongoing transaction if any (there may not be one if + * the creation process failed before starting one, or if the + * key creation is a registration of a key in a secure element). + * Earlier functions must already have done what it takes to undo any + * partial creation. All that's left is to update the transaction data + * itself. */ + (void) psa_crypto_stop_transaction(); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + psa_wipe_key_slot(slot); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex); +#endif +} + +/** Validate optional attributes during key creation. + * + * Some key attributes are optional during key creation. If they are + * specified in the attributes structure, check that they are consistent + * with the data in the slot. + * + * This function should be called near the end of key creation, after + * the slot in memory is fully populated but before saving persistent data. + */ +static psa_status_t psa_validate_optional_attributes( + const psa_key_slot_t *slot, + const psa_key_attributes_t *attributes) +{ + if (attributes->type != 0) { + if (attributes->type != slot->attr.type) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + + if (attributes->bits != 0) { + if (attributes->bits != slot->attr.bits) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + + return PSA_SUCCESS; +} + +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data_external, + size_t data_length, + mbedtls_svc_key_id_t *key) +{ + psa_status_t status; + LOCAL_INPUT_DECLARE(data_external, data); + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + size_t bits; + size_t storage_size = data_length; + + *key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Reject zero-length symmetric keys (including raw data key objects). + * This also rejects any key which might be encoded as an empty string, + * which is never valid. */ + if (data_length == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Ensure that the bytes-to-bits conversion cannot overflow. */ + if (data_length > SIZE_MAX / 8) { + return PSA_ERROR_NOT_SUPPORTED; + } + + LOCAL_INPUT_ALLOC(data_external, data_length, data); + + status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes, + &slot, &driver); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* In the case of a transparent key or an opaque key stored in local + * storage ( thus not in the case of importing a key in a secure element + * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a + * buffer to hold the imported key material. */ + if (slot->key.data == NULL) { + if (psa_key_lifetime_is_external(attributes->lifetime)) { + status = psa_driver_wrapper_get_key_buffer_size_from_key_data( + attributes, data, data_length, &storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } + status = psa_allocate_buffer_to_slot(slot, storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + bits = slot->attr.bits; + status = psa_driver_wrapper_import_key(attributes, + data, data_length, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (slot->attr.bits == 0) { + slot->attr.bits = (psa_key_bits_t) bits; + } else if (bits != slot->attr.bits) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Enforce a size limit, and in particular ensure that the bit + * size fits in its representation type.*/ + if (bits > PSA_MAX_KEY_BITS) { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_validate_optional_attributes(slot, attributes); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_finish_key_creation(slot, driver, key); +exit: + LOCAL_INPUT_FREE(data_external, data); + if (status != PSA_SUCCESS) { + psa_fail_key_creation(slot, driver); + } + + return status; +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Leaving attributes unspecified is not currently supported. + * It could make sense to query the key type and size from the + * secure element, but not all secure elements support this + * and the driver HAL doesn't currently support it. */ + if (psa_get_key_type(attributes) == PSA_KEY_TYPE_NONE) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (psa_get_key_bits(attributes) == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Not usable with volatile keys, even with an appropriate location, + * due to the API design. + * https://github.com/Mbed-TLS/mbedtls/issues/9253 + */ + if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(attributes))) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes, + &slot, &driver); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_finish_key_creation(slot, driver, &key); + +exit: + if (status != PSA_SUCCESS) { + psa_fail_key_creation(slot, driver); + } + + /* Registration doesn't keep the key in RAM. */ + psa_close_key(key); + return status; +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, + const psa_key_attributes_t *specified_attributes, + mbedtls_svc_key_id_t *target_key) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *source_slot = NULL; + psa_key_slot_t *target_slot = NULL; + psa_key_attributes_t actual_attributes = *specified_attributes; + psa_se_drv_table_entry_t *driver = NULL; + size_t storage_size = 0; + + *target_key = MBEDTLS_SVC_KEY_ID_INIT; + + status = psa_get_and_lock_key_slot_with_policy( + source_key, &source_slot, PSA_KEY_USAGE_COPY, 0); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_validate_optional_attributes(source_slot, + specified_attributes); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* The target key type and number of bits have been validated by + * psa_validate_optional_attributes() to be either equal to zero or + * equal to the ones of the source key. So it is safe to inherit + * them from the source key now." + * */ + actual_attributes.bits = source_slot->attr.bits; + actual_attributes.type = source_slot->attr.type; + + + status = psa_restrict_key_policy(source_slot->attr.type, + &actual_attributes.policy, + &source_slot->attr.policy); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_start_key_creation(PSA_KEY_CREATION_COPY, &actual_attributes, + &target_slot, &driver); + if (status != PSA_SUCCESS) { + goto exit; + } + if (PSA_KEY_LIFETIME_GET_LOCATION(target_slot->attr.lifetime) != + PSA_KEY_LIFETIME_GET_LOCATION(source_slot->attr.lifetime)) { + /* + * If the source and target keys are stored in different locations, + * the source key would need to be exported as plaintext and re-imported + * in the other location. This has security implications which have not + * been fully mapped. For now, this can be achieved through + * appropriate API invocations from the application, if needed. + * */ + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + /* + * When the source and target keys are within the same location, + * - For transparent keys it is a blind copy without any driver invocation, + * - For opaque keys this translates to an invocation of the drivers' + * copy_key entry point through the dispatch layer. + * */ + if (psa_key_lifetime_is_external(actual_attributes.lifetime)) { + status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes, + &storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_allocate_buffer_to_slot(target_slot, storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_copy_key(&actual_attributes, + source_slot->key.data, + source_slot->key.bytes, + target_slot->key.data, + target_slot->key.bytes, + &target_slot->key.bytes); + if (status != PSA_SUCCESS) { + goto exit; + } + } else { + status = psa_copy_key_material_into_slot(target_slot, + source_slot->key.data, + source_slot->key.bytes); + if (status != PSA_SUCCESS) { + goto exit; + } + } + status = psa_finish_key_creation(target_slot, driver, target_key); +exit: + if (status != PSA_SUCCESS) { + psa_fail_key_creation(target_slot, driver); + } + + unlock_status = psa_unregister_read_under_mutex(source_slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + + + +/****************************************************************/ +/* Message digests */ +/****************************************************************/ + +psa_status_t psa_hash_abort(psa_hash_operation_t *operation) +{ + /* Aborting a non-active operation is allowed */ + if (operation->id == 0) { + return PSA_SUCCESS; + } + + psa_status_t status = psa_driver_wrapper_hash_abort(operation); + operation->id = 0; + + return status; +} + +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if (operation->id != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!PSA_ALG_IS_HASH(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Ensure all of the context is zeroized, since PSA_HASH_OPERATION_INIT only + * directly zeroes the int-sized dummy member of the context union. */ + memset(&operation->ctx, 0, sizeof(operation->ctx)); + + status = psa_driver_wrapper_hash_setup(operation, alg); + +exit: + if (status != PSA_SUCCESS) { + psa_hash_abort(operation); + } + + return status; +} + +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input_external, + size_t input_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* Don't require hash implementations to behave correctly on a + * zero-length input, which may have an invalid pointer. */ + if (input_length == 0) { + return PSA_SUCCESS; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_hash_update(operation, input, input_length); + +exit: + if (status != PSA_SUCCESS) { + psa_hash_abort(operation); + } + + LOCAL_INPUT_FREE(input_external, input); + return status; +} + +static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *hash_length = 0; + if (operation->id == 0) { + return PSA_ERROR_BAD_STATE; + } + + status = psa_driver_wrapper_hash_finish( + operation, hash, hash_size, hash_length); + psa_hash_abort(operation); + + return status; +} + +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash_external, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_OUTPUT_DECLARE(hash_external, hash); + + LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); + status = psa_hash_finish_internal(operation, hash, hash_size, hash_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_OUTPUT_FREE(hash_external, hash); + return status; +} + +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash_external, + size_t hash_length) +{ + uint8_t actual_hash[PSA_HASH_MAX_SIZE]; + size_t actual_hash_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + + status = psa_hash_finish_internal( + operation, + actual_hash, sizeof(actual_hash), + &actual_hash_length); + + if (status != PSA_SUCCESS) { + goto exit; + } + + if (actual_hash_length != hash_length) { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { + status = PSA_ERROR_INVALID_SIGNATURE; + } + +exit: + mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); + if (status != PSA_SUCCESS) { + psa_hash_abort(operation); + } + LOCAL_INPUT_FREE(hash_external, hash); + return status; +} + +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input_external, size_t input_length, + uint8_t *hash_external, size_t hash_size, + size_t *hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(hash_external, hash); + + *hash_length = 0; + if (!PSA_ALG_IS_HASH(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); + status = psa_driver_wrapper_hash_compute(alg, input, input_length, + hash, hash_size, hash_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(hash_external, hash); + return status; +} + +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input_external, size_t input_length, + const uint8_t *hash_external, size_t hash_length) +{ + uint8_t actual_hash[PSA_HASH_MAX_SIZE]; + size_t actual_hash_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(hash_external, hash); + + if (!PSA_ALG_IS_HASH(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + return status; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_hash_compute( + alg, input, input_length, + actual_hash, sizeof(actual_hash), + &actual_hash_length); + if (status != PSA_SUCCESS) { + goto exit; + } + if (actual_hash_length != hash_length) { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { + status = PSA_ERROR_INVALID_SIGNATURE; + } + +exit: + mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(hash_external, hash); + + return status; +} + +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation) +{ + if (source_operation->id == 0 || + target_operation->id != 0) { + return PSA_ERROR_BAD_STATE; + } + + psa_status_t status = psa_driver_wrapper_hash_clone(source_operation, + target_operation); + if (status != PSA_SUCCESS) { + psa_hash_abort(target_operation); + } + + return status; +} + + +/****************************************************************/ +/* MAC */ +/****************************************************************/ + +psa_status_t psa_mac_abort(psa_mac_operation_t *operation) +{ + /* Aborting a non-active operation is allowed */ + if (operation->id == 0) { + return PSA_SUCCESS; + } + + psa_status_t status = psa_driver_wrapper_mac_abort(operation); + operation->mac_size = 0; + operation->is_sign = 0; + operation->id = 0; + + return status; +} + +static psa_status_t psa_mac_finalize_alg_and_key_validation( + psa_algorithm_t alg, + const psa_key_attributes_t *attributes, + uint8_t *mac_size) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t key_type = psa_get_key_type(attributes); + size_t key_bits = psa_get_key_bits(attributes); + + if (!PSA_ALG_IS_MAC(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Validate the combination of key type and algorithm */ + status = psa_mac_key_can_do(alg, key_type); + if (status != PSA_SUCCESS) { + return status; + } + + /* Get the output length for the algorithm and key combination */ + *mac_size = PSA_MAC_LENGTH(key_type, key_bits, alg); + + if (*mac_size < 4) { + /* A very short MAC is too short for security since it can be + * brute-forced. Ancient protocols with 32-bit MACs do exist, + * so we make this our minimum, even though 32 bits is still + * too small for security. */ + return PSA_ERROR_NOT_SUPPORTED; + } + + if (*mac_size > PSA_MAC_LENGTH(key_type, key_bits, + PSA_ALG_FULL_LENGTH_MAC(alg))) { + /* It's impossible to "truncate" to a larger length than the full length + * of the algorithm. */ + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (*mac_size > PSA_MAC_MAX_SIZE) { + /* PSA_MAC_LENGTH returns the correct length even for a MAC algorithm + * that is disabled in the compile-time configuration. The result can + * therefore be larger than PSA_MAC_MAX_SIZE, which does take the + * configuration into account. In this case, force a return of + * PSA_ERROR_NOT_SUPPORTED here. Otherwise psa_mac_verify(), or + * psa_mac_compute(mac_size=PSA_MAC_MAX_SIZE), would return + * PSA_ERROR_BUFFER_TOO_SMALL for an unsupported algorithm whose MAC size + * is larger than PSA_MAC_MAX_SIZE, which is misleading and which breaks + * systematically generated tests. */ + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} + +static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + int is_sign) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + /* A context must be freshly initialized before it can be set up. */ + if (operation->id != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, + &slot, + is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, + &operation->mac_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + operation->is_sign = is_sign; + /* Dispatch the MAC setup call with validated input */ + if (is_sign) { + status = psa_driver_wrapper_mac_sign_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } else { + status = psa_driver_wrapper_mac_verify_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } + +exit: + if (status != PSA_SUCCESS) { + psa_mac_abort(operation); + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_mac_setup(operation, key, alg, 1); +} + +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_mac_setup(operation, key, alg, 0); +} + +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input_external, + size_t input_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + return status; + } + + /* Don't require hash implementations to behave correctly on a + * zero-length input, which may have an invalid pointer. */ + if (input_length == 0) { + status = PSA_SUCCESS; + return status; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_mac_update(operation, input, input_length); + + if (status != PSA_SUCCESS) { + psa_mac_abort(operation); + } + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + + return status; +} + +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac_external, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_OUTPUT_DECLARE(mac_external, mac); + LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!operation->is_sign) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL) + * once all the error checks are done. */ + if (operation->mac_size == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (mac_size < operation->mac_size) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + + status = psa_driver_wrapper_mac_sign_finish(operation, + mac, operation->mac_size, + mac_length); + +exit: + /* In case of success, set the potential excess room in the output buffer + * to an invalid value, to avoid potentially leaking a longer MAC. + * In case of error, set the output length and content to a safe default, + * such that in case the caller misses an error check, the output would be + * an unachievable MAC. + */ + if (status != PSA_SUCCESS) { + *mac_length = mac_size; + operation->mac_size = 0; + } + + if (mac != NULL) { + psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); + } + + abort_status = psa_mac_abort(operation); + LOCAL_OUTPUT_FREE(mac_external, mac); + + return status == PSA_SUCCESS ? abort_status : status; +} + +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac_external, + size_t mac_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(mac_external, mac); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->is_sign) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->mac_size != mac_length) { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + + LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); + status = psa_driver_wrapper_mac_verify_finish(operation, + mac, mac_length); + +exit: + abort_status = psa_mac_abort(operation); + LOCAL_INPUT_FREE(mac_external, mac); + + return status == PSA_SUCCESS ? abort_status : status; +} + +static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length, + int is_sign) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + uint8_t operation_mac_size = 0; + + status = psa_get_and_lock_key_slot_with_policy( + key, + &slot, + is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, + &operation_mac_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (mac_size < operation_mac_size) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_driver_wrapper_mac_compute( + &slot->attr, + slot->key.data, slot->key.bytes, + alg, + input, input_length, + mac, operation_mac_size, mac_length); + +exit: + /* In case of success, set the potential excess room in the output buffer + * to an invalid value, to avoid potentially leaking a longer MAC. + * In case of error, set the output length and content to a safe default, + * such that in case the caller misses an error check, the output would be + * an unachievable MAC. + */ + if (status != PSA_SUCCESS) { + *mac_length = mac_size; + operation_mac_size = 0; + } + + psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + uint8_t *mac_external, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(mac_external, mac); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); + status = psa_mac_compute_internal(key, alg, + input, input_length, + mac, mac_size, mac_length, 1); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(mac_external, mac); + + return status; +} + +psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + const uint8_t *mac_external, + size_t mac_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t actual_mac[PSA_MAC_MAX_SIZE]; + size_t actual_mac_length; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(mac_external, mac); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_mac_compute_internal(key, alg, + input, input_length, + actual_mac, sizeof(actual_mac), + &actual_mac_length, 0); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (mac_length != actual_mac_length) { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + + LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); + if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + +exit: + mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(mac_external, mac); + + return status; +} + +/****************************************************************/ +/* Asymmetric cryptography */ +/****************************************************************/ + +static psa_status_t psa_sign_verify_check_alg(int input_is_message, + psa_algorithm_t alg) +{ + if (input_is_message) { + if (!PSA_ALG_IS_SIGN_MESSAGE(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (PSA_ALG_IS_SIGN_HASH(alg)) { + if (!PSA_ALG_IS_HASH(PSA_ALG_SIGN_GET_HASH(alg))) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + } else { + if (!PSA_ALG_IS_SIGN_HASH(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + + return PSA_SUCCESS; +} + +static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key, + int input_is_message, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + *signature_length = 0; + + status = psa_sign_verify_check_alg(input_is_message, alg); + if (status != PSA_SUCCESS) { + return status; + } + + /* Immediately reject a zero-length signature buffer. This guarantees + * that signature must be a valid pointer. (On the other hand, the input + * buffer can in principle be empty since it doesn't actually have + * to be a hash.) */ + if (signature_size == 0) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, + input_is_message ? PSA_KEY_USAGE_SIGN_MESSAGE : + PSA_KEY_USAGE_SIGN_HASH, + alg); + + if (status != PSA_SUCCESS) { + goto exit; + } + + if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if (input_is_message) { + status = psa_driver_wrapper_sign_message( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_size, signature_length); + } else { + + status = psa_driver_wrapper_sign_hash( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_size, signature_length); + } + + +exit: + psa_wipe_tag_output_buffer(signature, status, signature_size, + *signature_length); + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +static psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key, + int input_is_message, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *signature, + size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + status = psa_sign_verify_check_alg(input_is_message, alg); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, + input_is_message ? PSA_KEY_USAGE_VERIFY_MESSAGE : + PSA_KEY_USAGE_VERIFY_HASH, + alg); + + if (status != PSA_SUCCESS) { + return status; + } + + if (input_is_message) { + status = psa_driver_wrapper_verify_message( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_length); + } else { + status = psa_driver_wrapper_verify_hash( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_length); + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; + +} + +psa_status_t psa_sign_message_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (PSA_ALG_IS_SIGN_HASH(alg)) { + size_t hash_length; + uint8_t hash[PSA_HASH_MAX_SIZE]; + + status = psa_driver_wrapper_hash_compute( + PSA_ALG_SIGN_GET_HASH(alg), + input, input_length, + hash, sizeof(hash), &hash_length); + + if (status != PSA_SUCCESS) { + return status; + } + + return psa_driver_wrapper_sign_hash( + attributes, key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_size, signature_length); + } + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + uint8_t *signature_external, + size_t signature_size, + size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); + status = psa_sign_internal(key, 1, alg, input, input_length, signature, + signature_size, signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(signature_external, signature); + return status; +} + +psa_status_t psa_verify_message_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *signature, + size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (PSA_ALG_IS_SIGN_HASH(alg)) { + size_t hash_length; + uint8_t hash[PSA_HASH_MAX_SIZE]; + + status = psa_driver_wrapper_hash_compute( + PSA_ALG_SIGN_GET_HASH(alg), + input, input_length, + hash, sizeof(hash), &hash_length); + + if (status != PSA_SUCCESS) { + return status; + } + + return psa_driver_wrapper_verify_hash( + attributes, key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_length); + } + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + const uint8_t *signature_external, + size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); + status = psa_verify_internal(key, 1, alg, input, input_length, signature, + signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(signature_external, signature); + + return status; +} + +psa_status_t psa_sign_hash_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length) +{ + if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || + PSA_ALG_IS_RSA_PSS(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + return mbedtls_psa_rsa_sign_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_size, signature_length); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { + if (PSA_ALG_IS_ECDSA(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + return mbedtls_psa_ecdsa_sign_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_size, signature_length); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + + (void) key_buffer; + (void) key_buffer_size; + (void) hash; + (void) hash_length; + (void) signature; + (void) signature_size; + (void) signature_length; + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash_external, + size_t hash_length, + uint8_t *signature_external, + size_t signature_size, + size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_OUTPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); + status = psa_sign_internal(key, 0, alg, hash, hash_length, signature, + signature_size, signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_OUTPUT_FREE(signature_external, signature); + + return status; +} + +psa_status_t psa_verify_hash_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length) +{ + if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { + if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || + PSA_ALG_IS_RSA_PSS(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + return mbedtls_psa_rsa_verify_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_length); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { + if (PSA_ALG_IS_ECDSA(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + return mbedtls_psa_ecdsa_verify_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_length); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + + (void) key_buffer; + (void) key_buffer_size; + (void) hash; + (void) hash_length; + (void) signature; + (void) signature_length; + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash_external, + size_t hash_length, + const uint8_t *signature_external, + size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_INPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); + status = psa_verify_internal(key, 0, alg, hash, hash_length, signature, + signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_INPUT_FREE(signature_external, signature); + + return status; +} + +psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + const uint8_t *salt_external, + size_t salt_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(salt_external, salt); + LOCAL_OUTPUT_DECLARE(output_external, output); + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); + if (status != PSA_SUCCESS) { + return status; + } + if (!(PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type) || + PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type))) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_asymmetric_encrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, salt, salt_length, + output, output_size, output_length); +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(salt_external, salt); + LOCAL_OUTPUT_FREE(output_external, output); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + const uint8_t *salt_external, + size_t salt_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(salt_external, salt); + LOCAL_OUTPUT_DECLARE(output_external, output); + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DECRYPT, alg); + if (status != PSA_SUCCESS) { + return status; + } + if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_asymmetric_decrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, salt, salt_length, + output, output_size, output_length); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(salt_external, salt); + LOCAL_OUTPUT_FREE(output_external, output); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +/****************************************************************/ +/* Asymmetric interruptible cryptography */ +/****************************************************************/ + +static uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED; + +void psa_interruptible_set_max_ops(uint32_t max_ops) +{ + psa_interruptible_max_ops = max_ops; +} + +uint32_t psa_interruptible_get_max_ops(void) +{ + return psa_interruptible_max_ops; +} + +uint32_t psa_sign_hash_get_num_ops( + const psa_sign_hash_interruptible_operation_t *operation) +{ + return operation->num_ops; +} + +uint32_t psa_verify_hash_get_num_ops( + const psa_verify_hash_interruptible_operation_t *operation) +{ + return operation->num_ops; +} + +static psa_status_t psa_sign_hash_abort_internal( + psa_sign_hash_interruptible_operation_t *operation) +{ + if (operation->id == 0) { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; + } + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_driver_wrapper_sign_hash_abort(operation); + + operation->id = 0; + + /* Do not clear either the error_occurred or num_ops elements here as they + * only want to be cleared by the application calling abort, not by abort + * being called at completion of an operation. */ + + return status; +} + +psa_status_t psa_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash_external, size_t hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(hash_external, hash); + + /* Check that start has not been previously called, or operation has not + * previously errored. */ + if (operation->id != 0 || operation->error_occurred) { + return PSA_ERROR_BAD_STATE; + } + + status = psa_sign_verify_check_alg(0, alg); + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + return status; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_SIGN_HASH, + alg); + + if (status != PSA_SUCCESS) { + goto exit; + } + + if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + + /* Ensure ops count gets reset, in case of operation re-use. */ + operation->num_ops = 0; + + status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr, + slot->key.data, + slot->key.bytes, alg, + hash, hash_length); +exit: + + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + psa_sign_hash_abort_internal(operation); + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + if (unlock_status != PSA_SUCCESS) { + operation->error_occurred = 1; + } + + LOCAL_INPUT_FREE(hash_external, hash); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + + +psa_status_t psa_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature_external, size_t signature_size, + size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_OUTPUT_DECLARE(signature_external, signature); + + *signature_length = 0; + + /* Check that start has been called first, and that operation has not + * previously errored. */ + if (operation->id == 0 || operation->error_occurred) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* Immediately reject a zero-length signature buffer. This guarantees that + * signature must be a valid pointer. */ + if (signature_size == 0) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); + + status = psa_driver_wrapper_sign_hash_complete(operation, signature, + signature_size, + signature_length); + + /* Update ops count with work done. */ + operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation); + +exit: + + if (signature != NULL) { + psa_wipe_tag_output_buffer(signature, status, signature_size, + *signature_length); + } + + if (status != PSA_OPERATION_INCOMPLETE) { + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + } + + psa_sign_hash_abort_internal(operation); + } + + LOCAL_OUTPUT_FREE(signature_external, signature); + + return status; +} + +psa_status_t psa_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_sign_hash_abort_internal(operation); + + /* We clear the number of ops done here, so that it is not cleared when + * the operation fails or succeeds, only on manual abort. */ + operation->num_ops = 0; + + /* Likewise, failure state. */ + operation->error_occurred = 0; + + return status; +} + +static psa_status_t psa_verify_hash_abort_internal( + psa_verify_hash_interruptible_operation_t *operation) +{ + if (operation->id == 0) { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; + } + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_driver_wrapper_verify_hash_abort(operation); + + operation->id = 0; + + /* Do not clear either the error_occurred or num_ops elements here as they + * only want to be cleared by the application calling abort, not by abort + * being called at completion of an operation. */ + + return status; +} + +psa_status_t psa_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash_external, size_t hash_length, + const uint8_t *signature_external, size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_INPUT_DECLARE(signature_external, signature); + + /* Check that start has not been previously called, or operation has not + * previously errored. */ + if (operation->id != 0 || operation->error_occurred) { + return PSA_ERROR_BAD_STATE; + } + + status = psa_sign_verify_check_alg(0, alg); + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + return status; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_VERIFY_HASH, + alg); + + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + return status; + } + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); + + /* Ensure ops count gets reset, in case of operation re-use. */ + operation->num_ops = 0; + + status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr, + slot->key.data, + slot->key.bytes, + alg, hash, hash_length, + signature, signature_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + psa_verify_hash_abort_internal(operation); + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + if (unlock_status != PSA_SUCCESS) { + operation->error_occurred = 1; + } + + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_INPUT_FREE(signature_external, signature); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* Check that start has been called first, and that operation has not + * previously errored. */ + if (operation->id == 0 || operation->error_occurred) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_verify_hash_complete(operation); + + /* Update ops count with work done. */ + operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops( + operation); + +exit: + + if (status != PSA_OPERATION_INCOMPLETE) { + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + } + + psa_verify_hash_abort_internal(operation); + } + + return status; +} + +psa_status_t psa_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_verify_hash_abort_internal(operation); + + /* We clear the number of ops done here, so that it is not cleared when + * the operation fails or succeeds, only on manual abort. */ + operation->num_ops = 0; + + /* Likewise, failure state. */ + operation->error_occurred = 0; + + return status; +} + +/****************************************************************/ +/* Asymmetric interruptible cryptography internal */ +/* implementations */ +/****************************************************************/ + +void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops) +{ + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + /* Internal implementation uses zero to indicate infinite number max ops, + * therefore avoid this value, and set to minimum possible. */ + if (max_ops == 0) { + max_ops = 1; + } + + mbedtls_ecp_set_max_ops(max_ops); +#else + (void) max_ops; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +uint32_t mbedtls_psa_sign_hash_get_num_ops( + const mbedtls_psa_sign_hash_interruptible_operation_t *operation) +{ +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + return operation->num_ops; +#else + (void) operation; + return 0; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +uint32_t mbedtls_psa_verify_hash_get_num_ops( + const mbedtls_psa_verify_hash_interruptible_operation_t *operation) +{ + #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + return operation->num_ops; +#else + (void) operation; + return 0; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +psa_status_t mbedtls_psa_sign_hash_start( + mbedtls_psa_sign_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t required_hash_length; + + if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (!PSA_ALG_IS_ECDSA(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + mbedtls_ecdsa_restart_init(&operation->restart_ctx); + + /* Ensure num_ops is zero'ed in case of context re-use. */ + operation->num_ops = 0; + + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &operation->ctx); + + if (status != PSA_SUCCESS) { + return status; + } + + operation->coordinate_bytes = PSA_BITS_TO_BYTES( + operation->ctx->grp.nbits); + + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); + operation->md_alg = mbedtls_md_type_from_psa_alg(hash_alg); + operation->alg = alg; + + /* We only need to store the same length of hash as the private key size + * here, it would be truncated by the internal implementation anyway. */ + required_hash_length = (hash_length < operation->coordinate_bytes ? + hash_length : operation->coordinate_bytes); + + if (required_hash_length > sizeof(operation->hash)) { + /* Shouldn't happen, but better safe than sorry. */ + return PSA_ERROR_CORRUPTION_DETECTED; + } + + memcpy(operation->hash, hash, required_hash_length); + operation->hash_length = required_hash_length; + + return PSA_SUCCESS; + +#else + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + (void) hash; + (void) hash_length; + (void) status; + (void) required_hash_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +psa_status_t mbedtls_psa_sign_hash_complete( + mbedtls_psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length) +{ +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r; + mbedtls_mpi s; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + /* Ensure max_ops is set to the current value (or default). */ + mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); + + if (signature_size < 2 * operation->coordinate_bytes) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) { + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + status = mbedtls_to_psa_error( + mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp, + &r, + &s, + &operation->ctx->d, + operation->hash, + operation->hash_length, + operation->md_alg, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + &operation->restart_ctx)); +#else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + } else { + status = mbedtls_to_psa_error( + mbedtls_ecdsa_sign_restartable(&operation->ctx->grp, + &r, + &s, + &operation->ctx->d, + operation->hash, + operation->hash_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + &operation->restart_ctx)); + } + + /* Hide the fact that the restart context only holds a delta of number of + * ops done during the last operation, not an absolute value. */ + operation->num_ops += operation->restart_ctx.ecp.ops_done; + + if (status == PSA_SUCCESS) { + status = mbedtls_to_psa_error( + mbedtls_mpi_write_binary(&r, + signature, + operation->coordinate_bytes) + ); + + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_mpi_write_binary(&s, + signature + + operation->coordinate_bytes, + operation->coordinate_bytes) + ); + + if (status != PSA_SUCCESS) { + goto exit; + } + + *signature_length = operation->coordinate_bytes * 2; + + status = PSA_SUCCESS; + } + +exit: + + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + return status; + + #else + + (void) operation; + (void) signature; + (void) signature_size; + (void) signature_length; + + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +psa_status_t mbedtls_psa_sign_hash_abort( + mbedtls_psa_sign_hash_interruptible_operation_t *operation) +{ + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + if (operation->ctx) { + mbedtls_ecdsa_free(operation->ctx); + mbedtls_free(operation->ctx); + operation->ctx = NULL; + } + + mbedtls_ecdsa_restart_free(&operation->restart_ctx); + + operation->num_ops = 0; + + return PSA_SUCCESS; + +#else + + (void) operation; + + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +psa_status_t mbedtls_psa_verify_hash_start( + mbedtls_psa_verify_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t coordinate_bytes = 0; + size_t required_hash_length = 0; + + if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (!PSA_ALG_IS_ECDSA(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + mbedtls_ecdsa_restart_init(&operation->restart_ctx); + mbedtls_mpi_init(&operation->r); + mbedtls_mpi_init(&operation->s); + + /* Ensure num_ops is zero'ed in case of context re-use. */ + operation->num_ops = 0; + + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &operation->ctx); + + if (status != PSA_SUCCESS) { + return status; + } + + coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits); + + if (signature_length != 2 * coordinate_bytes) { + return PSA_ERROR_INVALID_SIGNATURE; + } + + status = mbedtls_to_psa_error( + mbedtls_mpi_read_binary(&operation->r, + signature, + coordinate_bytes)); + + if (status != PSA_SUCCESS) { + return status; + } + + status = mbedtls_to_psa_error( + mbedtls_mpi_read_binary(&operation->s, + signature + + coordinate_bytes, + coordinate_bytes)); + + if (status != PSA_SUCCESS) { + return status; + } + + status = mbedtls_psa_ecp_load_public_part(operation->ctx); + + if (status != PSA_SUCCESS) { + return status; + } + + /* We only need to store the same length of hash as the private key size + * here, it would be truncated by the internal implementation anyway. */ + required_hash_length = (hash_length < coordinate_bytes ? hash_length : + coordinate_bytes); + + if (required_hash_length > sizeof(operation->hash)) { + /* Shouldn't happen, but better safe than sorry. */ + return PSA_ERROR_CORRUPTION_DETECTED; + } + + memcpy(operation->hash, hash, required_hash_length); + operation->hash_length = required_hash_length; + + return PSA_SUCCESS; +#else + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + (void) hash; + (void) hash_length; + (void) signature; + (void) signature_length; + (void) status; + (void) coordinate_bytes; + (void) required_hash_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +psa_status_t mbedtls_psa_verify_hash_complete( + mbedtls_psa_verify_hash_interruptible_operation_t *operation) +{ + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* Ensure max_ops is set to the current value (or default). */ + mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); + + status = mbedtls_to_psa_error( + mbedtls_ecdsa_verify_restartable(&operation->ctx->grp, + operation->hash, + operation->hash_length, + &operation->ctx->Q, + &operation->r, + &operation->s, + &operation->restart_ctx)); + + /* Hide the fact that the restart context only holds a delta of number of + * ops done during the last operation, not an absolute value. */ + operation->num_ops += operation->restart_ctx.ecp.ops_done; + + return status; +#else + (void) operation; + + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +psa_status_t mbedtls_psa_verify_hash_abort( + mbedtls_psa_verify_hash_interruptible_operation_t *operation) +{ + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + if (operation->ctx) { + mbedtls_ecdsa_free(operation->ctx); + mbedtls_free(operation->ctx); + operation->ctx = NULL; + } + + mbedtls_ecdsa_restart_free(&operation->restart_ctx); + + operation->num_ops = 0; + + mbedtls_mpi_free(&operation->r); + mbedtls_mpi_free(&operation->s); + + return PSA_SUCCESS; + +#else + (void) operation; + + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +static psa_status_t psa_generate_random_internal(uint8_t *output, + size_t output_size) +{ + GUARD_MODULE_INITIALIZED; + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + + psa_status_t status; + size_t output_length = 0; + status = mbedtls_psa_external_get_random(&global_data.rng, + output, output_size, + &output_length); + if (status != PSA_SUCCESS) { + return status; + } + /* Breaking up a request into smaller chunks is currently not supported + * for the external RNG interface. */ + if (output_length != output_size) { + return PSA_ERROR_INSUFFICIENT_ENTROPY; + } + return PSA_SUCCESS; + +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + while (output_size > 0) { + int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + size_t request_size = + (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? + MBEDTLS_PSA_RANDOM_MAX_REQUEST : + output_size); +#if defined(MBEDTLS_CTR_DRBG_C) + ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size); +#elif defined(MBEDTLS_HMAC_DRBG_C) + ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size); +#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ + if (ret != 0) { + return mbedtls_to_psa_error(ret); + } + output_size -= request_size; + output += request_size; + } + return PSA_SUCCESS; +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + + +/****************************************************************/ +/* Symmetric cryptography */ +/****************************************************************/ + +static psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + mbedtls_operation_t cipher_operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_DECRYPT); + + /* A context must be freshly initialized before it can be set up. */ + if (operation->id != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!PSA_ALG_IS_CIPHER(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* Initialize the operation struct members, except for id. The id member + * is used to indicate to psa_cipher_abort that there are resources to free, + * so we only set it (in the driver wrapper) after resources have been + * allocated/initialized. */ + operation->iv_set = 0; + if (alg == PSA_ALG_ECB_NO_PADDING) { + operation->iv_required = 0; + } else { + operation->iv_required = 1; + } + operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); + + /* Try doing the operation through a driver before using software fallback. */ + if (cipher_operation == MBEDTLS_ENCRYPT) { + status = psa_driver_wrapper_cipher_encrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } else { + status = psa_driver_wrapper_cipher_decrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } + +exit: + if (status != PSA_SUCCESS) { + psa_cipher_abort(operation); + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT); +} + +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT); +} + +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv_external, + size_t iv_size, + size_t *iv_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t default_iv_length = 0; + + LOCAL_OUTPUT_DECLARE(iv_external, iv); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_set || !operation->iv_required) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + default_iv_length = operation->default_iv_length; + if (iv_size < default_iv_length) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { + status = PSA_ERROR_GENERIC_ERROR; + goto exit; + } + + LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv); + + status = psa_generate_random_internal(iv, default_iv_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_cipher_set_iv(operation, + iv, default_iv_length); + +exit: + if (status == PSA_SUCCESS) { + *iv_length = default_iv_length; + operation->iv_set = 1; + } else { + *iv_length = 0; + psa_cipher_abort(operation); + if (iv != NULL) { + mbedtls_platform_zeroize(iv, default_iv_length); + } + } + + LOCAL_OUTPUT_FREE(iv_external, iv); + return status; +} + +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv_external, + size_t iv_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(iv_external, iv); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_set || !operation->iv_required) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (iv_length > PSA_CIPHER_IV_MAX_SIZE) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + LOCAL_INPUT_ALLOC(iv_external, iv_length, iv); + + status = psa_driver_wrapper_cipher_set_iv(operation, + iv, + iv_length); + +exit: + if (status == PSA_SUCCESS) { + operation->iv_set = 1; + } else { + psa_cipher_abort(operation); + } + + LOCAL_INPUT_FREE(iv_external, iv); + + return status; +} + +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_required && !operation->iv_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_update(operation, + input, + input_length, + output, + output_size, + output_length); + +exit: + if (status != PSA_SUCCESS) { + psa_cipher_abort(operation); + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_required && !operation->iv_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_finish(operation, + output, + output_size, + output_length); + +exit: + if (status == PSA_SUCCESS) { + status = psa_cipher_abort(operation); + } else { + *output_length = 0; + (void) psa_cipher_abort(operation); + } + + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) +{ + if (operation->id == 0) { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; + } + + psa_driver_wrapper_cipher_abort(operation); + + operation->id = 0; + operation->iv_set = 0; + operation->iv_required = 0; + + return PSA_SUCCESS; +} + +psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; + size_t default_iv_length = 0; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (!PSA_ALG_IS_CIPHER(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_ENCRYPT, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); + if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { + status = PSA_ERROR_GENERIC_ERROR; + goto exit; + } + + if (default_iv_length > 0) { + if (output_size < default_iv_length) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_generate_random_internal(local_iv, default_iv_length); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_encrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, local_iv, default_iv_length, input, input_length, + psa_crypto_buffer_offset(output, default_iv_length), + output_size - default_iv_length, output_length); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + if (status == PSA_SUCCESS) { + status = unlock_status; + } + + if (status == PSA_SUCCESS) { + if (default_iv_length > 0) { + memcpy(output, local_iv, default_iv_length); + } + *output_length += default_iv_length; + } else { + *output_length = 0; + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (!PSA_ALG_IS_CIPHER(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_DECRYPT, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_decrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, + output, output_size, output_length); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + if (status == PSA_SUCCESS) { + status = unlock_status; + } + + if (status != PSA_SUCCESS) { + *output_length = 0; + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + + +/****************************************************************/ +/* AEAD */ +/****************************************************************/ + +/* Helper function to get the base algorithm from its variants. */ +static psa_algorithm_t psa_aead_get_base_algorithm(psa_algorithm_t alg) +{ + return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg); +} + +/* Helper function to perform common nonce length checks. */ +static psa_status_t psa_aead_check_nonce_length(psa_algorithm_t alg, + size_t nonce_length) +{ + psa_algorithm_t base_alg = psa_aead_get_base_algorithm(alg); + + switch (base_alg) { +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_GCM: + /* Not checking max nonce size here as GCM spec allows almost + * arbitrarily large nonces. Please note that we do not generally + * recommend the usage of nonces of greater length than + * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter + * size, which can then lead to collisions if you encrypt a very + * large number of messages.*/ + if (nonce_length != 0) { + return PSA_SUCCESS; + } + break; +#endif /* PSA_WANT_ALG_GCM */ +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_CCM: + if (nonce_length >= 7 && nonce_length <= 13) { + return PSA_SUCCESS; + } + break; +#endif /* PSA_WANT_ALG_CCM */ +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + if (nonce_length == 12) { + return PSA_SUCCESS; + } else if (nonce_length == 8) { + return PSA_ERROR_NOT_SUPPORTED; + } + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + default: + (void) nonce_length; + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_ERROR_INVALID_ARGUMENT; +} + +static psa_status_t psa_aead_check_algorithm(psa_algorithm_t alg) +{ + if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + +psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce_external, + size_t nonce_length, + const uint8_t *additional_data_external, + size_t additional_data_length, + const uint8_t *plaintext_external, + size_t plaintext_length, + uint8_t *ciphertext_external, + size_t ciphertext_size, + size_t *ciphertext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_DECLARE(additional_data_external, additional_data); + LOCAL_INPUT_DECLARE(plaintext_external, plaintext); + LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); + + *ciphertext_length = 0; + + status = psa_aead_check_algorithm(alg); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data); + LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext); + LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); + + status = psa_aead_check_nonce_length(alg, nonce_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_aead_encrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length); + + if (status != PSA_SUCCESS && ciphertext_size != 0) { + memset(ciphertext, 0, ciphertext_size); + } + +exit: + LOCAL_INPUT_FREE(nonce_external, nonce); + LOCAL_INPUT_FREE(additional_data_external, additional_data); + LOCAL_INPUT_FREE(plaintext_external, plaintext); + LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); + + psa_unregister_read_under_mutex(slot); + + return status; +} + +psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce_external, + size_t nonce_length, + const uint8_t *additional_data_external, + size_t additional_data_length, + const uint8_t *ciphertext_external, + size_t ciphertext_length, + uint8_t *plaintext_external, + size_t plaintext_size, + size_t *plaintext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_DECLARE(additional_data_external, additional_data); + LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); + + *plaintext_length = 0; + + status = psa_aead_check_algorithm(alg); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DECRYPT, alg); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, + additional_data); + LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext); + LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); + + status = psa_aead_check_nonce_length(alg, nonce_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_aead_decrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length); + + if (status != PSA_SUCCESS && plaintext_size != 0) { + memset(plaintext, 0, plaintext_size); + } + +exit: + LOCAL_INPUT_FREE(nonce_external, nonce); + LOCAL_INPUT_FREE(additional_data_external, additional_data); + LOCAL_INPUT_FREE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_FREE(plaintext_external, plaintext); + + psa_unregister_read_under_mutex(slot); + + return status; +} + +static psa_status_t psa_validate_tag_length(psa_algorithm_t alg) +{ + const uint8_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); + + switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): + /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.*/ + if (tag_len < 4 || tag_len > 16 || tag_len % 2) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif /* PSA_WANT_ALG_CCM */ + +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): + /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. */ + if (tag_len != 4 && tag_len != 8 && (tag_len < 12 || tag_len > 16)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif /* PSA_WANT_ALG_GCM */ + +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): + /* We only support the default tag length. */ + if (tag_len != 16) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + + default: + (void) tag_len; + return PSA_ERROR_NOT_SUPPORTED; + } + return PSA_SUCCESS; +} + +/* Set the key for a multipart authenticated operation. */ +static psa_status_t psa_aead_setup(psa_aead_operation_t *operation, + int is_encrypt, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + psa_key_usage_t key_usage = 0; + + status = psa_aead_check_algorithm(alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (operation->id != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->nonce_set || operation->lengths_set || + operation->ad_started || operation->body_started) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (is_encrypt) { + key_usage = PSA_KEY_USAGE_ENCRYPT; + } else { + key_usage = PSA_KEY_USAGE_DECRYPT; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, key_usage, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) { + goto exit; + } + + if (is_encrypt) { + status = psa_driver_wrapper_aead_encrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } else { + status = psa_driver_wrapper_aead_decrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } + if (status != PSA_SUCCESS) { + goto exit; + } + + operation->key_type = psa_get_key_type(&slot->attr); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + + if (status == PSA_SUCCESS) { + status = unlock_status; + operation->alg = psa_aead_get_base_algorithm(alg); + operation->is_encrypt = is_encrypt; + } else { + psa_aead_abort(operation); + } + + return status; +} + +/* Set the key for a multipart authenticated encryption operation. */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_aead_setup(operation, 1, key, alg); +} + +/* Set the key for a multipart authenticated decryption operation. */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_aead_setup(operation, 0, key, alg); +} + +static psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->nonce_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_aead_check_nonce_length(operation->alg, nonce_length); + if (status != PSA_SUCCESS) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_driver_wrapper_aead_set_nonce(operation, nonce, + nonce_length); + +exit: + if (status == PSA_SUCCESS) { + operation->nonce_set = 1; + } else { + psa_aead_abort(operation); + } + + return status; +} + +/* Generate a random nonce / IV for multipart AEAD operation */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce_external, + size_t nonce_size, + size_t *nonce_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE]; + size_t required_nonce_size = 0; + + LOCAL_OUTPUT_DECLARE(nonce_external, nonce); + LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce); + + *nonce_length = 0; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->nonce_set || !operation->is_encrypt) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* For CCM, this size may not be correct according to the PSA + * specification. The PSA Crypto 1.0.1 specification states: + * + * CCM encodes the plaintext length pLen in L octets, with L the smallest + * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes. + * + * However this restriction that L has to be the smallest integer is not + * applied in practice, and it is not implementable here since the + * plaintext length may or may not be known at this time. */ + required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type, + operation->alg); + if (nonce_size < required_nonce_size) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_generate_random_internal(local_nonce, required_nonce_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_aead_set_nonce_internal(operation, local_nonce, + required_nonce_size); + +exit: + if (status == PSA_SUCCESS) { + memcpy(nonce, local_nonce, required_nonce_size); + *nonce_length = required_nonce_size; + } else { + psa_aead_abort(operation); + } + + LOCAL_OUTPUT_FREE(nonce_external, nonce); + + return status; +} + +/* Set the nonce for a multipart authenticated encryption or decryption + operation.*/ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce_external, + size_t nonce_length) +{ + psa_status_t status; + + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + + status = psa_aead_set_nonce_internal(operation, nonce, nonce_length); + +/* Exit label is only needed for buffer copying, prevent unused warnings. */ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + + LOCAL_INPUT_FREE(nonce_external, nonce); + + return status; +} + +/* Declare the lengths of the message and additional data for multipart AEAD. */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->lengths_set || operation->ad_started || + operation->body_started) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_GCM: + /* Lengths can only be too large for GCM if size_t is bigger than 32 + * bits. Without the guard this code will generate warnings on 32bit + * builds. */ +#if SIZE_MAX > UINT32_MAX + if (((uint64_t) ad_length) >> 61 != 0 || + ((uint64_t) plaintext_length) > 0xFFFFFFFE0ull) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } +#endif + break; +#endif /* PSA_WANT_ALG_GCM */ +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_CCM: + if (ad_length > 0xFF00) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + break; +#endif /* PSA_WANT_ALG_CCM */ +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + /* No length restrictions for ChaChaPoly. */ + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + default: + break; + } + + status = psa_driver_wrapper_aead_set_lengths(operation, ad_length, + plaintext_length); + +exit: + if (status == PSA_SUCCESS) { + operation->ad_remaining = ad_length; + operation->body_remaining = plaintext_length; + operation->lengths_set = 1; + } else { + psa_aead_abort(operation); + } + + return status; +} + +/* Pass additional data to an active multipart AEAD operation. */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input_external, + size_t input_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_ALLOC(input_external, input_length, input); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!operation->nonce_set || operation->body_started) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* No input to add (zero length), nothing to do. */ + if (input_length == 0) { + status = PSA_SUCCESS; + goto exit; + } + + if (operation->lengths_set) { + if (operation->ad_remaining < input_length) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->ad_remaining -= input_length; + } +#if defined(PSA_WANT_ALG_CCM) + else if (operation->alg == PSA_ALG_CCM) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ + + status = psa_driver_wrapper_aead_update_ad(operation, input, + input_length); + +exit: + if (status == PSA_SUCCESS) { + operation->ad_started = 1; + } else { + psa_aead_abort(operation); + } + + LOCAL_INPUT_FREE(input_external, input); + + return status; +} + +/* Encrypt or decrypt a message fragment in an active multipart AEAD + operation.*/ +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + *output_length = 0; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!operation->nonce_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->lengths_set) { + /* Additional data length was supplied, but not all the additional + data was supplied.*/ + if (operation->ad_remaining != 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Too much data provided. */ + if (operation->body_remaining < input_length) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->body_remaining -= input_length; + } +#if defined(PSA_WANT_ALG_CCM) + else if (operation->alg == PSA_ALG_CCM) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ + + status = psa_driver_wrapper_aead_update(operation, input, input_length, + output, output_size, + output_length); + +exit: + if (status == PSA_SUCCESS) { + operation->body_started = 1; + } else { + psa_aead_abort(operation); + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +static psa_status_t psa_aead_final_checks(const psa_aead_operation_t *operation) +{ + if (operation->id == 0 || !operation->nonce_set) { + return PSA_ERROR_BAD_STATE; + } + + if (operation->lengths_set && (operation->ad_remaining != 0 || + operation->body_remaining != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + +/* Finish encrypting a message in a multipart AEAD operation. */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext_external, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag_external, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_DECLARE(tag_external, tag); + + LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); + LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag); + + *ciphertext_length = 0; + *tag_length = tag_size; + + status = psa_aead_final_checks(operation); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (!operation->is_encrypt) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_aead_finish(operation, ciphertext, + ciphertext_size, + ciphertext_length, + tag, tag_size, tag_length); + +exit: + + + /* In case the operation fails and the user fails to check for failure or + * the zero tag size, make sure the tag is set to something implausible. + * Even if the operation succeeds, make sure we clear the rest of the + * buffer to prevent potential leakage of anything previously placed in + * the same buffer.*/ + psa_wipe_tag_output_buffer(tag, status, tag_size, *tag_length); + + psa_aead_abort(operation); + + LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_FREE(tag_external, tag); + + return status; +} + +/* Finish authenticating and decrypting a message in a multipart AEAD + operation.*/ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext_external, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag_external, + size_t tag_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); + LOCAL_INPUT_DECLARE(tag_external, tag); + + LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); + LOCAL_INPUT_ALLOC(tag_external, tag_length, tag); + + *plaintext_length = 0; + + status = psa_aead_final_checks(operation); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (operation->is_encrypt) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_aead_verify(operation, plaintext, + plaintext_size, + plaintext_length, + tag, tag_length); + +exit: + psa_aead_abort(operation); + + LOCAL_OUTPUT_FREE(plaintext_external, plaintext); + LOCAL_INPUT_FREE(tag_external, tag); + + return status; +} + +/* Abort an AEAD operation. */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->id == 0) { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; + } + + status = psa_driver_wrapper_aead_abort(operation); + + memset(operation, 0, sizeof(*operation)); + + return status; +} + +/****************************************************************/ +/* Generators */ +/****************************************************************/ + +#if defined(BUILTIN_ALG_ANY_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \ + defined(PSA_HAVE_SOFT_PBKDF2) +#define AT_LEAST_ONE_BUILTIN_KDF +#endif /* At least one builtin KDF */ + +#if defined(BUILTIN_ALG_ANY_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_key_derivation_start_hmac( + psa_mac_operation_t *operation, + psa_algorithm_t hash_alg, + const uint8_t *hmac_key, + size_t hmac_key_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + + operation->is_sign = 1; + operation->mac_size = PSA_HASH_LENGTH(hash_alg); + + status = psa_driver_wrapper_mac_sign_setup(operation, + &attributes, + hmac_key, hmac_key_length, + PSA_ALG_HMAC(hash_alg)); + + psa_reset_key_attributes(&attributes); + return status; +} +#endif /* KDF algorithms reliant on HMAC */ + +#define HKDF_STATE_INIT 0 /* no input yet */ +#define HKDF_STATE_STARTED 1 /* got salt */ +#define HKDF_STATE_KEYED 2 /* got key */ +#define HKDF_STATE_OUTPUT 3 /* output started */ + +static psa_algorithm_t psa_key_derivation_get_kdf_alg( + const psa_key_derivation_operation_t *operation) +{ + if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { + return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg); + } else { + return operation->alg; + } +} + +psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation) +{ + psa_status_t status = PSA_SUCCESS; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + if (kdf_alg == 0) { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + } else +#if defined(BUILTIN_ALG_ANY_HKDF) + if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { + mbedtls_free(operation->ctx.hkdf.info); + status = psa_mac_abort(&operation->ctx.hkdf.hmac); + } else +#endif /* BUILTIN_ALG_ANY_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || + /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ + PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + if (operation->ctx.tls12_prf.secret != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.secret, + operation->ctx.tls12_prf.secret_length); + } + + if (operation->ctx.tls12_prf.seed != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.seed, + operation->ctx.tls12_prf.seed_length); + } + + if (operation->ctx.tls12_prf.label != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.label, + operation->ctx.tls12_prf.label_length); + } +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (operation->ctx.tls12_prf.other_secret != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.other_secret, + operation->ctx.tls12_prf.other_secret_length); + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + status = PSA_SUCCESS; + + /* We leave the fields Ai and output_block to be erased safely by the + * mbedtls_platform_zeroize() in the end of this function. */ + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + mbedtls_platform_zeroize(operation->ctx.tls12_ecjpake_to_pms.data, + sizeof(operation->ctx.tls12_ecjpake_to_pms.data)); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */ +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + if (operation->ctx.pbkdf2.salt != NULL) { + mbedtls_zeroize_and_free(operation->ctx.pbkdf2.salt, + operation->ctx.pbkdf2.salt_length); + } + + status = PSA_SUCCESS; + } else +#endif /* defined(PSA_HAVE_SOFT_PBKDF2) */ + { + status = PSA_ERROR_BAD_STATE; + } + mbedtls_platform_zeroize(operation, sizeof(*operation)); + return status; +} + +psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ + if (operation->alg == 0) { + /* This is a blank key derivation operation. */ + return PSA_ERROR_BAD_STATE; + } + + *capacity = operation->capacity; + return PSA_SUCCESS; +} + +psa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation, + size_t capacity) +{ + if (operation->alg == 0) { + return PSA_ERROR_BAD_STATE; + } + if (capacity > operation->capacity) { + return PSA_ERROR_INVALID_ARGUMENT; + } + operation->capacity = capacity; + return PSA_SUCCESS; +} + +#if defined(BUILTIN_ALG_ANY_HKDF) +/* Read some bytes from an HKDF-based operation. */ +static psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t kdf_alg, + uint8_t *output, + size_t output_length) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); + uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); + size_t hmac_output_length; + psa_status_t status; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + const uint8_t last_block = PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ? 0 : 0xff; +#else + const uint8_t last_block = 0xff; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + + if (hkdf->state < HKDF_STATE_KEYED || + (!hkdf->info_set +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + && !PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + )) { + return PSA_ERROR_BAD_STATE; + } + hkdf->state = HKDF_STATE_OUTPUT; + + while (output_length != 0) { + /* Copy what remains of the current block */ + uint8_t n = hash_length - hkdf->offset_in_block; + if (n > output_length) { + n = (uint8_t) output_length; + } + memcpy(output, hkdf->output_block + hkdf->offset_in_block, n); + output += n; + output_length -= n; + hkdf->offset_in_block += n; + if (output_length == 0) { + break; + } + /* We can't be wanting more output after the last block, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if (hkdf->block_number == last_block) { + return PSA_ERROR_BAD_STATE; + } + + /* We need a new block */ + ++hkdf->block_number; + hkdf->offset_in_block = 0; + + status = psa_key_derivation_start_hmac(&hkdf->hmac, + hash_alg, + hkdf->prk, + hash_length); + if (status != PSA_SUCCESS) { + return status; + } + + if (hkdf->block_number != 1) { + status = psa_mac_update(&hkdf->hmac, + hkdf->output_block, + hash_length); + if (status != PSA_SUCCESS) { + return status; + } + } + status = psa_mac_update(&hkdf->hmac, + hkdf->info, + hkdf->info_length); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_mac_update(&hkdf->hmac, + &hkdf->block_number, 1); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_mac_sign_finish(&hkdf->hmac, + hkdf->output_block, + sizeof(hkdf->output_block), + &hmac_output_length); + if (status != PSA_SUCCESS) { + return status; + } + } + + return PSA_SUCCESS; +} +#endif /* BUILTIN_ALG_ANY_HKDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg); + uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); + psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT; + size_t hmac_output_length; + psa_status_t status, cleanup_status; + + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if (tls12_prf->block_number == 0xff) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + + /* We need a new block */ + ++tls12_prf->block_number; + tls12_prf->left_in_block = hash_length; + + /* Recall the definition of the TLS-1.2-PRF from RFC 5246: + * + * PRF(secret, label, seed) = P_<hash>(secret, label + seed) + * + * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + + * HMAC_hash(secret, A(2) + seed) + + * HMAC_hash(secret, A(3) + seed) + ... + * + * A(0) = seed + * A(i) = HMAC_hash(secret, A(i-1)) + * + * The `psa_tls12_prf_key_derivation` structure saves the block + * `HMAC_hash(secret, A(i) + seed)` from which the output + * is currently extracted as `output_block` and where i is + * `block_number`. + */ + + status = psa_key_derivation_start_hmac(&hmac, + hash_alg, + tls12_prf->secret, + tls12_prf->secret_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + /* Calculate A(i) where i = tls12_prf->block_number. */ + if (tls12_prf->block_number == 1) { + /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads + * the variable seed and in this instance means it in the context of the + * P_hash function, where seed = label + seed.) */ + status = psa_mac_update(&hmac, + tls12_prf->label, + tls12_prf->label_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, + tls12_prf->seed, + tls12_prf->seed_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + } else { + /* A(i) = HMAC_hash(secret, A(i-1)) */ + status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + } + + status = psa_mac_sign_finish(&hmac, + tls12_prf->Ai, hash_length, + &hmac_output_length); + if (hmac_output_length != hash_length) { + status = PSA_ERROR_CORRUPTION_DETECTED; + } + if (status != PSA_SUCCESS) { + goto cleanup; + } + + /* Calculate HMAC_hash(secret, A(i) + label + seed). */ + status = psa_key_derivation_start_hmac(&hmac, + hash_alg, + tls12_prf->secret, + tls12_prf->secret_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_sign_finish(&hmac, + tls12_prf->output_block, hash_length, + &hmac_output_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + +cleanup: + cleanup_status = psa_mac_abort(&hmac); + if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) { + status = cleanup_status; + } + + return status; +} + +static psa_status_t psa_key_derivation_tls12_prf_read( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg, + uint8_t *output, + size_t output_length) +{ + psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg); + uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); + psa_status_t status; + uint8_t offset, length; + + switch (tls12_prf->state) { + case PSA_TLS12_PRF_STATE_LABEL_SET: + tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT; + break; + case PSA_TLS12_PRF_STATE_OUTPUT: + break; + default: + return PSA_ERROR_BAD_STATE; + } + + while (output_length != 0) { + /* Check if we have fully processed the current block. */ + if (tls12_prf->left_in_block == 0) { + status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf, + alg); + if (status != PSA_SUCCESS) { + return status; + } + + continue; + } + + if (tls12_prf->left_in_block > output_length) { + length = (uint8_t) output_length; + } else { + length = tls12_prf->left_in_block; + } + + offset = hash_length - tls12_prf->left_in_block; + memcpy(output, tls12_prf->output_block + offset, length); + output += length; + output_length -= length; + tls12_prf->left_in_block -= length; + } + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) +static psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read( + psa_tls12_ecjpake_to_pms_t *ecjpake, + uint8_t *output, + size_t output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_size = 0; + + if (output_length != 32) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_hash_compute(PSA_ALG_SHA_256, ecjpake->data, + PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE, output, output_length, + &output_size); + if (status != PSA_SUCCESS) { + return status; + } + + if (output_size != output_length) { + return PSA_ERROR_GENERIC_ERROR; + } + + return PSA_SUCCESS; +} +#endif + +#if defined(PSA_HAVE_SOFT_PBKDF2) +static psa_status_t psa_key_derivation_pbkdf2_generate_block( + psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t prf_alg, + uint8_t prf_output_length, + psa_key_attributes_t *attributes) +{ + psa_status_t status; + psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT; + size_t mac_output_length; + uint8_t U_i[PSA_MAC_MAX_SIZE]; + uint8_t *U_accumulator = pbkdf2->output_block; + uint64_t i; + uint8_t block_counter[4]; + + mac_operation.is_sign = 1; + mac_operation.mac_size = prf_output_length; + MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0); + + status = psa_driver_wrapper_mac_sign_setup(&mac_operation, + attributes, + pbkdf2->password, + pbkdf2->password_length, + prf_alg); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter)); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i), + &mac_output_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + if (mac_output_length != prf_output_length) { + status = PSA_ERROR_CORRUPTION_DETECTED; + goto cleanup; + } + + memcpy(U_accumulator, U_i, prf_output_length); + + for (i = 1; i < pbkdf2->input_cost; i++) { + /* We are passing prf_output_length as mac_size because the driver + * function directly sets mac_output_length as mac_size upon success. + * See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ + status = psa_driver_wrapper_mac_compute(attributes, + pbkdf2->password, + pbkdf2->password_length, + prf_alg, U_i, prf_output_length, + U_i, prf_output_length, + &mac_output_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length); + } + +cleanup: + /* Zeroise buffers to clear sensitive data from memory. */ + mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE); + return status; +} + +static psa_status_t psa_key_derivation_pbkdf2_read( + psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t kdf_alg, + uint8_t *output, + size_t output_length) +{ + psa_status_t status; + psa_algorithm_t prf_alg; + uint8_t prf_output_length; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { + prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg)); + prf_output_length = PSA_HASH_LENGTH(prf_alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { + prf_alg = PSA_ALG_CMAC; + prf_output_length = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + + switch (pbkdf2->state) { + case PSA_PBKDF2_STATE_PASSWORD_SET: + /* Initially we need a new block so bytes_used is equal to block size*/ + pbkdf2->bytes_used = prf_output_length; + pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT; + break; + case PSA_PBKDF2_STATE_OUTPUT: + break; + default: + return PSA_ERROR_BAD_STATE; + } + + while (output_length != 0) { + uint8_t n = prf_output_length - pbkdf2->bytes_used; + if (n > output_length) { + n = (uint8_t) output_length; + } + memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n); + output += n; + output_length -= n; + pbkdf2->bytes_used += n; + + if (output_length == 0) { + break; + } + + /* We need a new block */ + pbkdf2->bytes_used = 0; + pbkdf2->block_number++; + + status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg, + prf_output_length, + &attributes); + if (status != PSA_SUCCESS) { + return status; + } + } + + return PSA_SUCCESS; +} +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output_external, + size_t output_length) +{ + psa_status_t status; + LOCAL_OUTPUT_DECLARE(output_external, output); + + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + + if (operation->alg == 0) { + /* This is a blank operation. */ + return PSA_ERROR_BAD_STATE; + } + + if (output_length == 0 && operation->capacity == 0) { + /* Edge case: this is a finished operation, and 0 bytes + * were requested. The right error in this case could + * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return + * INSUFFICIENT_CAPACITY, which is right for a finished + * operation, for consistency with the case when + * output_length > 0. */ + return PSA_ERROR_INSUFFICIENT_DATA; + } + + LOCAL_OUTPUT_ALLOC(output_external, output_length, output); + if (output_length > operation->capacity) { + operation->capacity = 0; + /* Go through the error path to wipe all confidential data now + * that the operation object is useless. */ + status = PSA_ERROR_INSUFFICIENT_DATA; + goto exit; + } + + operation->capacity -= output_length; + +#if defined(BUILTIN_ALG_ANY_HKDF) + if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { + status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, kdf_alg, + output, output_length); + } else +#endif /* BUILTIN_ALG_ANY_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || + PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf, + kdf_alg, output, + output_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + status = psa_key_derivation_tls12_ecjpake_to_pms_read( + &operation->ctx.tls12_ecjpake_to_pms, output, output_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg, + output, output_length); + } else +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + + { + (void) kdf_alg; + status = PSA_ERROR_BAD_STATE; + LOCAL_OUTPUT_FREE(output_external, output); + + return status; + } + +exit: + if (status != PSA_SUCCESS) { + /* Preserve the algorithm upon errors, but clear all sensitive state. + * This allows us to differentiate between exhausted operations and + * blank operations, so we can return PSA_ERROR_BAD_STATE on blank + * operations. */ + psa_algorithm_t alg = operation->alg; + psa_key_derivation_abort(operation); + operation->alg = alg; + if (output != NULL) { + memset(output, '!', output_length); + } + } + + LOCAL_OUTPUT_FREE(output_external, output); + return status; +} + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) +static void psa_des_set_key_parity(uint8_t *data, size_t data_size) +{ + if (data_size >= 8) { + mbedtls_des_key_set_parity(data); + } + if (data_size >= 16) { + mbedtls_des_key_set_parity(data + 8); + } + if (data_size >= 24) { + mbedtls_des_key_set_parity(data + 16); + } +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + +/* + * ECC keys on a Weierstrass elliptic curve require the generation + * of a private key which is an integer + * in the range [1, N - 1], where N is the boundary of the private key domain: + * N is the prime p for Diffie-Hellman, or the order of the + * curve’s base point for ECC. + * + * Let m be the bit size of N, such that 2^m > N >= 2^(m-1). + * This function generates the private key using the following process: + * + * 1. Draw a byte string of length ceiling(m/8) bytes. + * 2. If m is not a multiple of 8, set the most significant + * (8 * ceiling(m/8) - m) bits of the first byte in the string to zero. + * 3. Convert the string to integer k by decoding it as a big-endian byte string. + * 4. If k > N - 2, discard the result and return to step 1. + * 5. Output k + 1 as the private key. + * + * This method allows compliance to NIST standards, specifically the methods titled + * Key-Pair Generation by Testing Candidates in the following publications: + * - NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment + * Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.6.1.1.4 for + * Diffie-Hellman keys. + * + * - [SP800-56A] §5.6.1.2.2 or FIPS Publication 186-4: Digital Signature + * Standard (DSS) [FIPS186-4] §B.4.2 for elliptic curve keys. + * + * Note: Function allocates memory for *data buffer, so given *data should be + * always NULL. + */ +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( + psa_key_slot_t *slot, + size_t bits, + psa_key_derivation_operation_t *operation, + uint8_t **data + ) +{ + unsigned key_out_of_range = 1; + mbedtls_mpi k; + mbedtls_mpi diff_N_2; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t m; + size_t m_bytes; + + mbedtls_mpi_init(&k); + mbedtls_mpi_init(&diff_N_2); + + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( + slot->attr.type); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_from_psa(curve, bits); + + if (grp_id == MBEDTLS_ECP_DP_NONE) { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto cleanup; + } + + mbedtls_ecp_group ecp_group; + mbedtls_ecp_group_init(&ecp_group); + + MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ecp_group, grp_id)); + + /* N is the boundary of the private key domain (ecp_group.N). */ + /* Let m be the bit size of N. */ + m = ecp_group.nbits; + + m_bytes = PSA_BITS_TO_BYTES(m); + + /* Calculate N - 2 - it will be needed later. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&diff_N_2, &ecp_group.N, 2)); + + /* Note: This function is always called with *data == NULL and it + * allocates memory for the data buffer. */ + *data = mbedtls_calloc(1, m_bytes); + if (*data == NULL) { + ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; + goto cleanup; + } + + while (key_out_of_range) { + /* 1. Draw a byte string of length ceiling(m/8) bytes. */ + if ((status = psa_key_derivation_output_bytes(operation, *data, m_bytes)) != 0) { + goto cleanup; + } + + /* 2. If m is not a multiple of 8 */ + if (m % 8 != 0) { + /* Set the most significant + * (8 * ceiling(m/8) - m) bits of the first byte in + * the string to zero. + */ + uint8_t clear_bit_mask = (1 << (m % 8)) - 1; + (*data)[0] &= clear_bit_mask; + } + + /* 3. Convert the string to integer k by decoding it as a + * big-endian byte string. + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&k, *data, m_bytes)); + + /* 4. If k > N - 2, discard the result and return to step 1. + * Result of comparison is returned. When it indicates error + * then this function is called again. + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(&diff_N_2, &k, &key_out_of_range)); + } + + /* 5. Output k + 1 as the private key. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&k, &k, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&k, *data, m_bytes)); +cleanup: + if (ret != 0) { + status = mbedtls_to_psa_error(ret); + } + if (status != PSA_SUCCESS) { + mbedtls_free(*data); + *data = NULL; + } + mbedtls_mpi_free(&k); + mbedtls_mpi_free(&diff_N_2); + return status; +} + +/* ECC keys on a Montgomery elliptic curve draws a byte string whose length + * is determined by the curve, and sets the mandatory bits accordingly. That is: + * + * - Curve25519 (PSA_ECC_FAMILY_MONTGOMERY, 255 bits): + * draw a 32-byte string and process it as specified in + * Elliptic Curves for Security [RFC7748] §5. + * + * - Curve448 (PSA_ECC_FAMILY_MONTGOMERY, 448 bits): + * draw a 56-byte string and process it as specified in [RFC7748] §5. + * + * Note: Function allocates memory for *data buffer, so given *data should be + * always NULL. + */ + +static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( + size_t bits, + psa_key_derivation_operation_t *operation, + uint8_t **data + ) +{ + size_t output_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + switch (bits) { + case 255: + output_length = 32; + break; + case 448: + output_length = 56; + break; + default: + return PSA_ERROR_INVALID_ARGUMENT; + break; + } + + *data = mbedtls_calloc(1, output_length); + + if (*data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + status = psa_key_derivation_output_bytes(operation, *data, output_length); + + if (status != PSA_SUCCESS) { + return status; + } + + switch (bits) { + case 255: + (*data)[0] &= 248; + (*data)[31] &= 127; + (*data)[31] |= 64; + break; + case 448: + (*data)[0] &= 252; + (*data)[55] |= 128; + break; + default: + return PSA_ERROR_CORRUPTION_DETECTED; + break; + } + + return status; +} +#else /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ +static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( + psa_key_slot_t *slot, size_t bits, + psa_key_derivation_operation_t *operation, uint8_t **data) +{ + (void) slot; + (void) bits; + (void) operation; + (void) data; + return PSA_ERROR_NOT_SUPPORTED; +} + +static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( + size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data) +{ + (void) bits; + (void) operation; + (void) data; + return PSA_ERROR_NOT_SUPPORTED; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ + +static psa_status_t psa_generate_derived_key_internal( + psa_key_slot_t *slot, + size_t bits, + psa_key_derivation_operation_t *operation) +{ + uint8_t *data = NULL; + size_t bytes = PSA_BITS_TO_BYTES(bits); + size_t storage_size = bytes; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) + if (PSA_KEY_TYPE_IS_ECC(slot->attr.type)) { + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type); + if (PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) { + /* Weierstrass elliptic curve */ + status = psa_generate_derived_ecc_key_weierstrass_helper(slot, bits, operation, &data); + if (status != PSA_SUCCESS) { + goto exit; + } + } else { + /* Montgomery elliptic curve */ + status = psa_generate_derived_ecc_key_montgomery_helper(bits, operation, &data); + if (status != PSA_SUCCESS) { + goto exit; + } + } + } else +#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) */ + if (key_type_is_raw_bytes(slot->attr.type)) { + if (bits % 8 != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + data = mbedtls_calloc(1, bytes); + if (data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + status = psa_key_derivation_output_bytes(operation, data, bytes); + if (status != PSA_SUCCESS) { + goto exit; + } +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + if (slot->attr.type == PSA_KEY_TYPE_DES) { + psa_des_set_key_parity(data, bytes); + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) */ + } else { + return PSA_ERROR_NOT_SUPPORTED; + } + + slot->attr.bits = (psa_key_bits_t) bits; + + if (psa_key_lifetime_is_external(slot->attr.lifetime)) { + status = psa_driver_wrapper_get_key_buffer_size(&slot->attr, + &storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } + status = psa_allocate_buffer_to_slot(slot, storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_import_key(&slot->attr, + data, bytes, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits); + if (bits != slot->attr.bits) { + status = PSA_ERROR_INVALID_ARGUMENT; + } + +exit: + mbedtls_free(data); + return status; +} + +static const psa_custom_key_parameters_t default_custom_production = + PSA_CUSTOM_KEY_PARAMETERS_INIT; + +int psa_custom_key_parameters_are_default( + const psa_custom_key_parameters_t *custom, + size_t custom_data_length) +{ + if (custom->flags != 0) { + return 0; + } + if (custom_data_length != 0) { + return 0; + } + return 1; +} + +psa_status_t psa_key_derivation_output_key_custom( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + const psa_custom_key_parameters_t *custom, + const uint8_t *custom_data, + size_t custom_data_length, + mbedtls_svc_key_id_t *key) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + *key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if (psa_get_key_bits(attributes) == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + (void) custom_data; /* We only accept 0-length data */ + if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (operation->alg == PSA_ALG_NONE) { + return PSA_ERROR_BAD_STATE; + } + + if (!operation->can_output_key) { + return PSA_ERROR_NOT_PERMITTED; + } + + status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes, + &slot, &driver); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if (driver != NULL) { + /* Deriving a key in a secure element is not implemented yet. */ + status = PSA_ERROR_NOT_SUPPORTED; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if (status == PSA_SUCCESS) { + status = psa_generate_derived_key_internal(slot, + attributes->bits, + operation); + } + if (status == PSA_SUCCESS) { + status = psa_finish_key_creation(slot, driver, key); + } + if (status != PSA_SUCCESS) { + psa_fail_key_creation(slot, driver); + } + + return status; +} + +psa_status_t psa_key_derivation_output_key_ext( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key) +{ + return psa_key_derivation_output_key_custom( + attributes, operation, + (const psa_custom_key_parameters_t *) params, + params->data, params_data_length, + key); +} + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key) +{ + return psa_key_derivation_output_key_custom(attributes, operation, + &default_custom_production, + NULL, 0, + key); +} + + +/****************************************************************/ +/* Key derivation */ +/****************************************************************/ + +#if defined(AT_LEAST_ONE_BUILTIN_KDF) +static int is_kdf_alg_supported(psa_algorithm_t kdf_alg) +{ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) + if (PSA_ALG_IS_HKDF(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) + if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { + return 1; + } +#endif + return 0; +} + +static psa_status_t psa_hash_try_support(psa_algorithm_t alg) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = psa_hash_setup(&operation, alg); + psa_hash_abort(&operation); + return status; +} + +static psa_status_t psa_key_derivation_set_maximum_capacity( + psa_key_derivation_operation_t *operation, + psa_algorithm_t kdf_alg) +{ +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256); + return PSA_SUCCESS; + } +#endif +#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) + if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { +#if (SIZE_MAX > UINT32_MAX) + operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH( + PSA_KEY_TYPE_AES, + 128U, + PSA_ALG_CMAC); +#else + operation->capacity = SIZE_MAX; +#endif + return PSA_SUCCESS; + } +#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */ + + /* After this point, if kdf_alg is not valid then value of hash_alg may be + * invalid or meaningless but it does not affect this function */ + psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg); + size_t hash_size = PSA_HASH_LENGTH(hash_alg); + if (hash_size == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Make sure that hash_alg is a supported hash algorithm. Otherwise + * we might fail later, which is somewhat unfriendly and potentially + * risk-prone. */ + psa_status_t status = psa_hash_try_support(hash_alg); + if (status != PSA_SUCCESS) { + return status; + } + +#if defined(PSA_WANT_ALG_HKDF) + if (PSA_ALG_IS_HKDF(kdf_alg)) { + operation->capacity = 255 * hash_size; + } else +#endif +#if defined(PSA_WANT_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + operation->capacity = hash_size; + } else +#endif +#if defined(PSA_WANT_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + operation->capacity = 255 * hash_size; + } else +#endif +#if defined(PSA_WANT_ALG_TLS12_PRF) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg) && + (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { + operation->capacity = SIZE_MAX; + } else +#endif +#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) && + (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { + /* Master Secret is always 48 bytes + * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */ + operation->capacity = 48U; + } else +#endif +#if defined(PSA_WANT_ALG_PBKDF2_HMAC) + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { +#if (SIZE_MAX > UINT32_MAX) + operation->capacity = UINT32_MAX * hash_size; +#else + operation->capacity = SIZE_MAX; +#endif + } else +#endif /* PSA_WANT_ALG_PBKDF2_HMAC */ + { + (void) hash_size; + status = PSA_ERROR_NOT_SUPPORTED; + } + return status; +} + +static psa_status_t psa_key_derivation_setup_kdf( + psa_key_derivation_operation_t *operation, + psa_algorithm_t kdf_alg) +{ + /* Make sure that operation->ctx is properly zero-initialised. (Macro + * initialisers for this union leave some bytes unspecified.) */ + memset(&operation->ctx, 0, sizeof(operation->ctx)); + + /* Make sure that kdf_alg is a supported key derivation algorithm. */ + if (!is_kdf_alg_supported(kdf_alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + psa_status_t status = psa_key_derivation_set_maximum_capacity(operation, + kdf_alg); + return status; +} + +static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg) +{ +#if defined(PSA_WANT_ALG_ECDH) + if (alg == PSA_ALG_ECDH) { + return PSA_SUCCESS; + } +#endif +#if defined(PSA_WANT_ALG_FFDH) + if (alg == PSA_ALG_FFDH) { + return PSA_SUCCESS; + } +#endif + (void) alg; + return PSA_ERROR_NOT_SUPPORTED; +} + +static int psa_key_derivation_allows_free_form_secret_input( + psa_algorithm_t kdf_alg) +{ +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + return 0; + } +#endif + (void) kdf_alg; + return 1; +} +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + +psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, + psa_algorithm_t alg) +{ + psa_status_t status; + + if (operation->alg != 0) { + return PSA_ERROR_BAD_STATE; + } + + if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) { +#if defined(AT_LEAST_ONE_BUILTIN_KDF) + psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg); + psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg); + status = psa_key_agreement_try_support(ka_alg); + if (status != PSA_SUCCESS) { + return status; + } + if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + status = psa_key_derivation_setup_kdf(operation, kdf_alg); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) { +#if defined(AT_LEAST_ONE_BUILTIN_KDF) + status = psa_key_derivation_setup_kdf(operation, alg); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (status == PSA_SUCCESS) { + operation->alg = alg; + } + return status; +} + +#if defined(BUILTIN_ALG_ANY_HKDF) +static psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t kdf_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); + psa_status_t status; + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SALT: +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ + if (hkdf->state != HKDF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } else { + status = psa_key_derivation_start_hmac(&hkdf->hmac, + hash_alg, + data, data_length); + if (status != PSA_SUCCESS) { + return status; + } + hkdf->state = HKDF_STATE_STARTED; + return PSA_SUCCESS; + } + case PSA_KEY_DERIVATION_INPUT_SECRET: +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + /* We shouldn't be in different state as HKDF_EXPAND only allows + * two inputs: SECRET (this case) and INFO which does not modify + * the state. It could happen only if the hkdf + * object was corrupted. */ + if (hkdf->state != HKDF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } + + /* Allow only input that fits expected prk size */ + if (data_length != PSA_HASH_LENGTH(hash_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memcpy(hkdf->prk, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ + { + /* HKDF: If no salt was provided, use an empty salt. + * HKDF-EXTRACT: salt is mandatory. */ + if (hkdf->state == HKDF_STATE_INIT) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + return PSA_ERROR_BAD_STATE; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + status = psa_key_derivation_start_hmac(&hkdf->hmac, + hash_alg, + NULL, 0); + if (status != PSA_SUCCESS) { + return status; + } + hkdf->state = HKDF_STATE_STARTED; + } + if (hkdf->state != HKDF_STATE_STARTED) { + return PSA_ERROR_BAD_STATE; + } + status = psa_mac_update(&hkdf->hmac, + data, data_length); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_mac_sign_finish(&hkdf->hmac, + hkdf->prk, + sizeof(hkdf->prk), + &data_length); + if (status != PSA_SUCCESS) { + return status; + } + } + + hkdf->state = HKDF_STATE_KEYED; + hkdf->block_number = 0; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + /* The only block of output is the PRK. */ + memcpy(hkdf->output_block, hkdf->prk, PSA_HASH_LENGTH(hash_alg)); + hkdf->offset_in_block = 0; + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + { + /* Block 0 is empty, and the next block will be + * generated by psa_key_derivation_hkdf_read(). */ + hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg); + } + + return PSA_SUCCESS; + case PSA_KEY_DERIVATION_INPUT_INFO: +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg) && + hkdf->state == HKDF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + if (hkdf->state == HKDF_STATE_OUTPUT) { + return PSA_ERROR_BAD_STATE; + } + if (hkdf->info_set) { + return PSA_ERROR_BAD_STATE; + } + hkdf->info_length = data_length; + if (data_length != 0) { + hkdf->info = mbedtls_calloc(1, data_length); + if (hkdf->info == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + memcpy(hkdf->info, data, data_length); + } + hkdf->info_set = 1; + return PSA_SUCCESS; + default: + return PSA_ERROR_INVALID_ARGUMENT; + } +} +#endif /* BUILTIN_ALG_ANY_HKDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->seed = mbedtls_calloc(1, data_length); + if (prf->seed == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->seed, data, data_length); + prf->seed_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_SEED_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET && + prf->state != PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->secret = mbedtls_calloc(1, data_length); + if (prf->secret == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->secret, data, data_length); + prf->secret_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_KEY_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->label = mbedtls_calloc(1, data_length); + if (prf->label == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->label, data, data_length); + prf->label_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_LABEL_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SEED: + return psa_tls12_prf_set_seed(prf, data, data_length); + case PSA_KEY_DERIVATION_INPUT_SECRET: + return psa_tls12_prf_set_key(prf, data, data_length); + case PSA_KEY_DERIVATION_INPUT_LABEL: + return psa_tls12_prf_set_label(prf, data, data_length); + default: + return PSA_ERROR_INVALID_ARGUMENT; + } +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_tls12_prf_psk_to_ms_set_key( + psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + const size_t pms_len = (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET ? + 4 + data_length + prf->other_secret_length : + 4 + 2 * data_length); + + if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + uint8_t *pms = mbedtls_calloc(1, pms_len); + if (pms == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + uint8_t *cur = pms; + + /* pure-PSK: + * Quoting RFC 4279, Section 2: + * + * The premaster secret is formed as follows: if the PSK is N octets + * long, concatenate a uint16 with the value N, N zero octets, a second + * uint16 with the value N, and the PSK itself. + * + * mixed-PSK: + * In a DHE-PSK, RSA-PSK, ECDHE-PSK the premaster secret is formed as + * follows: concatenate a uint16 with the length of the other secret, + * the other secret itself, uint16 with the length of PSK, and the + * PSK itself. + * For details please check: + * - RFC 4279, Section 4 for the definition of RSA-PSK, + * - RFC 4279, Section 3 for the definition of DHE-PSK, + * - RFC 5489 for the definition of ECDHE-PSK. + */ + + if (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { + *cur++ = MBEDTLS_BYTE_1(prf->other_secret_length); + *cur++ = MBEDTLS_BYTE_0(prf->other_secret_length); + if (prf->other_secret_length != 0) { + memcpy(cur, prf->other_secret, prf->other_secret_length); + mbedtls_platform_zeroize(prf->other_secret, prf->other_secret_length); + cur += prf->other_secret_length; + } + } else { + *cur++ = MBEDTLS_BYTE_1(data_length); + *cur++ = MBEDTLS_BYTE_0(data_length); + memset(cur, 0, data_length); + cur += data_length; + } + + *cur++ = MBEDTLS_BYTE_1(data_length); + *cur++ = MBEDTLS_BYTE_0(data_length); + memcpy(cur, data, data_length); + cur += data_length; + + status = psa_tls12_prf_set_key(prf, pms, (size_t) (cur - pms)); + + mbedtls_zeroize_and_free(pms, pms_len); + return status; +} + +static psa_status_t psa_tls12_prf_psk_to_ms_set_other_key( + psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->other_secret = mbedtls_calloc(1, data_length); + if (prf->other_secret == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->other_secret, data, data_length); + prf->other_secret_length = data_length; + } else { + prf->other_secret_length = 0; + } + + prf->state = PSA_TLS12_PRF_STATE_OTHER_KEY_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_psk_to_ms_input( + psa_tls12_prf_key_derivation_t *prf, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SECRET: + return psa_tls12_prf_psk_to_ms_set_key(prf, + data, data_length); + break; + case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: + return psa_tls12_prf_psk_to_ms_set_other_key(prf, + data, + data_length); + break; + default: + return psa_tls12_prf_input(prf, step, data, data_length); + break; + + } +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) +static psa_status_t psa_tls12_ecjpake_to_pms_input( + psa_tls12_ecjpake_to_pms_t *ecjpake, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + if (data_length != PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE || + step != PSA_KEY_DERIVATION_INPUT_SECRET) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Check if the passed point is in an uncompressed form */ + if (data[0] != 0x04) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Only K.X has to be extracted - bytes 1 to 32 inclusive. */ + memcpy(ecjpake->data, data + 1, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ + +#if defined(PSA_HAVE_SOFT_PBKDF2) +static psa_status_t psa_pbkdf2_set_input_cost( + psa_pbkdf2_key_derivation_t *pbkdf2, + psa_key_derivation_step_t step, + uint64_t data) +{ + if (step != PSA_KEY_DERIVATION_INPUT_COST) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } + + if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (data == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + pbkdf2->input_cost = data; + pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2, + const uint8_t *data, + size_t data_length) +{ + if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) { + pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET; + } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) { + /* Appending to existing salt. No state change. */ + } else { + return PSA_ERROR_BAD_STATE; + } + + if (data_length == 0) { + /* Appending an empty string, nothing to do. */ + } else { + uint8_t *next_salt; + + next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length); + if (next_salt == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + if (pbkdf2->salt_length != 0) { + memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length); + } + memcpy(next_salt + pbkdf2->salt_length, data, data_length); + pbkdf2->salt_length += data_length; + mbedtls_free(pbkdf2->salt); + pbkdf2->salt = next_salt; + } + return PSA_SUCCESS; +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) +static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg, + const uint8_t *input, + size_t input_len, + uint8_t *output, + size_t *output_len) +{ + psa_status_t status = PSA_SUCCESS; + if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) { + return psa_hash_compute(hash_alg, input, input_len, output, + PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len); + } else if (input_len > 0) { + memcpy(output, input, input_len); + } + *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg); + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) +static psa_status_t psa_pbkdf2_cmac_set_password(const uint8_t *input, + size_t input_len, + uint8_t *output, + size_t *output_len) +{ + psa_status_t status = PSA_SUCCESS; + if (input_len != PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC)) { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + uint8_t zeros[16] = { 0 }; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(zeros))); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + /* Passing PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC) as + * mac_size as the driver function sets mac_output_length = mac_size + * on success. See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ + status = psa_driver_wrapper_mac_compute(&attributes, + zeros, sizeof(zeros), + PSA_ALG_CMAC, input, input_len, + output, + PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, + 128U, + PSA_ALG_CMAC), + output_len); + } else { + memcpy(output, input, input_len); + *output_len = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); + } + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ + +static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t kdf_alg, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status = PSA_SUCCESS; + if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) { + return PSA_ERROR_BAD_STATE; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { + psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg); + status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length, + pbkdf2->password, + &pbkdf2->password_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) + if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { + status = psa_pbkdf2_cmac_set_password(data, data_length, + pbkdf2->password, + &pbkdf2->password_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ + { + return PSA_ERROR_INVALID_ARGUMENT; + } + + pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET; + + return status; +} + +static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t kdf_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SALT: + return psa_pbkdf2_set_salt(pbkdf2, data, data_length); + case PSA_KEY_DERIVATION_INPUT_PASSWORD: + return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length); + default: + return PSA_ERROR_INVALID_ARGUMENT; + } +} +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + +/** Check whether the given key type is acceptable for the given + * input step of a key derivation. + * + * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. + * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. + * Both secret and non-secret inputs can alternatively have the type + * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning + * that the input was passed as a buffer rather than via a key object. + */ +static int psa_key_derivation_check_input_type( + psa_key_derivation_step_t step, + psa_key_type_t key_type) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SECRET: + if (key_type == PSA_KEY_TYPE_DERIVE) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: + if (key_type == PSA_KEY_TYPE_DERIVE) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + case PSA_KEY_DERIVATION_INPUT_LABEL: + case PSA_KEY_DERIVATION_INPUT_SALT: + case PSA_KEY_DERIVATION_INPUT_INFO: + case PSA_KEY_DERIVATION_INPUT_SEED: + if (key_type == PSA_KEY_TYPE_RAW_DATA) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + case PSA_KEY_DERIVATION_INPUT_PASSWORD: + if (key_type == PSA_KEY_TYPE_PASSWORD) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_DERIVE) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + } + return PSA_ERROR_INVALID_ARGUMENT; +} + +static psa_status_t psa_key_derivation_input_internal( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_type_t key_type, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + + status = psa_key_derivation_check_input_type(step, key_type); + if (status != PSA_SUCCESS) { + goto exit; + } + +#if defined(BUILTIN_ALG_ANY_HKDF) + if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { + status = psa_hkdf_input(&operation->ctx.hkdf, kdf_alg, + step, data, data_length); + } else +#endif /* BUILTIN_ALG_ANY_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { + status = psa_tls12_prf_input(&operation->ctx.tls12_prf, + step, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf, + step, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + status = psa_tls12_ecjpake_to_pms_input( + &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg, + step, data, data_length); + } else +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + { + /* This can't happen unless the operation object was not initialized */ + (void) data; + (void) data_length; + (void) kdf_alg; + return PSA_ERROR_BAD_STATE; + } + +exit: + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + } + return status; +} + +static psa_status_t psa_key_derivation_input_integer_internal( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + status = psa_pbkdf2_set_input_cost( + &operation->ctx.pbkdf2, step, value); + } else +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + { + (void) step; + (void) value; + (void) kdf_alg; + status = PSA_ERROR_INVALID_ARGUMENT; + } + + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + } + return status; +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data_external, + size_t data_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(data_external, data); + + LOCAL_INPUT_ALLOC(data_external, data_length, data); + + status = psa_key_derivation_input_internal(operation, step, + PSA_KEY_TYPE_NONE, + data, data_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(data_external, data); + return status; +} + +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value) +{ + return psa_key_derivation_input_integer_internal(operation, step, value); +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + status = psa_get_and_lock_transparent_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + return status; + } + + /* Passing a key object as a SECRET or PASSWORD input unlocks the + * permission to output to a key object. */ + if (step == PSA_KEY_DERIVATION_INPUT_SECRET || + step == PSA_KEY_DERIVATION_INPUT_PASSWORD) { + operation->can_output_key = 1; + } + + status = psa_key_derivation_input_internal(operation, + step, slot->attr.type, + slot->key.data, + slot->key.bytes); + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + + + +/****************************************************************/ +/* Key agreement */ +/****************************************************************/ + +psa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) +{ + switch (alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + case PSA_ALG_ECDH: + return mbedtls_psa_key_agreement_ecdh(attributes, key_buffer, + key_buffer_size, alg, + peer_key, peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) + case PSA_ALG_FFDH: + return mbedtls_psa_ffdh_key_agreement(attributes, + peer_key, + peer_key_length, + key_buffer, + key_buffer_size, + shared_secret, + shared_secret_size, + shared_secret_length); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ + + default: + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; + (void) peer_key; + (void) peer_key_length; + (void) shared_secret; + (void) shared_secret_size; + (void) shared_secret_length; + return PSA_ERROR_NOT_SUPPORTED; + } +} + +/** Internal function for raw key agreement + * Calls the driver wrapper which will hand off key agreement task + * to the driver's implementation if a driver is present. + * Fallback specified in the driver wrapper is built-in raw key agreement + * (psa_key_agreement_raw_builtin). + */ +static psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) +{ + if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return psa_driver_wrapper_key_agreement(&private_key->attr, + private_key->key.data, + private_key->key.bytes, alg, + peer_key, peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length); +} + +/* Note that if this function fails, you must call psa_key_derivation_abort() + * to potentially free embedded data structures and wipe confidential data. + */ +static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length) +{ + psa_status_t status; + uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 }; + size_t shared_secret_length = 0; + psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg); + + /* Step 1: run the secret agreement algorithm to generate the shared + * secret. */ + status = psa_key_agreement_raw_internal(ka_alg, + private_key, + peer_key, peer_key_length, + shared_secret, + sizeof(shared_secret), + &shared_secret_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* Step 2: set up the key derivation to generate key material from + * the shared secret. A shared secret is permitted wherever a key + * of type DERIVE is permitted. */ + status = psa_key_derivation_input_internal(operation, step, + PSA_KEY_TYPE_DERIVE, + shared_secret, + shared_secret_length); +exit: + mbedtls_platform_zeroize(shared_secret, shared_secret_length); + return status; +} + +psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key_external, + size_t peer_key_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(peer_key_external, peer_key); + + if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + status = psa_get_and_lock_transparent_key_slot_with_policy( + private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); + status = psa_key_agreement_internal(operation, step, + slot, + peer_key, peer_key_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + } else { + /* If a private key has been added as SECRET, we allow the derived + * key material to be used as a key in PSA Crypto. */ + if (step == PSA_KEY_DERIVATION_INPUT_SECRET) { + operation->can_output_key = 1; + } + } + + unlock_status = psa_unregister_read_under_mutex(slot); + LOCAL_INPUT_FREE(peer_key_external, peer_key); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key_external, + size_t peer_key_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + size_t expected_length; + LOCAL_INPUT_DECLARE(peer_key_external, peer_key); + LOCAL_OUTPUT_DECLARE(output_external, output); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + status = psa_get_and_lock_transparent_key_slot_with_policy( + private_key, &slot, PSA_KEY_USAGE_DERIVE, alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound + * for the output size. The PSA specification only guarantees that this + * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...), + * but it might be nice to allow smaller buffers if the output fits. + * At the time of writing this comment, with only ECDH implemented, + * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot. + * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily + * be exact for it as well. */ + expected_length = + PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits); + if (output_size < expected_length) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); + status = psa_key_agreement_raw_internal(alg, slot, + peer_key, peer_key_length, + output, output_size, + output_length); + +exit: + /* Check for successful allocation of output, + * with an unsuccessful status. */ + if (output != NULL && status != PSA_SUCCESS) { + /* If an error happens and is not handled properly, the output + * may be used as a key to protect sensitive data. Arrange for such + * a key to be random, which is likely to result in decryption or + * verification errors. This is better than filling the buffer with + * some constant data such as zeros, which would result in the data + * being protected with a reproducible, easily knowable key. + */ + psa_generate_random_internal(output, output_size); + *output_length = output_size; + } + + if (output == NULL) { + /* output allocation failed. */ + *output_length = 0; + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_INPUT_FREE(peer_key_external, peer_key); + LOCAL_OUTPUT_FREE(output_external, output); + return (status == PSA_SUCCESS) ? unlock_status : status; +} + + +/****************************************************************/ +/* Random generation */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include "entropy_poll.h" +#endif + +/** Initialize the PSA random generator. + * + * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling + * this function if mutexes are enabled. + */ +static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset(rng, 0, sizeof(*rng)); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + /* Set default configuration if + * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ + if (rng->entropy_init == NULL) { + rng->entropy_init = mbedtls_entropy_init; + } + if (rng->entropy_free == NULL) { + rng->entropy_free = mbedtls_entropy_free; + } + + rng->entropy_init(&rng->entropy); +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + /* The PSA entropy injection feature depends on using NV seed as an entropy + * source. Add NV seed as an entropy source for PSA entropy injection. */ + mbedtls_entropy_add_source(&rng->entropy, + mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG); +#endif + + mbedtls_psa_drbg_init(&rng->drbg); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +/** Deinitialize the PSA random generator. + * + * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling + * this function if mutexes are enabled. + */ +static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset(rng, 0, sizeof(*rng)); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + mbedtls_psa_drbg_free(&rng->drbg); + rng->entropy_free(&rng->entropy); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +/** Seed the PSA random generator. + */ +static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + /* Do nothing: the external RNG seeds itself. */ + (void) rng; + return PSA_SUCCESS; +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + const unsigned char drbg_seed[] = "PSA"; + int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy, + drbg_seed, sizeof(drbg_seed) - 1); + return mbedtls_to_psa_error(ret); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +psa_status_t psa_generate_random(uint8_t *output_external, + size_t output_size) +{ + psa_status_t status; + + LOCAL_OUTPUT_DECLARE(output_external, output); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_generate_random_internal(output, output_size); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_OUTPUT_FREE(output_external, output); + return status; +} + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, + size_t seed_size) +{ + if (psa_get_initialized()) { + return PSA_ERROR_NOT_PERMITTED; + } + + if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || + (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) || + (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return mbedtls_psa_storage_inject_entropy(seed, seed_size); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +/** Validate the key type and size for key generation + * + * \param type The key type + * \param bits The number of bits of the key + * + * \retval #PSA_SUCCESS + * The key type and size are valid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in bits of the key is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + */ +static psa_status_t psa_validate_key_type_and_size_for_key_generation( + psa_key_type_t type, size_t bits) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (key_type_is_raw_bytes(type)) { + status = psa_validate_unstructured_key_bit_size(type, bits); + if (status != PSA_SUCCESS) { + return status; + } + } else +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (bits < PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Accept only byte-aligned keys, for the same reasons as + * in psa_import_rsa_key(). */ + if (bits % 8 != 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + } else +#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + /* To avoid empty block, return successfully here. */ + return PSA_SUCCESS; + } else +#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + if (psa_is_dh_key_size_valid(bits) == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + } else +#endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ + { + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} + +psa_status_t psa_generate_key_internal( + const psa_key_attributes_t *attributes, + const psa_custom_key_parameters_t *custom, + const uint8_t *custom_data, + size_t custom_data_length, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = attributes->type; + + /* Only used for RSA */ + (void) custom; + (void) custom_data; + (void) custom_data_length; + + if (key_type_is_raw_bytes(type)) { + status = psa_generate_random_internal(key_buffer, key_buffer_size); + if (status != PSA_SUCCESS) { + return status; + } + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + if (type == PSA_KEY_TYPE_DES) { + psa_des_set_key_parity(key_buffer, key_buffer_size); + } +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + } else + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) + if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + return mbedtls_psa_rsa_generate_key(attributes, + custom_data, custom_data_length, + key_buffer, + key_buffer_size, + key_buffer_length); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + return mbedtls_psa_ecp_generate_key(attributes, + key_buffer, + key_buffer_size, + key_buffer_length); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + return mbedtls_psa_ffdh_generate_key(attributes, + key_buffer, + key_buffer_size, + key_buffer_length); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ + { + (void) key_buffer_length; + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} + +psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes, + const psa_custom_key_parameters_t *custom, + const uint8_t *custom_data, + size_t custom_data_length, + mbedtls_svc_key_id_t *key) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + size_t key_buffer_size; + + *key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if (psa_get_key_bits(attributes) == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Reject any attempt to create a public key. */ + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) + if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + if (custom->flags != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } else +#endif + if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes, + &slot, &driver); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* In the case of a transparent key or an opaque key stored in local + * storage ( thus not in the case of generating a key in a secure element + * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a + * buffer to hold the generated key material. */ + if (slot->key.data == NULL) { + if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) == + PSA_KEY_LOCATION_LOCAL_STORAGE) { + status = psa_validate_key_type_and_size_for_key_generation( + attributes->type, attributes->bits); + if (status != PSA_SUCCESS) { + goto exit; + } + + key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( + attributes->type, + attributes->bits); + } else { + status = psa_driver_wrapper_get_key_buffer_size( + attributes, &key_buffer_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + status = psa_allocate_buffer_to_slot(slot, key_buffer_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + status = psa_driver_wrapper_generate_key(attributes, + custom, + custom_data, custom_data_length, + slot->key.data, slot->key.bytes, + &slot->key.bytes); + if (status != PSA_SUCCESS) { + psa_remove_key_data_from_memory(slot); + } + +exit: + if (status == PSA_SUCCESS) { + status = psa_finish_key_creation(slot, driver, key); + } + if (status != PSA_SUCCESS) { + psa_fail_key_creation(slot, driver); + } + + return status; +} + +psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key) +{ + return psa_generate_key_custom( + attributes, + (const psa_custom_key_parameters_t *) params, + params->data, params_data_length, + key); +} + +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key) +{ + return psa_generate_key_custom(attributes, + &default_custom_production, + NULL, 0, + key); +} + +/****************************************************************/ +/* Module setup */ +/****************************************************************/ + +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init)(mbedtls_entropy_context *ctx), + void (* entropy_free)(mbedtls_entropy_context *ctx)) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (global_data.rng_state != RNG_NOT_INITIALIZED) { + status = PSA_ERROR_BAD_STATE; + } else { + global_data.rng.entropy_init = entropy_init; + global_data.rng.entropy_free = entropy_free; + status = PSA_SUCCESS; + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + return status; +} +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +void mbedtls_psa_crypto_free(void) +{ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + /* Nothing to do to free transaction. */ + if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) { + global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; + } + + if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) { + psa_wipe_all_key_slots(); + global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (global_data.rng_state != RNG_NOT_INITIALIZED) { + mbedtls_psa_random_free(&global_data.rng); + } + global_data.rng_state = RNG_NOT_INITIALIZED; + mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng)); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + /* Terminate drivers */ + if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) { + psa_driver_wrapper_free(); + global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + +} + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) +/** Recover a transaction that was interrupted by a power failure. + * + * This function is called during initialization, before psa_crypto_init() + * returns. If this function returns a failure status, the initialization + * fails. + */ +static psa_status_t psa_crypto_recover_transaction( + const psa_crypto_transaction_t *transaction) +{ + switch (transaction->unknown.type) { + case PSA_CRYPTO_TRANSACTION_CREATE_KEY: + case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: + /* TODO - fall through to the failure case until this + * is implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/218 + */ + default: + /* We found an unsupported transaction in the storage. + * We don't know what state the storage is in. Give up. */ + return PSA_ERROR_DATA_INVALID; + } +} +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + +static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t driver_wrappers_initialized = 0; + + switch (subsystem) { + case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS: + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) { + /* Init drivers */ + status = psa_driver_wrapper_init(); + + /* Drivers need shutdown regardless of startup errors. */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; + + + } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + break; + + case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS: + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) { + status = psa_initialize_key_slots(); + + /* Need to wipe keys even if initialization fails. */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; + + } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + break; + + case PSA_CRYPTO_SUBSYSTEM_RNG: + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + driver_wrappers_initialized = + (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED); + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + /* Need to use separate mutex here, as initialisation can require + * testing of init flags, which requires locking the global data + * mutex. */ +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + /* Initialize and seed the random generator. */ + if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) { + mbedtls_psa_random_init(&global_data.rng); + global_data.rng_state = RNG_INITIALIZED; + + status = mbedtls_psa_random_seed(&global_data.rng); + if (status == PSA_SUCCESS) { + global_data.rng_state = RNG_SEEDED; + } + } + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_rngdata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + break; + + case PSA_CRYPTO_SUBSYSTEM_TRANSACTION: + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) { +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + status = psa_crypto_load_transaction(); + if (status == PSA_SUCCESS) { + status = psa_crypto_recover_transaction(&psa_crypto_transaction); + if (status == PSA_SUCCESS) { + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; + } + status = psa_crypto_stop_transaction(); + } else if (status == PSA_ERROR_DOES_NOT_EXIST) { + /* There's no transaction to complete. It's all good. */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; + status = PSA_SUCCESS; + } +#else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; + status = PSA_SUCCESS; +#endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ + } + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + break; + + default: + status = PSA_ERROR_CORRUPTION_DETECTED; + } + + /* Exit label only required when using threading macros. */ +#if defined(MBEDTLS_THREADING_C) +exit: +#endif /* defined(MBEDTLS_THREADING_C) */ + + return status; +} + +psa_status_t psa_crypto_init(void) +{ + psa_status_t status; + + /* Double initialization is explicitly allowed. Early out if everything is + * done. */ + if (psa_get_initialized()) { + return PSA_SUCCESS; + } + + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION); + +exit: + + if (status != PSA_SUCCESS) { + mbedtls_psa_crypto_free(); + } + + return status; +} + +#if defined(PSA_WANT_ALG_SOME_PAKE) +psa_status_t psa_crypto_driver_pake_get_password_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *password_len) +{ + if (inputs->password_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + *password_len = inputs->password_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_password( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *buffer, size_t buffer_size, size_t *buffer_length) +{ + if (inputs->password_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + if (buffer_size < inputs->password_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(buffer, inputs->password, inputs->password_len); + *buffer_length = inputs->password_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_user_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *user_len) +{ + if (inputs->user_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + *user_len = inputs->user_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_user( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *user_id, size_t user_id_size, size_t *user_id_len) +{ + if (inputs->user_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + if (user_id_size < inputs->user_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(user_id, inputs->user, inputs->user_len); + *user_id_len = inputs->user_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_peer_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *peer_len) +{ + if (inputs->peer_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + *peer_len = inputs->peer_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_peer( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length) +{ + if (inputs->peer_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + if (peer_id_size < inputs->peer_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(peer_id, inputs->peer, inputs->peer_len); + *peer_id_length = inputs->peer_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_cipher_suite( + const psa_crypto_driver_pake_inputs_t *inputs, + psa_pake_cipher_suite_t *cipher_suite) +{ + if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) { + return PSA_ERROR_BAD_STATE; + } + + *cipher_suite = inputs->cipher_suite; + + return PSA_SUCCESS; +} + +psa_status_t psa_pake_setup( + psa_pake_operation_t *operation, + const psa_pake_cipher_suite_t *cipher_suite) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 || + PSA_ALG_IS_HASH(cipher_suite->hash) == 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + memset(&operation->data.inputs, 0, sizeof(operation->data.inputs)); + + operation->alg = cipher_suite->algorithm; + operation->primitive = PSA_PAKE_PRIMITIVE(cipher_suite->type, + cipher_suite->family, cipher_suite->bits); + operation->data.inputs.cipher_suite = *cipher_suite; + +#if defined(PSA_WANT_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + psa_jpake_computation_stage_t *computation_stage = + &operation->computation_stage.jpake; + + memset(computation_stage, 0, sizeof(*computation_stage)); + computation_stage->step = PSA_PAKE_STEP_KEY_SHARE; + } else +#endif /* PSA_WANT_ALG_JPAKE */ + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS; + + return PSA_SUCCESS; +exit: + psa_pake_abort(operation); + return status; +} + +psa_status_t psa_pake_set_password_key( + psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + psa_key_type_t type; + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy(password, &slot, + PSA_KEY_USAGE_DERIVE, + operation->alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + type = psa_get_key_type(&slot->attr); + + if (type != PSA_KEY_TYPE_PASSWORD && + type != PSA_KEY_TYPE_PASSWORD_HASH) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes); + if (operation->data.inputs.password == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes); + operation->data.inputs.password_len = slot->key.bytes; + operation->data.inputs.attributes = slot->attr; + +exit: + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + unlock_status = psa_unregister_read_under_mutex(slot); + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_pake_set_user( + psa_pake_operation_t *operation, + const uint8_t *user_id_external, + size_t user_id_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(user_id_external, user_id); + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (user_id_len == 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if (operation->data.inputs.user_len != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + operation->data.inputs.user = mbedtls_calloc(1, user_id_len); + if (operation->data.inputs.user == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id); + + memcpy(operation->data.inputs.user, user_id, user_id_len); + operation->data.inputs.user_len = user_id_len; + + status = PSA_SUCCESS; + +exit: + LOCAL_INPUT_FREE(user_id_external, user_id); + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + return status; +} + +psa_status_t psa_pake_set_peer( + psa_pake_operation_t *operation, + const uint8_t *peer_id_external, + size_t peer_id_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(peer_id_external, peer_id); + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (peer_id_len == 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if (operation->data.inputs.peer_len != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + operation->data.inputs.peer = mbedtls_calloc(1, peer_id_len); + if (operation->data.inputs.peer == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id); + + memcpy(operation->data.inputs.peer, peer_id, peer_id_len); + operation->data.inputs.peer_len = peer_id_len; + + status = PSA_SUCCESS; + +exit: + LOCAL_INPUT_FREE(peer_id_external, peer_id); + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + return status; +} + +psa_status_t psa_pake_set_role( + psa_pake_operation_t *operation, + psa_pake_role_t role) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + if (role == PSA_PAKE_ROLE_NONE) { + return PSA_SUCCESS; + } + status = PSA_ERROR_INVALID_ARGUMENT; + break; +#endif + default: + (void) role; + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } +exit: + psa_pake_abort(operation); + return status; +} + +/* Auxiliary function to convert core computation stage to single driver step. */ +#if defined(PSA_WANT_ALG_JPAKE) +static psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step( + psa_jpake_computation_stage_t *stage) +{ + psa_crypto_driver_pake_step_t key_share_step; + if (stage->round == PSA_JPAKE_FIRST) { + int is_x1; + + if (stage->io_mode == PSA_JPAKE_OUTPUT) { + is_x1 = (stage->outputs < 1); + } else { + is_x1 = (stage->inputs < 1); + } + + key_share_step = is_x1 ? + PSA_JPAKE_X1_STEP_KEY_SHARE : + PSA_JPAKE_X2_STEP_KEY_SHARE; + } else if (stage->round == PSA_JPAKE_SECOND) { + key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ? + PSA_JPAKE_X2S_STEP_KEY_SHARE : + PSA_JPAKE_X4S_STEP_KEY_SHARE; + } else { + return PSA_JPAKE_STEP_INVALID; + } + return (psa_crypto_driver_pake_step_t) (key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE); +} +#endif /* PSA_WANT_ALG_JPAKE */ + +static psa_status_t psa_pake_complete_inputs( + psa_pake_operation_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + /* Create copy of the inputs on stack as inputs share memory + with the driver context which will be setup by the driver. */ + psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs; + + if (inputs.password_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + if (operation->alg == PSA_ALG_JPAKE) { + if (inputs.user_len == 0 || inputs.peer_len == 0) { + return PSA_ERROR_BAD_STATE; + } + } + + /* Clear driver context */ + mbedtls_platform_zeroize(&operation->data, sizeof(operation->data)); + + status = psa_driver_wrapper_pake_setup(operation, &inputs); + + /* Driver is responsible for creating its own copy of the password. */ + mbedtls_zeroize_and_free(inputs.password, inputs.password_len); + + /* User and peer are translated to role. */ + mbedtls_free(inputs.user); + mbedtls_free(inputs.peer); + + if (status == PSA_SUCCESS) { +#if defined(PSA_WANT_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION; + } else +#endif /* PSA_WANT_ALG_JPAKE */ + { + status = PSA_ERROR_NOT_SUPPORTED; + } + } + return status; +} + +#if defined(PSA_WANT_ALG_JPAKE) +static psa_status_t psa_jpake_prologue( + psa_pake_operation_t *operation, + psa_pake_step_t step, + psa_jpake_io_mode_t io_mode) +{ + if (step != PSA_PAKE_STEP_KEY_SHARE && + step != PSA_PAKE_STEP_ZK_PUBLIC && + step != PSA_PAKE_STEP_ZK_PROOF) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_jpake_computation_stage_t *computation_stage = + &operation->computation_stage.jpake; + + if (computation_stage->round != PSA_JPAKE_FIRST && + computation_stage->round != PSA_JPAKE_SECOND) { + return PSA_ERROR_BAD_STATE; + } + + /* Check that the step we are given is the one we were expecting */ + if (step != computation_stage->step) { + return PSA_ERROR_BAD_STATE; + } + + if (step == PSA_PAKE_STEP_KEY_SHARE && + computation_stage->inputs == 0 && + computation_stage->outputs == 0) { + /* Start of the round, so function decides whether we are inputting + * or outputting */ + computation_stage->io_mode = io_mode; + } else if (computation_stage->io_mode != io_mode) { + /* Middle of the round so the mode we are in must match the function + * called by the user */ + return PSA_ERROR_BAD_STATE; + } + + return PSA_SUCCESS; +} + +static psa_status_t psa_jpake_epilogue( + psa_pake_operation_t *operation, + psa_jpake_io_mode_t io_mode) +{ + psa_jpake_computation_stage_t *stage = + &operation->computation_stage.jpake; + + if (stage->step == PSA_PAKE_STEP_ZK_PROOF) { + /* End of an input/output */ + if (io_mode == PSA_JPAKE_INPUT) { + stage->inputs++; + if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) { + stage->io_mode = PSA_JPAKE_OUTPUT; + } + } + if (io_mode == PSA_JPAKE_OUTPUT) { + stage->outputs++; + if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { + stage->io_mode = PSA_JPAKE_INPUT; + } + } + if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) && + stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { + /* End of a round, move to the next round */ + stage->inputs = 0; + stage->outputs = 0; + stage->round++; + } + stage->step = PSA_PAKE_STEP_KEY_SHARE; + } else { + stage->step++; + } + return PSA_SUCCESS; +} + +#endif /* PSA_WANT_ALG_JPAKE */ + +psa_status_t psa_pake_output( + psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; + LOCAL_OUTPUT_DECLARE(output_external, output); + *output_length = 0; + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = psa_pake_complete_inputs(operation); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (output_size == 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT); + if (status != PSA_SUCCESS) { + goto exit; + } + driver_step = convert_jpake_computation_stage_to_driver_step( + &operation->computation_stage.jpake); + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + (void) step; + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_pake_output(operation, driver_step, + output, output_size, output_length); + + if (status != PSA_SUCCESS) { + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT); + if (status != PSA_SUCCESS) { + goto exit; + } + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + +exit: + LOCAL_OUTPUT_FREE(output_external, output); + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + return status; +} + +psa_status_t psa_pake_input( + psa_pake_operation_t *operation, + psa_pake_step_t step, + const uint8_t *input_external, + size_t input_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; + const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg, + operation->primitive, + step); + LOCAL_INPUT_DECLARE(input_external, input); + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = psa_pake_complete_inputs(operation); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (input_length == 0 || input_length > max_input_length) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT); + if (status != PSA_SUCCESS) { + goto exit; + } + driver_step = convert_jpake_computation_stage_to_driver_step( + &operation->computation_stage.jpake); + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + (void) step; + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_pake_input(operation, driver_step, + input, input_length); + + if (status != PSA_SUCCESS) { + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT); + if (status != PSA_SUCCESS) { + goto exit; + } + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + +exit: + LOCAL_INPUT_FREE(input_external, input); + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + return status; +} + +psa_status_t psa_pake_get_implicit_key( + psa_pake_operation_t *operation, + psa_key_derivation_operation_t *output) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]; + size_t shared_key_len = 0; + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + +#if defined(PSA_WANT_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + psa_jpake_computation_stage_t *computation_stage = + &operation->computation_stage.jpake; + if (computation_stage->round != PSA_JPAKE_FINISHED) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + } else +#endif /* PSA_WANT_ALG_JPAKE */ + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + status = psa_driver_wrapper_pake_get_implicit_key(operation, + shared_key, + sizeof(shared_key), + &shared_key_len); + + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_key_derivation_input_bytes(output, + PSA_KEY_DERIVATION_INPUT_SECRET, + shared_key, + shared_key_len); + + mbedtls_platform_zeroize(shared_key, sizeof(shared_key)); +exit: + abort_status = psa_pake_abort(operation); + return status == PSA_SUCCESS ? abort_status : status; +} + +psa_status_t psa_pake_abort( + psa_pake_operation_t *operation) +{ + psa_status_t status = PSA_SUCCESS; + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = psa_driver_wrapper_pake_abort(operation); + } + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + if (operation->data.inputs.password != NULL) { + mbedtls_zeroize_and_free(operation->data.inputs.password, + operation->data.inputs.password_len); + } + if (operation->data.inputs.user != NULL) { + mbedtls_free(operation->data.inputs.user); + } + if (operation->data.inputs.peer != NULL) { + mbedtls_free(operation->data.inputs.peer); + } + } + memset(operation, 0, sizeof(psa_pake_operation_t)); + + return status; +} +#endif /* PSA_WANT_ALG_SOME_PAKE */ + +/* Memory copying test hooks. These are called before input copy, after input + * copy, before output copy and after output copy, respectively. + * They are used by memory-poisoning tests to temporarily unpoison buffers + * while they are copied. */ +#if defined(MBEDTLS_TEST_HOOKS) +void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL; +void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL; +void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL; +void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL; +#endif + +/** Copy from an input buffer to a local copy. + * + * \param[in] input Pointer to input buffer. + * \param[in] input_len Length of the input buffer. + * \param[out] input_copy Pointer to a local copy in which to store the input data. + * \param[out] input_copy_len Length of the local copy buffer. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_CORRUPTION_DETECTED, if the local + * copy is too small to hold contents of the + * input buffer. + */ +MBEDTLS_STATIC_TESTABLE +psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, + uint8_t *input_copy, size_t input_copy_len) +{ + if (input_len > input_copy_len) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_input_pre_copy_hook != NULL) { + psa_input_pre_copy_hook(input, input_len); + } +#endif + + if (input_len > 0) { + memcpy(input_copy, input, input_len); + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_input_post_copy_hook != NULL) { + psa_input_post_copy_hook(input, input_len); + } +#endif + + return PSA_SUCCESS; +} + +/** Copy from a local output buffer into a user-supplied one. + * + * \param[in] output_copy Pointer to a local buffer containing the output. + * \param[in] output_copy_len Length of the local buffer. + * \param[out] output Pointer to user-supplied output buffer. + * \param[out] output_len Length of the user-supplied output buffer. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_BUFFER_TOO_SMALL, if the + * user-supplied output buffer is too small to + * hold the contents of the local buffer. + */ +MBEDTLS_STATIC_TESTABLE +psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, + uint8_t *output, size_t output_len) +{ + if (output_len < output_copy_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_output_pre_copy_hook != NULL) { + psa_output_pre_copy_hook(output, output_len); + } +#endif + + if (output_copy_len > 0) { + memcpy(output, output_copy, output_copy_len); + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_output_post_copy_hook != NULL) { + psa_output_post_copy_hook(output, output_len); + } +#endif + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, + psa_crypto_local_input_t *local_input) +{ + psa_status_t status; + + *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT; + + if (input_len == 0) { + return PSA_SUCCESS; + } + + local_input->buffer = mbedtls_calloc(input_len, 1); + if (local_input->buffer == NULL) { + /* Since we dealt with the zero-length case above, we know that + * a NULL return value means a failure of allocation. */ + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + /* From now on, we must free local_input->buffer on error. */ + + local_input->length = input_len; + + status = psa_crypto_copy_input(input, input_len, + local_input->buffer, local_input->length); + if (status != PSA_SUCCESS) { + goto error; + } + + return PSA_SUCCESS; + +error: + mbedtls_free(local_input->buffer); + local_input->buffer = NULL; + local_input->length = 0; + return status; +} + +void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input) +{ + mbedtls_free(local_input->buffer); + local_input->buffer = NULL; + local_input->length = 0; +} + +psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, + psa_crypto_local_output_t *local_output) +{ + *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; + + if (output_len == 0) { + return PSA_SUCCESS; + } + local_output->buffer = mbedtls_calloc(output_len, 1); + if (local_output->buffer == NULL) { + /* Since we dealt with the zero-length case above, we know that + * a NULL return value means a failure of allocation. */ + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + local_output->length = output_len; + local_output->original = output; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output) +{ + psa_status_t status; + + if (local_output->buffer == NULL) { + local_output->length = 0; + return PSA_SUCCESS; + } + if (local_output->original == NULL) { + /* We have an internal copy but nothing to copy back to. */ + return PSA_ERROR_CORRUPTION_DETECTED; + } + + status = psa_crypto_copy_output(local_output->buffer, local_output->length, + local_output->original, local_output->length); + if (status != PSA_SUCCESS) { + return status; + } + + mbedtls_free(local_output->buffer); + local_output->buffer = NULL; + local_output->length = 0; + + return PSA_SUCCESS; +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_aead.c b/thirdparty/mbedtls/library/psa_crypto_aead.c new file mode 100644 index 0000000000..a201985b4f --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_aead.c @@ -0,0 +1,649 @@ +/* + * PSA AEAD entry points + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_aead.h" +#include "psa_crypto_core.h" +#include "psa_crypto_cipher.h" + +#include <string.h> +#include "mbedtls/platform.h" + +#include "mbedtls/ccm.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/gcm.h" +#include "mbedtls/error.h" + +static psa_status_t psa_aead_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_cipher_id_t cipher_id; + mbedtls_cipher_mode_t mode; + size_t key_bits = attributes->bits; + (void) key_buffer_size; + + status = mbedtls_cipher_values_from_psa(alg, attributes->type, + &key_bits, &mode, &cipher_id); + if (status != PSA_SUCCESS) { + return status; + } + + switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): + operation->alg = PSA_ALG_CCM; + /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. + * The call to mbedtls_ccm_encrypt_and_tag or + * mbedtls_ccm_auth_decrypt will validate the tag length. */ + if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + mbedtls_ccm_init(&operation->ctx.ccm); + status = mbedtls_to_psa_error( + mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id, + key_buffer, (unsigned int) key_bits)); + if (status != PSA_SUCCESS) { + return status; + } + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): + operation->alg = PSA_ALG_GCM; + /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. + * The call to mbedtls_gcm_crypt_and_tag or + * mbedtls_gcm_auth_decrypt will validate the tag length. */ + if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + mbedtls_gcm_init(&operation->ctx.gcm); + status = mbedtls_to_psa_error( + mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id, + key_buffer, (unsigned int) key_bits)); + if (status != PSA_SUCCESS) { + return status; + } + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): + operation->alg = PSA_ALG_CHACHA20_POLY1305; + /* We only support the default tag length. */ + if (alg != PSA_ALG_CHACHA20_POLY1305) { + return PSA_ERROR_NOT_SUPPORTED; + } + + mbedtls_chachapoly_init(&operation->ctx.chachapoly); + status = mbedtls_to_psa_error( + mbedtls_chachapoly_setkey(&operation->ctx.chachapoly, + key_buffer)); + if (status != PSA_SUCCESS) { + return status; + } + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + + default: + (void) status; + (void) key_buffer; + return PSA_ERROR_NOT_SUPPORTED; + } + + operation->key_type = psa_get_key_type(attributes); + + operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); + + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_aead_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *plaintext, size_t plaintext_length, + uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; + uint8_t *tag; + + status = psa_aead_setup(&operation, attributes, key_buffer, + key_buffer_size, alg); + + if (status != PSA_SUCCESS) { + goto exit; + } + + /* For all currently supported modes, the tag is at the end of the + * ciphertext. */ + if (ciphertext_size < (plaintext_length + operation.tag_length)) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + tag = ciphertext + plaintext_length; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation.alg == PSA_ALG_CCM) { + status = mbedtls_to_psa_error( + mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm, + plaintext_length, + nonce, nonce_length, + additional_data, + additional_data_length, + plaintext, ciphertext, + tag, operation.tag_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation.alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm, + MBEDTLS_GCM_ENCRYPT, + plaintext_length, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, ciphertext, + operation.tag_length, tag)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { + if (operation.tag_length != 16) { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly, + plaintext_length, + nonce, + additional_data, + additional_data_length, + plaintext, + ciphertext, + tag)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) tag; + (void) nonce; + (void) nonce_length; + (void) additional_data; + (void) additional_data_length; + (void) plaintext; + return PSA_ERROR_NOT_SUPPORTED; + } + + if (status == PSA_SUCCESS) { + *ciphertext_length = plaintext_length + operation.tag_length; + } + +exit: + mbedtls_psa_aead_abort(&operation); + + return status; +} + +/* Locate the tag in a ciphertext buffer containing the encrypted data + * followed by the tag. Return the length of the part preceding the tag in + * *plaintext_length. This is the size of the plaintext in modes where + * the encrypted data has the same size as the plaintext, such as + * CCM and GCM. */ +static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + size_t plaintext_size, + const uint8_t **p_tag) +{ + size_t payload_length; + if (tag_length > ciphertext_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + payload_length = ciphertext_length - tag_length; + if (payload_length > plaintext_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + *p_tag = ciphertext + payload_length; + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_aead_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *ciphertext, size_t ciphertext_length, + uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; + const uint8_t *tag = NULL; + + status = psa_aead_setup(&operation, attributes, key_buffer, + key_buffer_size, alg); + + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_aead_unpadded_locate_tag(operation.tag_length, + ciphertext, ciphertext_length, + plaintext_size, &tag); + if (status != PSA_SUCCESS) { + goto exit; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation.alg == PSA_ALG_CCM) { + status = mbedtls_to_psa_error( + mbedtls_ccm_auth_decrypt(&operation.ctx.ccm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + ciphertext, plaintext, + tag, operation.tag_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation.alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_auth_decrypt(&operation.ctx.gcm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + tag, operation.tag_length, + ciphertext, plaintext)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { + if (operation.tag_length != 16) { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly, + ciphertext_length - operation.tag_length, + nonce, + additional_data, + additional_data_length, + tag, + ciphertext, + plaintext)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) nonce; + (void) nonce_length; + (void) additional_data; + (void) additional_data_length; + (void) plaintext; + return PSA_ERROR_NOT_SUPPORTED; + } + + if (status == PSA_SUCCESS) { + *plaintext_length = ciphertext_length - operation.tag_length; + } + +exit: + mbedtls_psa_aead_abort(&operation); + + if (status == PSA_SUCCESS) { + *plaintext_length = ciphertext_length - operation.tag_length; + } + return status; +} + +/* Set the key and algorithm for a multipart authenticated encryption + * operation. */ +psa_status_t mbedtls_psa_aead_encrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_aead_setup(operation, attributes, key_buffer, + key_buffer_size, alg); + + if (status == PSA_SUCCESS) { + operation->is_encrypt = 1; + } + + return status; +} + +/* Set the key and algorithm for a multipart authenticated decryption + * operation. */ +psa_status_t mbedtls_psa_aead_decrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_aead_setup(operation, attributes, key_buffer, + key_buffer_size, alg); + + if (status == PSA_SUCCESS) { + operation->is_encrypt = 0; + } + + return status; +} + +/* Set a nonce for the multipart AEAD operation*/ +psa_status_t mbedtls_psa_aead_set_nonce( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_starts(&operation->ctx.gcm, + operation->is_encrypt ? + MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, + nonce, + nonce_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + status = mbedtls_to_psa_error( + mbedtls_ccm_starts(&operation->ctx.ccm, + operation->is_encrypt ? + MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, + nonce, + nonce_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to + * allocate a buffer in the operation, copy the nonce to it and pad + * it, so for now check the nonce is 12 bytes, as + * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the + * passed in buffer. */ + if (nonce_length != 12) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_starts(&operation->ctx.chachapoly, + nonce, + operation->is_encrypt ? + MBEDTLS_CHACHAPOLY_ENCRYPT : + MBEDTLS_CHACHAPOLY_DECRYPT)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) operation; + (void) nonce; + (void) nonce_length; + + return PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + +/* Declare the lengths of the message and additional data for AEAD. */ +psa_status_t mbedtls_psa_aead_set_lengths( + mbedtls_psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + return mbedtls_to_psa_error( + mbedtls_ccm_set_lengths(&operation->ctx.ccm, + ad_length, + plaintext_length, + operation->tag_length)); + + } +#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + (void) operation; + (void) ad_length; + (void) plaintext_length; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + + return PSA_SUCCESS; +} + +/* Pass additional data to an active multipart AEAD operation. */ +psa_status_t mbedtls_psa_aead_update_ad( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + status = mbedtls_to_psa_error( + mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + status = mbedtls_to_psa_error( + mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly, + input, + input_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) operation; + (void) input; + (void) input_length; + + return PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + +/* Encrypt or decrypt a message fragment in an active multipart AEAD + * operation.*/ +psa_status_t mbedtls_psa_aead_update( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + size_t update_output_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + update_output_length = input_length; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_update(&operation->ctx.gcm, + input, input_length, + output, output_size, + &update_output_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + if (output_size < input_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_ccm_update(&operation->ctx.ccm, + input, input_length, + output, output_size, + &update_output_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + if (output_size < input_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_update(&operation->ctx.chachapoly, + input_length, + input, + output)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) operation; + (void) input; + (void) output; + (void) output_size; + + return PSA_ERROR_NOT_SUPPORTED; + } + + if (status == PSA_SUCCESS) { + *output_length = update_output_length; + } + + return status; +} + +/* Finish encrypting a message in a multipart AEAD operation. */ +psa_status_t mbedtls_psa_aead_finish( + mbedtls_psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t finish_output_size = 0; + + if (tag_size < operation->tag_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_finish(&operation->ctx.gcm, + ciphertext, ciphertext_size, ciphertext_length, + tag, operation->tag_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + /* tag must be big enough to store a tag of size passed into set + * lengths. */ + if (tag_size < operation->tag_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_ccm_finish(&operation->ctx.ccm, + tag, operation->tag_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + /* Belt and braces. Although the above tag_size check should have + * already done this, if we later start supporting smaller tag sizes + * for chachapoly, then passing a tag buffer smaller than 16 into here + * could cause a buffer overflow, so better safe than sorry. */ + if (tag_size < 16) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_finish(&operation->ctx.chachapoly, + tag)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) ciphertext; + (void) ciphertext_size; + (void) ciphertext_length; + (void) tag; + (void) tag_size; + (void) tag_length; + + return PSA_ERROR_NOT_SUPPORTED; + } + + if (status == PSA_SUCCESS) { + /* This will be zero for all supported algorithms currently, but left + * here for future support. */ + *ciphertext_length = finish_output_size; + *tag_length = operation->tag_length; + } + + return status; +} + +/* Abort an AEAD operation */ +psa_status_t mbedtls_psa_aead_abort( + mbedtls_psa_aead_operation_t *operation) +{ + switch (operation->alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + case PSA_ALG_CCM: + mbedtls_ccm_free(&operation->ctx.ccm); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + case PSA_ALG_GCM: + mbedtls_gcm_free(&operation->ctx.gcm); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + mbedtls_chachapoly_free(&operation->ctx.chachapoly); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + } + + operation->is_encrypt = 0; + + return PSA_SUCCESS; +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_cipher.c b/thirdparty/mbedtls/library/psa_crypto_cipher.c new file mode 100644 index 0000000000..3216c94898 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_cipher.c @@ -0,0 +1,724 @@ +/* + * PSA cipher driver entry points + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_random_impl.h" + +#include "mbedtls/cipher.h" +#include "mbedtls/error.h" + +#include <string.h> + +/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols + * are enabled, but it does not provide any compatibility check between them + * (i.e. if the specified key works with the specified algorithm). This helper + * function is meant to provide this support. + * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it + * requires CIPHER_C to be enabled. + */ +static psa_status_t mbedtls_cipher_validate_values( + psa_algorithm_t alg, + psa_key_type_t key_type) +{ + /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to + eliminate bits of the logic below. */ +#if !defined(PSA_WANT_KEY_TYPE_AES) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES); +#endif +#if !defined(PSA_WANT_KEY_TYPE_ARIA) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA); +#endif +#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA); +#endif +#if !defined(PSA_WANT_KEY_TYPE_CHACHA20) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20); +#endif +#if !defined(PSA_WANT_KEY_TYPE_DES) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES); +#endif +#if !defined(PSA_WANT_ALG_CCM) + MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0)); +#endif +#if !defined(PSA_WANT_ALG_GCM) + MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0)); +#endif +#if !defined(PSA_WANT_ALG_STREAM_CIPHER) + MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER); +#endif +#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305) + MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)); +#endif +#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) + MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG); +#endif +#if !defined(PSA_WANT_ALG_CTR) + MBEDTLS_ASSUME(alg != PSA_ALG_CTR); +#endif +#if !defined(PSA_WANT_ALG_CFB) + MBEDTLS_ASSUME(alg != PSA_ALG_CFB); +#endif +#if !defined(PSA_WANT_ALG_OFB) + MBEDTLS_ASSUME(alg != PSA_ALG_OFB); +#endif +#if !defined(PSA_WANT_ALG_XTS) + MBEDTLS_ASSUME(alg != PSA_ALG_XTS); +#endif +#if !defined(PSA_WANT_ALG_ECB_NO_PADDING) + MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING); +#endif +#if !defined(PSA_WANT_ALG_CBC_NO_PADDING) + MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING); +#endif +#if !defined(PSA_WANT_ALG_CBC_PKCS7) + MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7); +#endif +#if !defined(PSA_WANT_ALG_CMAC) + MBEDTLS_ASSUME(alg != PSA_ALG_CMAC); +#endif + + if (alg == PSA_ALG_STREAM_CIPHER || + alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) { + if (key_type == PSA_KEY_TYPE_CHACHA20) { + return PSA_SUCCESS; + } + } + + if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) || + alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) || + alg == PSA_ALG_CCM_STAR_NO_TAG) { + if (key_type == PSA_KEY_TYPE_AES || + key_type == PSA_KEY_TYPE_ARIA || + key_type == PSA_KEY_TYPE_CAMELLIA) { + return PSA_SUCCESS; + } + } + + if (alg == PSA_ALG_CTR || + alg == PSA_ALG_CFB || + alg == PSA_ALG_OFB || + alg == PSA_ALG_XTS || + alg == PSA_ALG_ECB_NO_PADDING || + alg == PSA_ALG_CBC_NO_PADDING || + alg == PSA_ALG_CBC_PKCS7 || + alg == PSA_ALG_CMAC) { + if (key_type == PSA_KEY_TYPE_AES || + key_type == PSA_KEY_TYPE_ARIA || + key_type == PSA_KEY_TYPE_DES || + key_type == PSA_KEY_TYPE_CAMELLIA) { + return PSA_SUCCESS; + } + } + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t mbedtls_cipher_values_from_psa( + psa_algorithm_t alg, + psa_key_type_t key_type, + size_t *key_bits, + mbedtls_cipher_mode_t *mode, + mbedtls_cipher_id_t *cipher_id) +{ + mbedtls_cipher_id_t cipher_id_tmp; + /* Only DES modifies key_bits */ +#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + (void) key_bits; +#endif + + if (PSA_ALG_IS_AEAD(alg)) { + alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0); + } + + if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) { + switch (alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) + case PSA_ALG_STREAM_CIPHER: + *mode = MBEDTLS_MODE_STREAM; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) + case PSA_ALG_CTR: + *mode = MBEDTLS_MODE_CTR; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) + case PSA_ALG_CFB: + *mode = MBEDTLS_MODE_CFB; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) + case PSA_ALG_OFB: + *mode = MBEDTLS_MODE_OFB; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) + case PSA_ALG_ECB_NO_PADDING: + *mode = MBEDTLS_MODE_ECB; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) + case PSA_ALG_CBC_NO_PADDING: + *mode = MBEDTLS_MODE_CBC; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) + case PSA_ALG_CBC_PKCS7: + *mode = MBEDTLS_MODE_CBC; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) + case PSA_ALG_CCM_STAR_NO_TAG: + *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): + *mode = MBEDTLS_MODE_CCM; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): + *mode = MBEDTLS_MODE_GCM; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): + *mode = MBEDTLS_MODE_CHACHAPOLY; + break; +#endif + default: + return PSA_ERROR_NOT_SUPPORTED; + } + } else if (alg == PSA_ALG_CMAC) { + *mode = MBEDTLS_MODE_ECB; + } else { + return PSA_ERROR_NOT_SUPPORTED; + } + + switch (key_type) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES) + case PSA_KEY_TYPE_AES: + cipher_id_tmp = MBEDTLS_CIPHER_ID_AES; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA) + case PSA_KEY_TYPE_ARIA: + cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + case PSA_KEY_TYPE_DES: + /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, + * and 192 for three-key Triple-DES. */ + if (*key_bits == 64) { + cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; + } else { + cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; + } + /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, + * but two-key Triple-DES is functionally three-key Triple-DES + * with K1=K3, so that's how we present it to mbedtls. */ + if (*key_bits == 128) { + *key_bits = 192; + } + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA) + case PSA_KEY_TYPE_CAMELLIA: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) + case PSA_KEY_TYPE_CHACHA20: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; + break; +#endif + default: + return PSA_ERROR_NOT_SUPPORTED; + } + if (cipher_id != NULL) { + *cipher_id = cipher_id_tmp; + } + + return mbedtls_cipher_validate_values(alg, key_type); +} + +#if defined(MBEDTLS_CIPHER_C) +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( + psa_algorithm_t alg, + psa_key_type_t key_type, + size_t key_bits, + mbedtls_cipher_id_t *cipher_id) +{ + mbedtls_cipher_mode_t mode; + psa_status_t status; + mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE; + + status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp); + if (status != PSA_SUCCESS) { + return NULL; + } + if (cipher_id != NULL) { + *cipher_id = cipher_id_tmp; + } + + return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode); +} +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + +static psa_status_t psa_cipher_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + mbedtls_operation_t cipher_operation) +{ + int ret = 0; + size_t key_bits; + const mbedtls_cipher_info_t *cipher_info = NULL; + psa_key_type_t key_type = attributes->type; + + (void) key_buffer_size; + + mbedtls_cipher_init(&operation->ctx.cipher); + + operation->alg = alg; + key_bits = attributes->bits; + cipher_info = mbedtls_cipher_info_from_psa(alg, key_type, + key_bits, NULL); + if (cipher_info == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + + ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info); + if (ret != 0) { + goto exit; + } + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) { + /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ + uint8_t keys[24]; + memcpy(keys, key_buffer, 16); + memcpy(keys + 16, key_buffer, 8); + ret = mbedtls_cipher_setkey(&operation->ctx.cipher, + keys, + 192, cipher_operation); + } else +#endif + { + ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer, + (int) key_bits, cipher_operation); + } + if (ret != 0) { + goto exit; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) + switch (alg) { + case PSA_ALG_CBC_NO_PADDING: + ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher, + MBEDTLS_PADDING_NONE); + break; + case PSA_ALG_CBC_PKCS7: + ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher, + MBEDTLS_PADDING_PKCS7); + break; + default: + /* The algorithm doesn't involve padding. */ + ret = 0; + break; + } + if (ret != 0) { + goto exit; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING || + MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */ + + operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 : + PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type)); + operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg); + +exit: + return mbedtls_to_psa_error(ret); +} + +psa_status_t mbedtls_psa_cipher_encrypt_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg) +{ + return psa_cipher_setup(operation, attributes, + key_buffer, key_buffer_size, + alg, MBEDTLS_ENCRYPT); +} + +psa_status_t mbedtls_psa_cipher_decrypt_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg) +{ + return psa_cipher_setup(operation, attributes, + key_buffer, key_buffer_size, + alg, MBEDTLS_DECRYPT); +} + +psa_status_t mbedtls_psa_cipher_set_iv( + mbedtls_psa_cipher_operation_t *operation, + const uint8_t *iv, size_t iv_length) +{ + if (iv_length != operation->iv_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return mbedtls_to_psa_error( + mbedtls_cipher_set_iv(&operation->ctx.cipher, + iv, iv_length)); +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) +/** Process input for which the algorithm is set to ECB mode. + * + * This requires manual processing, since the PSA API is defined as being + * able to process arbitrary-length calls to psa_cipher_update() with ECB mode, + * but the underlying mbedtls_cipher_update only takes full blocks. + * + * \param ctx The mbedtls cipher context to use. It must have been + * set up for ECB. + * \param[in] input The input plaintext or ciphertext to process. + * \param input_length The number of bytes to process from \p input. + * This does not need to be aligned to a block boundary. + * If there is a partial block at the end of the input, + * it is stored in \p ctx for future processing. + * \param output The buffer where the output is written. It must be + * at least `BS * floor((p + input_length) / BS)` bytes + * long, where `p` is the number of bytes in the + * unprocessed partial block in \p ctx (with + * `0 <= p <= BS - 1`) and `BS` is the block size. + * \param output_length On success, the number of bytes written to \p output. + * \c 0 on error. + * + * \return #PSA_SUCCESS or an error from a hardware accelerator + */ +static psa_status_t psa_cipher_update_ecb( + mbedtls_cipher_context_t *ctx, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); + size_t internal_output_length = 0; + *output_length = 0; + + if (input_length == 0) { + status = PSA_SUCCESS; + goto exit; + } + + if (ctx->unprocessed_len > 0) { + /* Fill up to block size, and run the block if there's a full one. */ + size_t bytes_to_copy = block_size - ctx->unprocessed_len; + + if (input_length < bytes_to_copy) { + bytes_to_copy = input_length; + } + + memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), + input, bytes_to_copy); + input_length -= bytes_to_copy; + input += bytes_to_copy; + ctx->unprocessed_len += bytes_to_copy; + + if (ctx->unprocessed_len == block_size) { + status = mbedtls_to_psa_error( + mbedtls_cipher_update(ctx, + ctx->unprocessed_data, + block_size, + output, &internal_output_length)); + + if (status != PSA_SUCCESS) { + goto exit; + } + + output += internal_output_length; + *output_length += internal_output_length; + ctx->unprocessed_len = 0; + } + } + + while (input_length >= block_size) { + /* Run all full blocks we have, one by one */ + status = mbedtls_to_psa_error( + mbedtls_cipher_update(ctx, input, + block_size, + output, &internal_output_length)); + + if (status != PSA_SUCCESS) { + goto exit; + } + + input_length -= block_size; + input += block_size; + + output += internal_output_length; + *output_length += internal_output_length; + } + + if (input_length > 0) { + /* Save unprocessed bytes for later processing */ + memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), + input, input_length); + ctx->unprocessed_len += input_length; + } + + status = PSA_SUCCESS; + +exit: + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ + +psa_status_t mbedtls_psa_cipher_update( + mbedtls_psa_cipher_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t expected_output_size; + + if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) { + /* Take the unprocessed partial block left over from previous + * update calls, if any, plus the input to this call. Remove + * the last partial block, if any. You get the data that will be + * output in this call. */ + expected_output_size = + (operation->ctx.cipher.unprocessed_len + input_length) + / operation->block_length * operation->block_length; + } else { + expected_output_size = input_length; + } + + if (output_size < expected_output_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) + if (operation->alg == PSA_ALG_ECB_NO_PADDING) { + /* mbedtls_cipher_update has an API inconsistency: it will only + * process a single block at a time in ECB mode. Abstract away that + * inconsistency here to match the PSA API behaviour. */ + status = psa_cipher_update_ecb(&operation->ctx.cipher, + input, + input_length, + output, + output_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ + if (input_length == 0) { + /* There is no input, nothing to be done */ + *output_length = 0; + status = PSA_SUCCESS; + } else { + status = mbedtls_to_psa_error( + mbedtls_cipher_update(&operation->ctx.cipher, input, + input_length, output, output_length)); + + if (*output_length > output_size) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + } + + return status; +} + +psa_status_t mbedtls_psa_cipher_finish( + mbedtls_psa_cipher_operation_t *operation, + uint8_t *output, size_t output_size, size_t *output_length) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + + if (operation->ctx.cipher.unprocessed_len != 0) { + if (operation->alg == PSA_ALG_ECB_NO_PADDING || + operation->alg == PSA_ALG_CBC_NO_PADDING) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + } + + status = mbedtls_to_psa_error( + mbedtls_cipher_finish(&operation->ctx.cipher, + temp_output_buffer, + output_length)); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (*output_length == 0) { + ; /* Nothing to copy. Note that output may be NULL in this case. */ + } else if (output_size >= *output_length) { + memcpy(output, temp_output_buffer, *output_length); + } else { + status = PSA_ERROR_BUFFER_TOO_SMALL; + } + +exit: + mbedtls_platform_zeroize(temp_output_buffer, + sizeof(temp_output_buffer)); + + return status; +} + +psa_status_t mbedtls_psa_cipher_abort( + mbedtls_psa_cipher_operation_t *operation) +{ + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + if (!PSA_ALG_IS_CIPHER(operation->alg)) { + return PSA_ERROR_BAD_STATE; + } + + mbedtls_cipher_free(&operation->ctx.cipher); + + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *iv, + size_t iv_length, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; + size_t update_output_length, finish_output_length; + + status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes, + key_buffer, key_buffer_size, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (iv_length > 0) { + status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + status = mbedtls_psa_cipher_update(&operation, input, input_length, + output, output_size, + &update_output_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_psa_cipher_finish( + &operation, + mbedtls_buffer_offset(output, update_output_length), + output_size - update_output_length, &finish_output_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + *output_length = update_output_length + finish_output_length; + +exit: + if (status == PSA_SUCCESS) { + status = mbedtls_psa_cipher_abort(&operation); + } else { + mbedtls_psa_cipher_abort(&operation); + } + + return status; +} + +psa_status_t mbedtls_psa_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; + size_t olength, accumulated_length; + + status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes, + key_buffer, key_buffer_size, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (operation.iv_length > 0) { + status = mbedtls_psa_cipher_set_iv(&operation, + input, operation.iv_length); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + status = mbedtls_psa_cipher_update( + &operation, + mbedtls_buffer_offset_const(input, operation.iv_length), + input_length - operation.iv_length, + output, output_size, &olength); + if (status != PSA_SUCCESS) { + goto exit; + } + + accumulated_length = olength; + + status = mbedtls_psa_cipher_finish( + &operation, + mbedtls_buffer_offset(output, accumulated_length), + output_size - accumulated_length, &olength); + if (status != PSA_SUCCESS) { + goto exit; + } + + *output_length = accumulated_length + olength; + +exit: + if (status == PSA_SUCCESS) { + status = mbedtls_psa_cipher_abort(&operation); + } else { + mbedtls_psa_cipher_abort(&operation); + } + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_client.c b/thirdparty/mbedtls/library/psa_crypto_client.c new file mode 100644 index 0000000000..72f671d63d --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_client.c @@ -0,0 +1,22 @@ +/* + * PSA crypto client code + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" +#include "psa/crypto.h" + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) + +#include <string.h> +#include "mbedtls/platform.h" + +void psa_reset_key_attributes(psa_key_attributes_t *attributes) +{ + memset(attributes, 0, sizeof(*attributes)); +} + +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ diff --git a/thirdparty/mbedtls/library/psa_crypto_driver_wrappers_no_static.c b/thirdparty/mbedtls/library/psa_crypto_driver_wrappers_no_static.c new file mode 100644 index 0000000000..de8a5269b3 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_driver_wrappers_no_static.c @@ -0,0 +1,256 @@ +/* + * Functions to delegate cryptographic operations to an available + * and appropriate accelerator. + * Warning: This file is now auto-generated. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + + +/* BEGIN-common headers */ +#include "common.h" +#include "psa_crypto_aead.h" +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers_no_static.h" +#include "psa_crypto_hash.h" +#include "psa_crypto_mac.h" +#include "psa_crypto_pake.h" +#include "psa_crypto_rsa.h" + +#include "mbedtls/platform.h" +/* END-common headers */ + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* BEGIN-driver headers */ +/* Headers for mbedtls_test opaque driver */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include "test/drivers/test_driver.h" + +#endif +/* Headers for mbedtls_test transparent driver */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include "test/drivers/test_driver.h" + +#endif +/* Headers for p256 transparent driver */ +#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) +#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h" + +#endif + +/* END-driver headers */ + +/* Auto-generated values depending on which drivers are registered. + * ID 0 is reserved for unallocated operations. + * ID 1 is reserved for the Mbed TLS software driver. */ +/* BEGIN-driver id definition */ +#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) +#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2) +#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3) +#define P256_TRANSPARENT_DRIVER_ID (4) + +/* END-driver id */ + +/* BEGIN-Common Macro definitions */ + +/* END-Common Macro definitions */ + +/* Support the 'old' SE interface when asked to */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style + * SE driver is present, to avoid unused argument errors at compile time. */ +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#include "psa_crypto_se.h" +#endif + +/** Get the key buffer size required to store the key material of a key + * associated with an opaque driver. + * + * \param[in] attributes The key attributes. + * \param[out] key_buffer_size Minimum buffer size to contain the key material + * + * \retval #PSA_SUCCESS + * The minimum size for a buffer to contain the key material has been + * returned successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is declared with a lifetime not known to us. + */ +psa_status_t psa_driver_wrapper_get_key_buffer_size( + const psa_key_attributes_t *attributes, + size_t *key_buffer_size ) +{ + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + psa_key_type_t key_type = psa_get_key_type(attributes); + size_t key_bits = psa_get_key_bits(attributes); + + *key_buffer_size = 0; + switch( location ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + /* Emulate property 'builtin_key_size' */ + if( psa_key_id_is_builtin( + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( + psa_get_key_id( attributes ) ) ) ) + { + *key_buffer_size = sizeof( psa_drv_slot_number_t ); + return( PSA_SUCCESS ); + } +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + *key_buffer_size = mbedtls_test_opaque_size_function( key_type, + key_bits ); + return( ( *key_buffer_size != 0 ) ? + PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + + default: + (void)key_type; + (void)key_bits; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) + +{ + + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export_public == NULL ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( drv->key_management->p_export_public( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + status = mbedtls_test_transparent_export_public_key + (attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length + ); + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + +#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) ) + status = p256_transparent_export_public_key + (attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length + ); + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + /* Fell through, meaning no accelerator supports this operation */ + return( psa_export_public_key_internal( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + case 0x7fffff: + return( mbedtls_test_opaque_export_public_key + (attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length + )); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } + +} + +psa_status_t psa_driver_wrapper_get_builtin_key( + psa_drv_slot_number_t slot_number, + psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + switch( location ) + { +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + case 0x7fffff: + return( mbedtls_test_opaque_get_builtin_key + (slot_number, + attributes, + key_buffer, + key_buffer_size, + key_buffer_length + )); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) slot_number; + (void) key_buffer; + (void) key_buffer_size; + (void) key_buffer_length; + return( PSA_ERROR_DOES_NOT_EXIST ); + } + +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_ecp.c b/thirdparty/mbedtls/library/psa_crypto_ecp.c new file mode 100644 index 0000000000..95baff6a0f --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_ecp.c @@ -0,0 +1,596 @@ +/* + * PSA ECP layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include <psa/crypto.h> +#include "psa_crypto_core.h" +#include "psa_crypto_ecp.h" +#include "psa_crypto_random_impl.h" +#include "mbedtls/psa_util.h" + +#include <stdlib.h> +#include <string.h> +#include "mbedtls/platform.h" + +#include <mbedtls/ecdsa.h> +#include <mbedtls/ecdh.h> +#include <mbedtls/ecp.h> +#include <mbedtls/error.h> + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +/* Helper function to verify if the provided EC's family and key bit size are valid. + * + * Note: "bits" parameter is used both as input and output and it might be updated + * in case provided input value is not multiple of 8 ("sloppy" bits). + */ +static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits) +{ + switch (family) { + case PSA_ECC_FAMILY_SECP_R1: + switch (*bits) { + case 192: + case 224: + case 256: + case 384: + case 521: + return PSA_SUCCESS; + case 528: + *bits = 521; + return PSA_SUCCESS; + } + break; + + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch (*bits) { + case 256: + case 384: + case 512: + return PSA_SUCCESS; + } + break; + + case PSA_ECC_FAMILY_MONTGOMERY: + switch (*bits) { + case 448: + case 255: + return PSA_SUCCESS; + case 256: + *bits = 255; + return PSA_SUCCESS; + } + break; + + case PSA_ECC_FAMILY_SECP_K1: + switch (*bits) { + case 192: + /* secp224k1 is not and will not be supported in PSA (#3541). */ + case 256: + return PSA_SUCCESS; + } + break; + } + + return PSA_ERROR_INVALID_ARGUMENT; +} + +psa_status_t mbedtls_psa_ecp_load_representation( + psa_key_type_t type, size_t curve_bits, + const uint8_t *data, size_t data_length, + mbedtls_ecp_keypair **p_ecp) +{ + mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; + psa_status_t status; + mbedtls_ecp_keypair *ecp = NULL; + size_t curve_bytes = data_length; + int explicit_bits = (curve_bits != 0); + + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && + PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) { + /* A Weierstrass public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where m is the curve size in bits. + */ + if ((data_length & 1) == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + curve_bytes = data_length / 2; + + /* Montgomery public keys are represented in compressed format, meaning + * their curve_bytes is equal to the amount of input. */ + + /* Private keys are represented in uncompressed private random integer + * format, meaning their curve_bytes is equal to the amount of input. */ + } + + if (explicit_bits) { + /* With an explicit bit-size, the data must have the matching length. */ + if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } else { + /* We need to infer the bit-size from the data. Since the only + * information we have is the length in bytes, the value of curve_bits + * at this stage is rounded up to the nearest multiple of 8. */ + curve_bits = PSA_BYTES_TO_BITS(curve_bytes); + } + + /* Allocate and initialize a key representation. */ + ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); + if (ecp == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + mbedtls_ecp_keypair_init(ecp); + + status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* Load the group. */ + grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), + curve_bits); + if (grp_id == MBEDTLS_ECP_DP_NONE) { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_group_load(&ecp->grp, grp_id)); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* Load the key material. */ + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { + /* Load the public value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q, + data, + data_length)); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* Check that the point is on the curve. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q)); + if (status != PSA_SUCCESS) { + goto exit; + } + } else { + /* Load and validate the secret value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_read_key(ecp->grp.id, + ecp, + data, + data_length)); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + *p_ecp = ecp; +exit: + if (status != PSA_SUCCESS) { + mbedtls_ecp_keypair_free(ecp); + mbedtls_free(ecp); + } + + return status; +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + +psa_status_t mbedtls_psa_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits) +{ + psa_status_t status; + mbedtls_ecp_keypair *ecp = NULL; + + /* Parse input */ + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, + data, + data_length, + &ecp); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) == + PSA_ECC_FAMILY_MONTGOMERY) { + *bits = ecp->grp.nbits + 1; + } else { + *bits = ecp->grp.nbits; + } + + /* Re-export the data to PSA export format. There is currently no support + * for other input formats then the export format, so this is a 1-1 + * copy operation. */ + status = mbedtls_psa_ecp_export_key(attributes->type, + ecp, + key_buffer, + key_buffer_size, + key_buffer_length); +exit: + /* Always free the PK object (will also free contained ECP context) */ + mbedtls_ecp_keypair_free(ecp); + mbedtls_free(ecp); + + return status; +} + +psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type, + mbedtls_ecp_keypair *ecp, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_status_t status; + + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { + /* Check whether the public part is loaded */ + if (mbedtls_ecp_is_zero(&ecp->Q)) { + /* Calculate the public key */ + status = mbedtls_to_psa_error( + mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); + if (status != PSA_SUCCESS) { + return status; + } + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + data_length, + data, + data_size)); + if (status != PSA_SUCCESS) { + memset(data, 0, data_size); + } + + return status; + } else { + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size)); + return status; + } +} + +psa_status_t mbedtls_psa_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + + status = mbedtls_psa_ecp_load_representation( + attributes->type, attributes->bits, + key_buffer, key_buffer_size, &ecp); + if (status != PSA_SUCCESS) { + return status; + } + + status = mbedtls_psa_ecp_export_key( + PSA_KEY_TYPE_ECC_PUBLIC_KEY( + PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)), + ecp, data, data_size, data_length); + + mbedtls_ecp_keypair_free(ecp); + mbedtls_free(ecp); + + return status; +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) +psa_status_t mbedtls_psa_ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( + attributes->type); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_from_psa(curve, attributes->bits); + + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id(grp_id); + mbedtls_ecp_keypair ecp; + + if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + + mbedtls_ecp_keypair_init(&ecp); + ret = mbedtls_ecp_gen_key(grp_id, &ecp, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + if (ret != 0) { + mbedtls_ecp_keypair_free(&ecp); + return mbedtls_to_psa_error(ret); + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key_ext(&ecp, key_buffer_length, + key_buffer, key_buffer_size)); + + mbedtls_ecp_keypair_free(&ecp); + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ + +/****************************************************************/ +/* ECDSA sign/verify */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) +psa_status_t mbedtls_psa_ecdsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t curve_bytes; + mbedtls_mpi r, s; + + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &ecp); + if (status != PSA_SUCCESS) { + return status; + } + + curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + if (signature_size < 2 * curve_bytes) { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); + mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); + MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext( + &ecp->grp, &r, &s, + &ecp->d, hash, + hash_length, md_alg, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); +#else + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + } else { + (void) alg; + MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d, + hash, hash_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r, + signature, + curve_bytes)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s, + signature + curve_bytes, + curve_bytes)); +cleanup: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + if (ret == 0) { + *signature_length = 2 * curve_bytes; + } + + mbedtls_ecp_keypair_free(ecp); + mbedtls_free(ecp); + + return mbedtls_to_psa_error(ret); +} + +psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp) +{ + int ret = 0; + + /* Check whether the public part is loaded. If not, load it. */ + if (mbedtls_ecp_is_zero(&ecp->Q)) { + ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q, + &ecp->d, &ecp->grp.G, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + } + + return mbedtls_to_psa_error(ret); +} + +psa_status_t mbedtls_psa_ecdsa_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + size_t curve_bytes; + mbedtls_mpi r, s; + + (void) alg; + + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &ecp); + if (status != PSA_SUCCESS) { + return status; + } + + curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + if (signature_length != 2 * curve_bytes) { + status = PSA_ERROR_INVALID_SIGNATURE; + goto cleanup; + } + + status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r, + signature, + curve_bytes)); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s, + signature + curve_bytes, + curve_bytes)); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = mbedtls_psa_ecp_load_public_part(ecp); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash, + hash_length, &ecp->Q, + &r, &s)); +cleanup: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + mbedtls_ecp_keypair_free(ecp); + mbedtls_free(ecp); + + return status; +} + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + +/****************************************************************/ +/* ECDH Key Agreement */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +psa_status_t mbedtls_psa_key_agreement_ecdh( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, + uint8_t *shared_secret, size_t shared_secret_size, + size_t *shared_secret_length) +{ + psa_status_t status; + if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) || + !PSA_ALG_IS_ECDH(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + mbedtls_ecp_keypair *ecp = NULL; + status = mbedtls_psa_ecp_load_representation( + attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &ecp); + if (status != PSA_SUCCESS) { + return status; + } + mbedtls_ecp_keypair *their_key = NULL; + mbedtls_ecdh_context ecdh; + size_t bits = 0; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits); + mbedtls_ecdh_init(&ecdh); + + status = mbedtls_psa_ecp_load_representation( + PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), + bits, + peer_key, + peer_key_length, + &their_key); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS)); + if (status != PSA_SUCCESS) { + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecdh_calc_secret(&ecdh, + shared_secret_length, + shared_secret, shared_secret_size, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); + if (status != PSA_SUCCESS) { + goto exit; + } + if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) { + status = PSA_ERROR_CORRUPTION_DETECTED; + } +exit: + if (status != PSA_SUCCESS) { + mbedtls_platform_zeroize(shared_secret, shared_secret_size); + } + mbedtls_ecdh_free(&ecdh); + mbedtls_ecp_keypair_free(their_key); + mbedtls_free(their_key); + mbedtls_ecp_keypair_free(ecp); + mbedtls_free(ecp); + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ + + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_ffdh.c b/thirdparty/mbedtls/library/psa_crypto_ffdh.c new file mode 100644 index 0000000000..ae38f6d7c6 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_ffdh.c @@ -0,0 +1,321 @@ +/* + * PSA FFDH layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* This header is only needed because it defines + * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in + * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module + * only uses bignum functions for arithmetic. */ +#include <mbedtls/dhm.h> + +#include <psa/crypto.h> +#include "psa_crypto_core.h" +#include "psa_crypto_ffdh.h" +#include "psa_crypto_random_impl.h" +#include "mbedtls/platform.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) +static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size, + mbedtls_mpi *P, + mbedtls_mpi *G) +{ + const unsigned char *dhm_P = NULL; + const unsigned char *dhm_G = NULL; + size_t dhm_size_P = 0; + size_t dhm_size_G = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (P == NULL && G == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) + static const unsigned char dhm_P_2048[] = + MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN; + static const unsigned char dhm_G_2048[] = + MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) + static const unsigned char dhm_P_3072[] = + MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN; + static const unsigned char dhm_G_3072[] = + MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) + static const unsigned char dhm_P_4096[] = + MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN; + static const unsigned char dhm_G_4096[] = + MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) + static const unsigned char dhm_P_6144[] = + MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN; + static const unsigned char dhm_G_6144[] = + MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) + static const unsigned char dhm_P_8192[] = + MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN; + static const unsigned char dhm_G_8192[] = + MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ + + switch (key_size) { +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) + case sizeof(dhm_P_2048): + dhm_P = dhm_P_2048; + dhm_G = dhm_G_2048; + dhm_size_P = sizeof(dhm_P_2048); + dhm_size_G = sizeof(dhm_G_2048); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) + case sizeof(dhm_P_3072): + dhm_P = dhm_P_3072; + dhm_G = dhm_G_3072; + dhm_size_P = sizeof(dhm_P_3072); + dhm_size_G = sizeof(dhm_G_3072); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) + case sizeof(dhm_P_4096): + dhm_P = dhm_P_4096; + dhm_G = dhm_G_4096; + dhm_size_P = sizeof(dhm_P_4096); + dhm_size_G = sizeof(dhm_G_4096); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) + case sizeof(dhm_P_6144): + dhm_P = dhm_P_6144; + dhm_G = dhm_G_6144; + dhm_size_P = sizeof(dhm_P_6144); + dhm_size_G = sizeof(dhm_G_6144); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) + case sizeof(dhm_P_8192): + dhm_P = dhm_P_8192; + dhm_G = dhm_G_8192; + dhm_size_P = sizeof(dhm_P_8192); + dhm_size_G = sizeof(dhm_G_8192); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ + default: + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (P != NULL) { + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P, + dhm_size_P)); + } + if (G != NULL) { + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G, + dhm_size_G)); + } + +cleanup: + if (ret != 0) { + return mbedtls_to_psa_error(ret); + } + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || + MBEDTLS_PSA_BUILTIN_ALG_FFDH */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) +psa_status_t mbedtls_psa_ffdh_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi GX, G, X, P; + psa_key_type_t type = attributes->type; + + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { + if (key_buffer_size > data_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + memcpy(data, key_buffer, key_buffer_size); + memset(data + key_buffer_size, 0, + data_size - key_buffer_size); + *data_length = key_buffer_size; + return PSA_SUCCESS; + } + + mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G); + mbedtls_mpi_init(&X); mbedtls_mpi_init(&P); + + size_t key_len = PSA_BITS_TO_BYTES(attributes->bits); + + status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, + key_buffer_size)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len)); + + *data_length = key_len; + + ret = 0; +cleanup: + mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); + mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX); + + if (status == PSA_SUCCESS && ret != 0) { + status = mbedtls_to_psa_error(ret); + } + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) +psa_status_t mbedtls_psa_ffdh_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) +{ + mbedtls_mpi X, P; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_init(&P); mbedtls_mpi_init(&X); + (void) attributes; + + status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their + secret exponent from the range [2, P-2]. + Select random value in range [3, P-1] and decrease it by 1. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size)); + *key_buffer_length = key_buffer_size; + +cleanup: + mbedtls_mpi_free(&P); mbedtls_mpi_free(&X); + if (status == PSA_SUCCESS && ret != 0) { + return mbedtls_to_psa_error(ret); + } + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) +psa_status_t mbedtls_psa_ffdh_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits) +{ + (void) attributes; + + if (key_buffer_size < data_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + memcpy(key_buffer, data, data_length); + *key_buffer_length = data_length; + *bits = PSA_BYTES_TO_BITS(data_length); + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) +psa_status_t mbedtls_psa_ffdh_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *peer_key, + size_t peer_key_length, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi P, G, X, GY, K; + const size_t calculated_shared_secret_size = peer_key_length; + + if (peer_key_length != key_buffer_size || + calculated_shared_secret_size > shared_secret_size) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + mbedtls_mpi_init(&P); mbedtls_mpi_init(&G); + mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY); + mbedtls_mpi_init(&K); + + status = mbedtls_psa_ffdh_set_prime_generator( + PSA_BITS_TO_BYTES(attributes->bits), &P, &G); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, + key_buffer_size)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key, + peer_key_length)); + + /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */ + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret, + calculated_shared_secret_size)); + + *shared_secret_length = calculated_shared_secret_size; + + ret = 0; + +cleanup: + mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); + mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY); + mbedtls_mpi_free(&K); + + if (status == PSA_SUCCESS && ret != 0) { + status = mbedtls_to_psa_error(ret); + } + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_hash.c b/thirdparty/mbedtls/library/psa_crypto_hash.c new file mode 100644 index 0000000000..eeb7666c1c --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_hash.c @@ -0,0 +1,470 @@ +/* + * PSA hashing layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include <psa/crypto.h> +#include "psa_crypto_core.h" +#include "psa_crypto_hash.h" + +#include <mbedtls/error.h> +#include <string.h> + +#if defined(MBEDTLS_PSA_BUILTIN_HASH) +psa_status_t mbedtls_psa_hash_abort( + mbedtls_psa_hash_operation_t *operation) +{ + switch (operation->alg) { + case 0: + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + break; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + mbedtls_md5_free(&operation->ctx.md5); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_free(&operation->ctx.ripemd160); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + mbedtls_sha1_free(&operation->ctx.sha1); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + mbedtls_sha256_free(&operation->ctx.sha256); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + mbedtls_sha256_free(&operation->ctx.sha256); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + mbedtls_sha512_free(&operation->ctx.sha512); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + mbedtls_sha512_free(&operation->ctx.sha512); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + mbedtls_sha3_free(&operation->ctx.sha3); + break; +#endif + default: + return PSA_ERROR_BAD_STATE; + } + operation->alg = 0; + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_hash_setup( + mbedtls_psa_hash_operation_t *operation, + psa_algorithm_t alg) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if (operation->alg != 0) { + return PSA_ERROR_BAD_STATE; + } + + switch (alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + mbedtls_md5_init(&operation->ctx.md5); + ret = mbedtls_md5_starts(&operation->ctx.md5); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_init(&operation->ctx.ripemd160); + ret = mbedtls_ripemd160_starts(&operation->ctx.ripemd160); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + mbedtls_sha1_init(&operation->ctx.sha1); + ret = mbedtls_sha1_starts(&operation->ctx.sha1); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + mbedtls_sha256_init(&operation->ctx.sha256); + ret = mbedtls_sha256_starts(&operation->ctx.sha256, 1); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + mbedtls_sha256_init(&operation->ctx.sha256); + ret = mbedtls_sha256_starts(&operation->ctx.sha256, 0); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + mbedtls_sha512_init(&operation->ctx.sha512); + ret = mbedtls_sha512_starts(&operation->ctx.sha512, 1); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + mbedtls_sha512_init(&operation->ctx.sha512); + ret = mbedtls_sha512_starts(&operation->ctx.sha512, 0); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_224); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_256); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_384); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_512); + break; +#endif + default: + return PSA_ALG_IS_HASH(alg) ? + PSA_ERROR_NOT_SUPPORTED : + PSA_ERROR_INVALID_ARGUMENT; + } + if (ret == 0) { + operation->alg = alg; + } else { + mbedtls_psa_hash_abort(operation); + } + return mbedtls_to_psa_error(ret); +} + +psa_status_t mbedtls_psa_hash_clone( + const mbedtls_psa_hash_operation_t *source_operation, + mbedtls_psa_hash_operation_t *target_operation) +{ + switch (source_operation->alg) { + case 0: + return PSA_ERROR_BAD_STATE; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + mbedtls_md5_clone(&target_operation->ctx.md5, + &source_operation->ctx.md5); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_clone(&target_operation->ctx.ripemd160, + &source_operation->ctx.ripemd160); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + mbedtls_sha1_clone(&target_operation->ctx.sha1, + &source_operation->ctx.sha1); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + mbedtls_sha256_clone(&target_operation->ctx.sha256, + &source_operation->ctx.sha256); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + mbedtls_sha256_clone(&target_operation->ctx.sha256, + &source_operation->ctx.sha256); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + mbedtls_sha512_clone(&target_operation->ctx.sha512, + &source_operation->ctx.sha512); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + mbedtls_sha512_clone(&target_operation->ctx.sha512, + &source_operation->ctx.sha512); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + mbedtls_sha3_clone(&target_operation->ctx.sha3, + &source_operation->ctx.sha3); + break; +#endif + default: + (void) source_operation; + (void) target_operation; + return PSA_ERROR_NOT_SUPPORTED; + } + + target_operation->alg = source_operation->alg; + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_hash_update( + mbedtls_psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + switch (operation->alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + ret = mbedtls_md5_update(&operation->ctx.md5, + input, input_length); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_update(&operation->ctx.ripemd160, + input, input_length); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_update(&operation->ctx.sha1, + input, input_length); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + ret = mbedtls_sha256_update(&operation->ctx.sha256, + input, input_length); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_update(&operation->ctx.sha256, + input, input_length); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + ret = mbedtls_sha512_update(&operation->ctx.sha512, + input, input_length); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_update(&operation->ctx.sha512, + input, input_length); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + ret = mbedtls_sha3_update(&operation->ctx.sha3, + input, input_length); + break; +#endif + default: + (void) input; + (void) input_length; + return PSA_ERROR_BAD_STATE; + } + + return mbedtls_to_psa_error(ret); +} + +psa_status_t mbedtls_psa_hash_finish( + mbedtls_psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t actual_hash_length = PSA_HASH_LENGTH(operation->alg); + + /* Fill the output buffer with something that isn't a valid hash + * (barring an attack on the hash and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + *hash_length = hash_size; + /* If hash_size is 0 then hash may be NULL and then the + * call to memset would have undefined behavior. */ + if (hash_size != 0) { + memset(hash, '!', hash_size); + } + + if (hash_size < actual_hash_length) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + switch (operation->alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + ret = mbedtls_md5_finish(&operation->ctx.md5, hash); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_finish(&operation->ctx.ripemd160, hash); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_finish(&operation->ctx.sha1, hash); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + ret = mbedtls_sha3_finish(&operation->ctx.sha3, hash, hash_size); + break; +#endif + default: + (void) hash; + return PSA_ERROR_BAD_STATE; + } + status = mbedtls_to_psa_error(ret); + +exit: + if (status == PSA_SUCCESS) { + *hash_length = actual_hash_length; + } + return status; +} + +psa_status_t mbedtls_psa_hash_compute( + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + + *hash_length = hash_size; + status = mbedtls_psa_hash_setup(&operation, alg); + if (status != PSA_SUCCESS) { + goto exit; + } + status = mbedtls_psa_hash_update(&operation, input, input_length); + if (status != PSA_SUCCESS) { + goto exit; + } + status = mbedtls_psa_hash_finish(&operation, hash, hash_size, hash_length); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + abort_status = mbedtls_psa_hash_abort(&operation); + if (status == PSA_SUCCESS) { + return abort_status; + } else { + return status; + } + +} +#endif /* MBEDTLS_PSA_BUILTIN_HASH */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_mac.c b/thirdparty/mbedtls/library/psa_crypto_mac.c new file mode 100644 index 0000000000..8fe6218118 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_mac.c @@ -0,0 +1,496 @@ +/* + * PSA MAC layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include <psa/crypto.h> +#include "psa_crypto_core.h" +#include "psa_crypto_cipher.h" +#include "psa_crypto_mac.h" +#include <mbedtls/md.h> + +#include <mbedtls/error.h> +#include "mbedtls/constant_time.h" +#include <string.h> + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) +static psa_status_t psa_hmac_abort_internal( + mbedtls_psa_hmac_operation_t *hmac) +{ + mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad)); + return psa_hash_abort(&hmac->hash_ctx); +} + +static psa_status_t psa_hmac_setup_internal( + mbedtls_psa_hmac_operation_t *hmac, + const uint8_t *key, + size_t key_length, + psa_algorithm_t hash_alg) +{ + uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; + size_t i; + size_t hash_size = PSA_HASH_LENGTH(hash_alg); + size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); + psa_status_t status; + + hmac->alg = hash_alg; + + /* Sanity checks on block_size, to guarantee that there won't be a buffer + * overflow below. This should never trigger if the hash algorithm + * is implemented correctly. */ + /* The size checks against the ipad and opad buffers cannot be written + * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` + * because that triggers -Wlogical-op on GCC 7.3. */ + if (block_size > sizeof(ipad)) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (block_size > sizeof(hmac->opad)) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (block_size < hash_size) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (key_length > block_size) { + status = psa_hash_compute(hash_alg, key, key_length, + ipad, sizeof(ipad), &key_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + } + /* A 0-length key is not commonly used in HMAC when used as a MAC, + * but it is permitted. It is common when HMAC is used in HKDF, for + * example. Don't call `memcpy` in the 0-length because `key` could be + * an invalid pointer which would make the behavior undefined. */ + else if (key_length != 0) { + memcpy(ipad, key, key_length); + } + + /* ipad contains the key followed by garbage. Xor and fill with 0x36 + * to create the ipad value. */ + for (i = 0; i < key_length; i++) { + ipad[i] ^= 0x36; + } + memset(ipad + key_length, 0x36, block_size - key_length); + + /* Copy the key material from ipad to opad, flipping the requisite bits, + * and filling the rest of opad with the requisite constant. */ + for (i = 0; i < key_length; i++) { + hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; + } + memset(hmac->opad + key_length, 0x5C, block_size - key_length); + + status = psa_hash_setup(&hmac->hash_ctx, hash_alg); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_hash_update(&hmac->hash_ctx, ipad, block_size); + +cleanup: + mbedtls_platform_zeroize(ipad, sizeof(ipad)); + + return status; +} + +static psa_status_t psa_hmac_update_internal( + mbedtls_psa_hmac_operation_t *hmac, + const uint8_t *data, + size_t data_length) +{ + return psa_hash_update(&hmac->hash_ctx, data, data_length); +} + +static psa_status_t psa_hmac_finish_internal( + mbedtls_psa_hmac_operation_t *hmac, + uint8_t *mac, + size_t mac_size) +{ + uint8_t tmp[PSA_HASH_MAX_SIZE]; + psa_algorithm_t hash_alg = hmac->alg; + size_t hash_size = 0; + size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); + psa_status_t status; + + status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size); + if (status != PSA_SUCCESS) { + return status; + } + /* From here on, tmp needs to be wiped. */ + + status = psa_hash_setup(&hmac->hash_ctx, hash_alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + memcpy(mac, tmp, mac_size); + +exit: + mbedtls_platform_zeroize(tmp, hash_size); + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) +static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(PSA_WANT_KEY_TYPE_DES) + /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept + * to do CMAC with pure DES, so return NOT_SUPPORTED here. */ + if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES && + (psa_get_key_bits(attributes) == 64 || + psa_get_key_bits(attributes) == 128)) { + return PSA_ERROR_NOT_SUPPORTED; + } +#endif + + const mbedtls_cipher_info_t *cipher_info = + mbedtls_cipher_info_from_psa( + PSA_ALG_CMAC, + psa_get_key_type(attributes), + psa_get_key_bits(attributes), + NULL); + + if (cipher_info == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + + ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac, + key_buffer, + psa_get_key_bits(attributes)); +exit: + return mbedtls_to_psa_error(ret); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + +/* Initialize this driver's MAC operation structure. Once this function has been + * called, mbedtls_psa_mac_abort can run and will do the right thing. */ +static psa_status_t mac_init( + mbedtls_psa_mac_operation_t *operation, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + operation->alg = alg; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { + mbedtls_cipher_init(&operation->ctx.cmac); + status = PSA_SUCCESS; + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if (PSA_ALG_IS_HMAC(operation->alg)) { + /* We'll set up the hash operation later in psa_hmac_setup_internal. */ + operation->ctx.hmac.alg = 0; + status = PSA_SUCCESS; + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + (void) operation; + status = PSA_ERROR_NOT_SUPPORTED; + } + + if (status != PSA_SUCCESS) { + memset(operation, 0, sizeof(*operation)); + } + return status; +} + +psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation) +{ + if (operation->alg == 0) { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; + } else +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { + mbedtls_cipher_free(&operation->ctx.cmac); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if (PSA_ALG_IS_HMAC(operation->alg)) { + psa_hmac_abort_internal(&operation->ctx.hmac); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + goto bad_state; + } + + operation->alg = 0; + + return PSA_SUCCESS; + +bad_state: + /* If abort is called on an uninitialized object, we can't trust + * anything. Wipe the object in case it contains confidential data. + * This may result in a memory leak if a pointer gets overwritten, + * but it's too late to do anything about this. */ + memset(operation, 0, sizeof(*operation)); + return PSA_ERROR_BAD_STATE; +} + +static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if (operation->alg != 0) { + return PSA_ERROR_BAD_STATE; + } + + status = mac_init(operation, alg); + if (status != PSA_SUCCESS) { + return status; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) { + /* Key buffer size for CMAC is dictated by the key bits set on the + * attributes, and previously validated by the core on key import. */ + (void) key_buffer_size; + status = cmac_setup(operation, attributes, key_buffer); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if (PSA_ALG_IS_HMAC(alg)) { + status = psa_hmac_setup_internal(&operation->ctx.hmac, + key_buffer, + key_buffer_size, + PSA_ALG_HMAC_GET_HASH(alg)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; + status = PSA_ERROR_NOT_SUPPORTED; + } + + if (status != PSA_SUCCESS) { + mbedtls_psa_mac_abort(operation); + } + + return status; +} + +psa_status_t mbedtls_psa_mac_sign_setup( + mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + return psa_mac_setup(operation, attributes, + key_buffer, key_buffer_size, alg); +} + +psa_status_t mbedtls_psa_mac_verify_setup( + mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + return psa_mac_setup(operation, attributes, + key_buffer, key_buffer_size, alg); +} + +psa_status_t mbedtls_psa_mac_update( + mbedtls_psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + if (operation->alg == 0) { + return PSA_ERROR_BAD_STATE; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { + return mbedtls_to_psa_error( + mbedtls_cipher_cmac_update(&operation->ctx.cmac, + input, input_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if (PSA_ALG_IS_HMAC(operation->alg)) { + return psa_hmac_update_internal(&operation->ctx.hmac, + input, input_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + (void) input; + (void) input_length; + return PSA_ERROR_BAD_STATE; + } +} + +static psa_status_t psa_mac_finish_internal( + mbedtls_psa_mac_operation_t *operation, + uint8_t *mac, size_t mac_size) +{ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { + uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE]; + int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp); + if (ret == 0) { + memcpy(mac, tmp, mac_size); + } + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + return mbedtls_to_psa_error(ret); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if (PSA_ALG_IS_HMAC(operation->alg)) { + return psa_hmac_finish_internal(&operation->ctx.hmac, + mac, mac_size); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + (void) operation; + (void) mac; + (void) mac_size; + return PSA_ERROR_BAD_STATE; + } +} + +psa_status_t mbedtls_psa_mac_sign_finish( + mbedtls_psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->alg == 0) { + return PSA_ERROR_BAD_STATE; + } + + status = psa_mac_finish_internal(operation, mac, mac_size); + if (status == PSA_SUCCESS) { + *mac_length = mac_size; + } + + return status; +} + +psa_status_t mbedtls_psa_mac_verify_finish( + mbedtls_psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length) +{ + uint8_t actual_mac[PSA_MAC_MAX_SIZE]; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->alg == 0) { + return PSA_ERROR_BAD_STATE; + } + + /* Consistency check: requested MAC length fits our local buffer */ + if (mac_length > sizeof(actual_mac)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_mac_finish_internal(operation, actual_mac, mac_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) { + status = PSA_ERROR_INVALID_SIGNATURE; + } + +cleanup: + mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); + + return status; +} + +psa_status_t mbedtls_psa_mac_compute( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT; + + status = psa_mac_setup(&operation, + attributes, key_buffer, key_buffer_size, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (input_length > 0) { + status = mbedtls_psa_mac_update(&operation, input, input_length); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + status = psa_mac_finish_internal(&operation, mac, mac_size); + if (status == PSA_SUCCESS) { + *mac_length = mac_size; + } + +exit: + mbedtls_psa_mac_abort(&operation); + + return status; +} + +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_pake.c b/thirdparty/mbedtls/library/psa_crypto_pake.c new file mode 100644 index 0000000000..9ac2e8c486 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_pake.c @@ -0,0 +1,571 @@ +/* + * PSA PAKE layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include <psa/crypto.h> +#include "psa_crypto_core.h" +#include "psa_crypto_pake.h" +#include "psa_crypto_slot_management.h" + +#include <mbedtls/ecjpake.h> +#include "psa_util_internal.h" + +#include <mbedtls/platform.h> +#include <mbedtls/error.h> +#include <string.h> + +/* + * State sequence: + * + * psa_pake_setup() + * | + * |-- In any order: + * | | psa_pake_set_password_key() + * | | psa_pake_set_user() + * | | psa_pake_set_peer() + * | | psa_pake_set_role() + * | + * |--- In any order: (First round input before or after first round output) + * | | + * | |------ In Order + * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) + * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) + * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) + * | + * |--- In any order: (Second round input before or after second round output) + * | | + * | |------ In Order + * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) + * | + * psa_pake_get_implicit_key() + * psa_pake_abort() + */ + +/* + * Possible sequence of calls to implementation: + * + * |--- In any order: + * | | + * | |------ In Order + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF) + * | + * |--- In any order: + * | | + * | |------ In Order + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF) + */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) +static psa_status_t mbedtls_ecjpake_to_psa_error(int ret) +{ + switch (ret) { + case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_INVALID_KEY: + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return PSA_ERROR_DATA_INVALID; + case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; + case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: + return PSA_ERROR_CORRUPTION_DETECTED; + default: + return PSA_ERROR_GENERIC_ERROR; + } +} +#endif + +#if defined(MBEDTLS_PSA_BUILTIN_PAKE) +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) +static psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_ecjpake_init(&operation->ctx.jpake); + + ret = mbedtls_ecjpake_setup(&operation->ctx.jpake, + operation->role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + operation->password, + operation->password_len); + + mbedtls_platform_zeroize(operation->password, operation->password_len); + + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + return PSA_SUCCESS; +} +#endif + +/* The only two JPAKE user/peer identifiers supported in built-in implementation. */ +static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; +static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; + +psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, + const psa_crypto_driver_pake_inputs_t *inputs) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t user_len = 0, peer_len = 0, password_len = 0; + uint8_t *peer = NULL, *user = NULL; + size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0; + psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); + + status = psa_crypto_driver_pake_get_password_len(inputs, &password_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_crypto_driver_pake_get_user_len(inputs, &user_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite); + if (status != PSA_SUCCESS) { + return status; + } + + operation->password = mbedtls_calloc(1, password_len); + if (operation->password == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + + user = mbedtls_calloc(1, user_len); + if (user == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + + peer = mbedtls_calloc(1, peer_len); + if (peer == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + + status = psa_crypto_driver_pake_get_password(inputs, operation->password, + password_len, &actual_password_len); + if (status != PSA_SUCCESS) { + goto error; + } + + status = psa_crypto_driver_pake_get_user(inputs, user, + user_len, &actual_user_len); + if (status != PSA_SUCCESS) { + goto error; + } + + status = psa_crypto_driver_pake_get_peer(inputs, peer, + peer_len, &actual_peer_len); + if (status != PSA_SUCCESS) { + goto error; + } + + operation->password_len = actual_password_len; + operation->alg = cipher_suite.algorithm; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + if (cipher_suite.algorithm == PSA_ALG_JPAKE) { + if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC || + cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 || + cipher_suite.bits != 256 || + cipher_suite.hash != PSA_ALG_SHA_256) { + status = PSA_ERROR_NOT_SUPPORTED; + goto error; + } + + const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length + if (actual_user_len != user_peer_len || + actual_peer_len != user_peer_len) { + status = PSA_ERROR_NOT_SUPPORTED; + goto error; + } + + if (memcmp(user, jpake_client_id, actual_user_len) == 0 && + memcmp(peer, jpake_server_id, actual_peer_len) == 0) { + operation->role = MBEDTLS_ECJPAKE_CLIENT; + } else + if (memcmp(user, jpake_server_id, actual_user_len) == 0 && + memcmp(peer, jpake_client_id, actual_peer_len) == 0) { + operation->role = MBEDTLS_ECJPAKE_SERVER; + } else { + status = PSA_ERROR_NOT_SUPPORTED; + goto error; + } + + operation->buffer_length = 0; + operation->buffer_offset = 0; + + status = psa_pake_ecjpake_setup(operation); + if (status != PSA_SUCCESS) { + goto error; + } + + /* Role has been set, release user/peer buffers. */ + mbedtls_free(user); mbedtls_free(peer); + + return PSA_SUCCESS; + } else +#else + (void) operation; + (void) inputs; +#endif + { status = PSA_ERROR_NOT_SUPPORTED; } + +error: + mbedtls_free(user); mbedtls_free(peer); + /* In case of failure of the setup of a multipart operation, the PSA driver interface + * specifies that the core does not call any other driver entry point thus does not + * call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean + * up like freeing the memory that may have been allocated to store the password. + */ + mbedtls_psa_pake_abort(operation); + return status; +} + +static psa_status_t mbedtls_psa_pake_output_internal( + mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t length; + (void) step; // Unused parameter + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + /* + * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different + * handling of output sequencing. + * + * The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data + * at once, on the other side the PSA CRYPTO PAKE api requires + * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be + * retrieved in sequence. + * + * In order to achieve API compatibility, the whole X1+X2 or X2S steps + * data is stored in an intermediate buffer at first step output call, + * and data is sliced down by parsing the ECPoint records in order + * to return the right parts on each step. + */ + if (operation->alg == PSA_ALG_JPAKE) { + /* Initialize & write round on KEY_SHARE sequences */ + if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) { + ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake, + operation->buffer, + sizeof(operation->buffer), + &operation->buffer_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + operation->buffer_offset = 0; + } else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) { + ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake, + operation->buffer, + sizeof(operation->buffer), + &operation->buffer_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + operation->buffer_offset = 0; + } + + /* + * mbedtls_ecjpake_write_round_xxx() outputs thing in the format + * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is + * that the data for each step is prepended with a length byte, and + * then they're concatenated. Additionally, the server's second round + * output is prepended with a 3-bytes ECParameters structure. + * + * In PSA, we output each step separately, and don't prepend the + * output with a length byte, even less a curve identifier, as that + * information is already available. + */ + if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE && + operation->role == MBEDTLS_ECJPAKE_SERVER) { + /* Skip ECParameters, with is 3 bytes (RFC 8422) */ + operation->buffer_offset += 3; + } + + /* Read the length byte then move past it to the data */ + length = operation->buffer[operation->buffer_offset]; + operation->buffer_offset += 1; + + if (operation->buffer_offset + length > operation->buffer_length) { + return PSA_ERROR_DATA_CORRUPT; + } + + if (output_size < length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(output, + operation->buffer + operation->buffer_offset, + length); + *output_length = length; + + operation->buffer_offset += length; + + /* Reset buffer after ZK_PROOF sequence */ + if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) || + (step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) { + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + operation->buffer_offset = 0; + } + + return PSA_SUCCESS; + } else +#else + (void) step; + (void) output; + (void) output_size; + (void) output_length; +#endif + { return PSA_ERROR_NOT_SUPPORTED; } +} + +psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = mbedtls_psa_pake_output_internal( + operation, step, output, output_size, output_length); + + return status; +} + +static psa_status_t mbedtls_psa_pake_input_internal( + mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + const uint8_t *input, + size_t input_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + (void) step; // Unused parameter + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + /* + * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different + * handling of input sequencing. + * + * The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data + * at once as input, on the other side the PSA CRYPTO PAKE api requires + * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be + * given in sequence. + * + * In order to achieve API compatibility, each X1+X2 or X4S step data + * is stored sequentially in an intermediate buffer and given to the + * Mbed TLS JPAKE API on the last step. + * + * This causes any input error to be only detected on the last step. + */ + if (operation->alg == PSA_ALG_JPAKE) { + /* + * Copy input to local buffer and format it as the Mbed TLS API + * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7. + * The summary is that the data for each step is prepended with a + * length byte, and then they're concatenated. Additionally, the + * server's second round output is prepended with a 3-bytes + * ECParameters structure - which means we have to prepend that when + * we're a client. + */ + if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE && + operation->role == MBEDTLS_ECJPAKE_CLIENT) { + /* We only support secp256r1. */ + /* This is the ECParameters structure defined by RFC 8422. */ + unsigned char ecparameters[3] = { + 3, /* named_curve */ + 0, 23 /* secp256r1 */ + }; + + if (operation->buffer_length + sizeof(ecparameters) > + sizeof(operation->buffer)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(operation->buffer + operation->buffer_length, + ecparameters, sizeof(ecparameters)); + operation->buffer_length += sizeof(ecparameters); + } + + /* + * The core checks that input_length is smaller than + * PSA_PAKE_INPUT_MAX_SIZE. + * Thus no risk of integer overflow here. + */ + if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + /* Write the length byte */ + operation->buffer[operation->buffer_length] = (uint8_t) input_length; + operation->buffer_length += 1; + + /* Finally copy the data */ + memcpy(operation->buffer + operation->buffer_length, + input, input_length); + operation->buffer_length += input_length; + + /* Load buffer at each last round ZK_PROOF */ + if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) { + ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake, + operation->buffer, + operation->buffer_length); + + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + } else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) { + ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake, + operation->buffer, + operation->buffer_length); + + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + } + + return PSA_SUCCESS; + } else +#else + (void) step; + (void) input; + (void) input_length; +#endif + { return PSA_ERROR_NOT_SUPPORTED; } +} + +psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status = mbedtls_psa_pake_input_internal( + operation, step, input, input_length); + + return status; +} + +psa_status_t mbedtls_psa_pake_get_implicit_key( + mbedtls_psa_pake_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake, + output, + output_size, + output_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + return PSA_SUCCESS; + } else +#else + (void) output; +#endif + { return PSA_ERROR_NOT_SUPPORTED; } +} + +psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation) +{ + mbedtls_zeroize_and_free(operation->password, operation->password_len); + operation->password = NULL; + operation->password_len = 0; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + operation->role = MBEDTLS_ECJPAKE_NONE; + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + operation->buffer_offset = 0; + mbedtls_ecjpake_free(&operation->ctx.jpake); + } +#endif + + operation->alg = PSA_ALG_NONE; + + return PSA_SUCCESS; +} + +#endif /* MBEDTLS_PSA_BUILTIN_PAKE */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_rsa.c b/thirdparty/mbedtls/library/psa_crypto_rsa.c new file mode 100644 index 0000000000..38dc3b8edc --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_rsa.c @@ -0,0 +1,705 @@ +/* + * PSA RSA layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include <psa/crypto.h> +#include "psa/crypto_values.h" +#include "psa_crypto_core.h" +#include "psa_crypto_random_impl.h" +#include "psa_crypto_rsa.h" +#include "psa_crypto_hash.h" +#include "mbedtls/psa_util.h" + +#include <stdlib.h> +#include <string.h> +#include "mbedtls/platform.h" + +#include <mbedtls/rsa.h> +#include <mbedtls/error.h> +#include "rsa_internal.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + +/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes + * that are not a multiple of 8) well. For example, there is only + * mbedtls_rsa_get_len(), which returns a number of bytes, and no + * way to return the exact bit size of a key. + * To keep things simple, reject non-byte-aligned key sizes. */ +static psa_status_t psa_check_rsa_key_byte_aligned( + const mbedtls_rsa_context *rsa) +{ + mbedtls_mpi n; + psa_status_t status; + mbedtls_mpi_init(&n); + status = mbedtls_to_psa_error( + mbedtls_rsa_export(rsa, &n, NULL, NULL, NULL, NULL)); + if (status == PSA_SUCCESS) { + if (mbedtls_mpi_bitlen(&n) % 8 != 0) { + status = PSA_ERROR_NOT_SUPPORTED; + } + } + mbedtls_mpi_free(&n); + return status; +} + +psa_status_t mbedtls_psa_rsa_load_representation( + psa_key_type_t type, const uint8_t *data, size_t data_length, + mbedtls_rsa_context **p_rsa) +{ + psa_status_t status; + size_t bits; + + *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); + if (*p_rsa == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + mbedtls_rsa_init(*p_rsa); + + /* Parse the data. */ + if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length)); + } else { + status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length)); + } + if (status != PSA_SUCCESS) { + goto exit; + } + + /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS + * supports non-byte-aligned key sizes, but not well. For example, + * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ + bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa)); + if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_check_rsa_key_byte_aligned(*p_rsa); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + return status; +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) +psa_status_t mbedtls_psa_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits) +{ + psa_status_t status; + mbedtls_rsa_context *rsa = NULL; + + /* Parse input */ + status = mbedtls_psa_rsa_load_representation(attributes->type, + data, + data_length, + &rsa); + if (status != PSA_SUCCESS) { + goto exit; + } + + *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(rsa)); + + /* Re-export the data to PSA export format, such that we can store export + * representation in the key slot. Export representation in case of RSA is + * the smallest representation that's allowed as input, so a straight-up + * allocation of the same size as the input buffer will be large enough. */ + status = mbedtls_psa_rsa_export_key(attributes->type, + rsa, + key_buffer, + key_buffer_size, + key_buffer_length); +exit: + /* Always free the RSA object */ + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); + + return status; +} +#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) +psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type, + mbedtls_rsa_context *rsa, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + int ret; + uint8_t *end = data + data_size; + + /* PSA Crypto API defines the format of an RSA key as a DER-encoded + * representation of the non-encrypted PKCS#1 RSAPrivateKey for a + * private key and of the RFC3279 RSAPublicKey for a public key. */ + if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + ret = mbedtls_rsa_write_key(rsa, data, &end); + } else { + ret = mbedtls_rsa_write_pubkey(rsa, data, &end); + } + + if (ret < 0) { + /* Clean up in case pk_write failed halfway through. */ + memset(data, 0, data_size); + return mbedtls_to_psa_error(ret); + } + + /* The mbedtls_pk_xxx functions write to the end of the buffer. + * Move the data to the beginning and erase remaining data + * at the original location. */ + if (2 * (size_t) ret <= data_size) { + memcpy(data, data + data_size - ret, ret); + memset(data + data_size - ret, 0, ret); + } else if ((size_t) ret < data_size) { + memmove(data, data + data_size - ret, ret); + memset(data + ret, 0, data_size - ret); + } + + *data_length = ret; + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = NULL; + + status = mbedtls_psa_rsa_load_representation( + attributes->type, key_buffer, key_buffer_size, &rsa); + if (status == PSA_SUCCESS) { + status = mbedtls_psa_rsa_export_key(PSA_KEY_TYPE_RSA_PUBLIC_KEY, + rsa, + data, + data_size, + data_length); + } + + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); + + return status; +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes, + size_t e_length, + int *exponent) +{ + size_t i; + uint32_t acc = 0; + + /* Mbed TLS encodes the public exponent as an int. For simplicity, only + * support values that fit in a 32-bit integer, which is larger than + * int on just about every platform anyway. */ + if (e_length > sizeof(acc)) { + return PSA_ERROR_NOT_SUPPORTED; + } + for (i = 0; i < e_length; i++) { + acc = (acc << 8) | e_bytes[i]; + } + if (acc > INT_MAX) { + return PSA_ERROR_NOT_SUPPORTED; + } + *exponent = acc; + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_rsa_generate_key( + const psa_key_attributes_t *attributes, + const uint8_t *custom_data, size_t custom_data_length, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) +{ + psa_status_t status; + mbedtls_rsa_context rsa; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int exponent = 65537; + + if (custom_data_length != 0) { + status = psa_rsa_read_exponent(custom_data, custom_data_length, + &exponent); + if (status != PSA_SUCCESS) { + return status; + } + } + + mbedtls_rsa_init(&rsa); + ret = mbedtls_rsa_gen_key(&rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + (unsigned int) attributes->bits, + exponent); + if (ret != 0) { + mbedtls_rsa_free(&rsa); + return mbedtls_to_psa_error(ret); + } + + status = mbedtls_psa_rsa_export_key(attributes->type, + &rsa, key_buffer, key_buffer_size, + key_buffer_length); + mbedtls_rsa_free(&rsa); + + return status; +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ + +/****************************************************************/ +/* Sign/verify hashes */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + +/* Decode the hash algorithm from alg and store the mbedtls encoding in + * md_alg. Verify that the hash length is acceptable. */ +static psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg, + size_t hash_length, + mbedtls_md_type_t *md_alg) +{ + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); + *md_alg = mbedtls_md_type_from_psa_alg(hash_alg); + + /* The Mbed TLS RSA module uses an unsigned int for hash length + * parameters. Validate that it fits so that we don't risk an + * overflow later. */ +#if SIZE_MAX > UINT_MAX + if (hash_length > UINT_MAX) { + return PSA_ERROR_INVALID_ARGUMENT; + } +#endif + + /* For signatures using a hash, the hash length must be correct. */ + if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) { + if (*md_alg == MBEDTLS_MD_NONE) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } + + return PSA_SUCCESS; +} + +psa_status_t mbedtls_psa_rsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = mbedtls_psa_rsa_load_representation(attributes->type, + key_buffer, + key_buffer_size, + &rsa); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_rsa_decode_md_type(alg, hash_length, &md_alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (signature_size < mbedtls_rsa_get_len(rsa)) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) + if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE); + if (ret == 0) { + ret = mbedtls_rsa_pkcs1_sign(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + md_alg, + (unsigned int) hash_length, + hash, + signature); + } + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + if (PSA_ALG_IS_RSA_PSS(alg)) { + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); + + if (ret == 0) { + ret = mbedtls_rsa_rsassa_pss_sign(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + MBEDTLS_MD_NONE, + (unsigned int) hash_length, + hash, + signature); + } + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if (ret == 0) { + *signature_length = mbedtls_rsa_get_len(rsa); + } + status = mbedtls_to_psa_error(ret); + +exit: + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); + + return status; +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) +static int rsa_pss_expected_salt_len(psa_algorithm_t alg, + const mbedtls_rsa_context *rsa, + size_t hash_length) +{ + if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) { + return MBEDTLS_RSA_SALT_LEN_ANY; + } + /* Otherwise: standard salt length, i.e. largest possible salt length + * up to the hash length. */ + int klen = (int) mbedtls_rsa_get_len(rsa); // known to fit + int hlen = (int) hash_length; // known to fit + int room = klen - 2 - hlen; + if (room < 0) { + return 0; // there is no valid signature in this case anyway + } else if (room > hlen) { + return hlen; + } else { + return room; + } +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ + +psa_status_t mbedtls_psa_rsa_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = mbedtls_psa_rsa_load_representation(attributes->type, + key_buffer, + key_buffer_size, + &rsa); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_rsa_decode_md_type(alg, hash_length, &md_alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (signature_length != mbedtls_rsa_get_len(rsa)) { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) + if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE); + if (ret == 0) { + ret = mbedtls_rsa_pkcs1_verify(rsa, + md_alg, + (unsigned int) hash_length, + hash, + signature); + } + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + if (PSA_ALG_IS_RSA_PSS(alg)) { + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); + if (ret == 0) { + int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length); + ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa, + md_alg, + (unsigned) hash_length, + hash, + md_alg, + slen, + signature); + } + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Mbed TLS distinguishes "invalid padding" from "valid padding but + * the rest of the signature is invalid". This has little use in + * practice and PSA doesn't report this distinction. */ + status = (ret == MBEDTLS_ERR_RSA_INVALID_PADDING) ? + PSA_ERROR_INVALID_SIGNATURE : + mbedtls_to_psa_error(ret); + +exit: + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); + + return status; +} + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ + +/****************************************************************/ +/* Asymmetric cryptography */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +static int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg, + mbedtls_rsa_context *rsa) +{ + psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg); + mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); + + /* Just to get the error status right, as rsa_set_padding() doesn't + * distinguish between "bad RSA algorithm" and "unknown hash". */ + if (mbedtls_md_info_from_type(md_alg) == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + +psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + (void) key_buffer; + (void) key_buffer_size; + (void) input; + (void) input_length; + (void) salt; + (void) salt_length; + (void) output; + (void) output_size; + (void) output_length; + + if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + mbedtls_rsa_context *rsa = NULL; + status = mbedtls_psa_rsa_load_representation(attributes->type, + key_buffer, + key_buffer_size, + &rsa); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + if (output_size < mbedtls_rsa_get_len(rsa)) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto rsa_exit; + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_encrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + input_length, + input, + output)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ + } else + if (PSA_ALG_IS_RSA_OAEP(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + status = mbedtls_to_psa_error( + psa_rsa_oaep_set_padding_mode(alg, rsa)); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_encrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + salt, salt_length, + input_length, + input, + output)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ + } else { + status = PSA_ERROR_INVALID_ARGUMENT; + } +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +rsa_exit: + if (status == PSA_SUCCESS) { + *output_length = mbedtls_rsa_get_len(rsa); + } + + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + } else { + status = PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + +psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + (void) key_buffer; + (void) key_buffer_size; + (void) input; + (void) input_length; + (void) salt; + (void) salt_length; + (void) output; + (void) output_size; + (void) output_length; + + *output_length = 0; + + if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + mbedtls_rsa_context *rsa = NULL; + status = mbedtls_psa_rsa_load_representation(attributes->type, + key_buffer, + key_buffer_size, + &rsa); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + if (input_length != mbedtls_rsa_get_len(rsa)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto rsa_exit; + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + + if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_decrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + output_length, + input, + output, + output_size)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ + } else + if (PSA_ALG_IS_RSA_OAEP(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + status = mbedtls_to_psa_error( + psa_rsa_oaep_set_padding_mode(alg, rsa)); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_decrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + salt, salt_length, + output_length, + input, + output, + output_size)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ + } else { + status = PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +rsa_exit: + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + } else { + status = PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_se.c b/thirdparty/mbedtls/library/psa_crypto_se.c new file mode 100644 index 0000000000..7a36a4f3a5 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_se.c @@ -0,0 +1,373 @@ +/* + * PSA crypto support for secure element drivers + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +#include <stdint.h> +#include <string.h> + +#include "psa/crypto_se_driver.h" + +#include "psa_crypto_se.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#include "mbedtls/platform.h" + + + +/****************************************************************/ +/* Driver lookup */ +/****************************************************************/ + +/* This structure is identical to psa_drv_se_context_t declared in + * `crypto_se_driver.h`, except that some parts are writable here + * (non-const, or pointer to non-const). */ +typedef struct { + void *persistent_data; + size_t persistent_data_size; + uintptr_t transient_data; +} psa_drv_se_internal_context_t; + +struct psa_se_drv_table_entry_s { + psa_key_location_t location; + const psa_drv_se_t *methods; + union { + psa_drv_se_internal_context_t internal; + psa_drv_se_context_t context; + } u; +}; + +static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; + +psa_se_drv_table_entry_t *psa_get_se_driver_entry( + psa_key_lifetime_t lifetime) +{ + size_t i; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); + /* In the driver table, location=0 means an entry that isn't used. + * No driver has a location of 0 because it's a reserved value + * (which designates transparent keys). Make sure we never return + * a driver entry for location 0. */ + if (location == 0) { + return NULL; + } + for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { + if (driver_table[i].location == location) { + return &driver_table[i]; + } + } + return NULL; +} + +const psa_drv_se_t *psa_get_se_driver_methods( + const psa_se_drv_table_entry_t *driver) +{ + return driver->methods; +} + +psa_drv_se_context_t *psa_get_se_driver_context( + psa_se_drv_table_entry_t *driver) +{ + return &driver->u.context; +} + +int psa_get_se_driver(psa_key_lifetime_t lifetime, + const psa_drv_se_t **p_methods, + psa_drv_se_context_t **p_drv_context) +{ + psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime); + if (p_methods != NULL) { + *p_methods = (driver ? driver->methods : NULL); + } + if (p_drv_context != NULL) { + *p_drv_context = (driver ? &driver->u.context : NULL); + } + return driver != NULL; +} + + + +/****************************************************************/ +/* Persistent data management */ +/****************************************************************/ + +static psa_status_t psa_get_se_driver_its_file_uid( + const psa_se_drv_table_entry_t *driver, + psa_storage_uid_t *uid) +{ + if (driver->location > PSA_MAX_SE_LOCATION) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* ITS file sizes are limited to 32 bits. */ + if (driver->u.internal.persistent_data_size > UINT32_MAX) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ + *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location; + return PSA_SUCCESS; +} + +psa_status_t psa_load_se_persistent_data( + const psa_se_drv_table_entry_t *driver) +{ + psa_status_t status; + psa_storage_uid_t uid; + size_t length; + + status = psa_get_se_driver_its_file_uid(driver, &uid); + if (status != PSA_SUCCESS) { + return status; + } + + /* Read the amount of persistent data that the driver requests. + * If the data in storage is larger, it is truncated. If the data + * in storage is smaller, silently keep what is already at the end + * of the output buffer. */ + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return psa_its_get(uid, 0, + (uint32_t) driver->u.internal.persistent_data_size, + driver->u.internal.persistent_data, + &length); +} + +psa_status_t psa_save_se_persistent_data( + const psa_se_drv_table_entry_t *driver) +{ + psa_status_t status; + psa_storage_uid_t uid; + + status = psa_get_se_driver_its_file_uid(driver, &uid); + if (status != PSA_SUCCESS) { + return status; + } + + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return psa_its_set(uid, + (uint32_t) driver->u.internal.persistent_data_size, + driver->u.internal.persistent_data, + 0); +} + +psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location) +{ + psa_storage_uid_t uid; + if (location > PSA_MAX_SE_LOCATION) { + return PSA_ERROR_NOT_SUPPORTED; + } + uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location; + return psa_its_remove(uid); +} + +psa_status_t psa_find_se_slot_for_key( + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t *slot_number) +{ + psa_status_t status; + psa_key_location_t key_location = + PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); + + /* If the location is wrong, it's a bug in the library. */ + if (driver->location != key_location) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + + /* If the driver doesn't support key creation in any way, give up now. */ + if (driver->methods->key_management == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) { + /* The application wants to use a specific slot. Allow it if + * the driver supports it. On a system with isolation, + * the crypto service must check that the application is + * permitted to request this slot. */ + psa_drv_se_validate_slot_number_t p_validate_slot_number = + driver->methods->key_management->p_validate_slot_number; + if (p_validate_slot_number == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + status = p_validate_slot_number(&driver->u.context, + driver->u.internal.persistent_data, + attributes, method, + *slot_number); + } else if (method == PSA_KEY_CREATION_REGISTER) { + /* The application didn't specify a slot number. This doesn't + * make sense when registering a slot. */ + return PSA_ERROR_INVALID_ARGUMENT; + } else { + /* The application didn't tell us which slot to use. Let the driver + * choose. This is the normal case. */ + psa_drv_se_allocate_key_t p_allocate = + driver->methods->key_management->p_allocate; + if (p_allocate == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + status = p_allocate(&driver->u.context, + driver->u.internal.persistent_data, + attributes, method, + slot_number); + } + return status; +} + +psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t slot_number) +{ + psa_status_t status; + psa_status_t storage_status; + /* Normally a missing method would mean that the action is not + * supported. But psa_destroy_key() is not supposed to return + * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should + * be able to destroy it. The only use case for a driver that + * does not have a way to destroy keys at all is if the keys are + * locked in a read-only state: we can use the keys but not + * destroy them. Hence, if the driver doesn't support destroying + * keys, it's really a lack of permission. */ + if (driver->methods->key_management == NULL || + driver->methods->key_management->p_destroy == NULL) { + return PSA_ERROR_NOT_PERMITTED; + } + status = driver->methods->key_management->p_destroy( + &driver->u.context, + driver->u.internal.persistent_data, + slot_number); + storage_status = psa_save_se_persistent_data(driver); + return status == PSA_SUCCESS ? storage_status : status; +} + +psa_status_t psa_init_all_se_drivers(void) +{ + size_t i; + for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { + psa_se_drv_table_entry_t *driver = &driver_table[i]; + if (driver->location == 0) { + continue; /* skipping unused entry */ + } + const psa_drv_se_t *methods = psa_get_se_driver_methods(driver); + if (methods->p_init != NULL) { + psa_status_t status = methods->p_init( + &driver->u.context, + driver->u.internal.persistent_data, + driver->location); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_save_se_persistent_data(driver); + if (status != PSA_SUCCESS) { + return status; + } + } + } + return PSA_SUCCESS; +} + + + +/****************************************************************/ +/* Driver registration */ +/****************************************************************/ + +psa_status_t psa_register_se_driver( + psa_key_location_t location, + const psa_drv_se_t *methods) +{ + size_t i; + psa_status_t status; + + if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) { + return PSA_ERROR_NOT_SUPPORTED; + } + /* Driver table entries are 0-initialized. 0 is not a valid driver + * location because it means a transparent key. */ + MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0, + "Secure element support requires 0 to mean a local key"); + + if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (location > PSA_MAX_SE_LOCATION) { + return PSA_ERROR_NOT_SUPPORTED; + } + + for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { + if (driver_table[i].location == 0) { + break; + } + /* Check that location isn't already in use up to the first free + * entry. Since entries are created in order and never deleted, + * there can't be a used entry after the first free entry. */ + if (driver_table[i].location == location) { + return PSA_ERROR_ALREADY_EXISTS; + } + } + if (i == PSA_MAX_SE_DRIVERS) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + driver_table[i].location = location; + driver_table[i].methods = methods; + driver_table[i].u.internal.persistent_data_size = + methods->persistent_data_size; + + if (methods->persistent_data_size != 0) { + driver_table[i].u.internal.persistent_data = + mbedtls_calloc(1, methods->persistent_data_size); + if (driver_table[i].u.internal.persistent_data == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + /* Load the driver's persistent data. On first use, the persistent + * data does not exist in storage, and is initialized to + * all-bits-zero by the calloc call just above. */ + status = psa_load_se_persistent_data(&driver_table[i]); + if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) { + goto error; + } + } + + return PSA_SUCCESS; + +error: + memset(&driver_table[i], 0, sizeof(driver_table[i])); + return status; +} + +void psa_unregister_all_se_drivers(void) +{ + size_t i; + for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { + if (driver_table[i].u.internal.persistent_data != NULL) { + mbedtls_free(driver_table[i].u.internal.persistent_data); + } + } + memset(driver_table, 0, sizeof(driver_table)); +} + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_slot_management.c b/thirdparty/mbedtls/library/psa_crypto_slot_management.c new file mode 100644 index 0000000000..9850d8c750 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_slot_management.c @@ -0,0 +1,1131 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers_no_static.h" +#include "psa_crypto_slot_management.h" +#include "psa_crypto_storage.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif + +#include <stdlib.h> +#include <string.h> +#include "mbedtls/platform.h" +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + + + +/* Make sure we have distinct ranges of key identifiers for distinct + * purposes. */ +MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MIN < PSA_KEY_ID_USER_MAX, + "Empty user key ID range"); +MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN < PSA_KEY_ID_VENDOR_MAX, + "Empty vendor key ID range"); +MBEDTLS_STATIC_ASSERT(MBEDTLS_PSA_KEY_ID_BUILTIN_MIN < MBEDTLS_PSA_KEY_ID_BUILTIN_MAX, + "Empty builtin key ID range"); +MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MIN < PSA_KEY_ID_VOLATILE_MAX, + "Empty volatile key ID range"); + +MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MAX < PSA_KEY_ID_VENDOR_MIN || + PSA_KEY_ID_VENDOR_MAX < PSA_KEY_ID_USER_MIN, + "Overlap between user key IDs and vendor key IDs"); + +MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN && + MBEDTLS_PSA_KEY_ID_BUILTIN_MAX <= PSA_KEY_ID_VENDOR_MAX, + "Builtin key identifiers are not in the vendor range"); + +MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= PSA_KEY_ID_VOLATILE_MIN && + PSA_KEY_ID_VOLATILE_MAX <= PSA_KEY_ID_VENDOR_MAX, + "Volatile key identifiers are not in the vendor range"); + +MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MAX < MBEDTLS_PSA_KEY_ID_BUILTIN_MIN || + MBEDTLS_PSA_KEY_ID_BUILTIN_MAX < PSA_KEY_ID_VOLATILE_MIN, + "Overlap between builtin key IDs and volatile key IDs"); + + + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + +/* Dynamic key store. + * + * The key store consists of multiple slices. + * + * The volatile keys are stored in variable-sized tables called slices. + * Slices are allocated on demand and deallocated when possible. + * The size of slices increases exponentially, so the average overhead + * (number of slots that are allocated but not used) is roughly + * proportional to the number of keys (with a factor that grows + * when the key store is fragmented). + * + * One slice is dedicated to the cache of persistent and built-in keys. + * For simplicity, they are separated from volatile keys. This cache + * slice has a fixed size and has the slice index KEY_SLOT_CACHE_SLICE_INDEX, + * located after the slices for volatile keys. + */ + +/* Size of the last slice containing the cache of persistent and built-in keys. */ +#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT + +/* Volatile keys are stored in slices 0 through + * (KEY_SLOT_VOLATILE_SLICE_COUNT - 1) inclusive. + * Each slice is twice the size of the previous slice. + * Volatile key identifiers encode the slice number as follows: + * bits 30..31: 0b10 (mandated by the PSA Crypto specification). + * bits 25..29: slice index (0...KEY_SLOT_VOLATILE_SLICE_COUNT-1) + * bits 0..24: slot index in slice + */ +#define KEY_ID_SLOT_INDEX_WIDTH 25u +#define KEY_ID_SLICE_INDEX_WIDTH 5u + +#define KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH 16u +#define KEY_SLOT_VOLATILE_SLICE_COUNT 22u +#define KEY_SLICE_COUNT (KEY_SLOT_VOLATILE_SLICE_COUNT + 1u) +#define KEY_SLOT_CACHE_SLICE_INDEX KEY_SLOT_VOLATILE_SLICE_COUNT + + +/* Check that the length of the largest slice (calculated as + * KEY_SLICE_LENGTH_MAX below) does not overflow size_t. We use + * an indirect method in case the calculation of KEY_SLICE_LENGTH_MAX + * itself overflows uintmax_t: if (BASE_LENGTH << c) + * overflows size_t then BASE_LENGTH > SIZE_MAX >> c. + */ +#if (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH > \ + SIZE_MAX >> (KEY_SLOT_VOLATILE_SLICE_COUNT - 1)) +#error "Maximum slice length overflows size_t" +#endif + +#if KEY_ID_SLICE_INDEX_WIDTH + KEY_ID_SLOT_INDEX_WIDTH > 30 +#error "Not enough room in volatile key IDs for slice index and slot index" +#endif +#if KEY_SLOT_VOLATILE_SLICE_COUNT > (1 << KEY_ID_SLICE_INDEX_WIDTH) +#error "Too many slices to fit the slice index in a volatile key ID" +#endif +#define KEY_SLICE_LENGTH_MAX \ + (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << (KEY_SLOT_VOLATILE_SLICE_COUNT - 1)) +#if KEY_SLICE_LENGTH_MAX > 1 << KEY_ID_SLOT_INDEX_WIDTH +#error "Not enough room in volatile key IDs for a slot index in the largest slice" +#endif +#if KEY_ID_SLICE_INDEX_WIDTH > 8 +#error "Slice index does not fit in uint8_t for psa_key_slot_t::slice_index" +#endif + + +/* Calculate the volatile key id to use for a given slot. + * This function assumes valid parameter values. */ +static psa_key_id_t volatile_key_id_of_index(size_t slice_idx, + size_t slot_idx) +{ + /* We assert above that the slice and slot indexes fit in separate + * bit-fields inside psa_key_id_t, which is a 32-bit type per the + * PSA Cryptography specification. */ + return (psa_key_id_t) (0x40000000u | + (slice_idx << KEY_ID_SLOT_INDEX_WIDTH) | + slot_idx); +} + +/* Calculate the slice containing the given volatile key. + * This function assumes valid parameter values. */ +static size_t slice_index_of_volatile_key_id(psa_key_id_t key_id) +{ + size_t mask = (1LU << KEY_ID_SLICE_INDEX_WIDTH) - 1; + return (key_id >> KEY_ID_SLOT_INDEX_WIDTH) & mask; +} + +/* Calculate the index of the slot containing the given volatile key. + * This function assumes valid parameter values. */ +static size_t slot_index_of_volatile_key_id(psa_key_id_t key_id) +{ + return key_id & ((1LU << KEY_ID_SLOT_INDEX_WIDTH) - 1); +} + +/* In global_data.first_free_slot_index, use this special value to + * indicate that the slice is full. */ +#define FREE_SLOT_INDEX_NONE ((size_t) -1) + +#if defined(MBEDTLS_TEST_HOOKS) +size_t psa_key_slot_volatile_slice_count(void) +{ + return KEY_SLOT_VOLATILE_SLICE_COUNT; +} +#endif + +#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + +/* Static key store. + * + * All the keys (volatile or persistent) are in a single slice. + * We only use slices as a concept to allow some differences between + * static and dynamic key store management to be buried in auxiliary + * functions. + */ + +#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT +#define KEY_SLICE_COUNT 1u +#define KEY_SLOT_CACHE_SLICE_INDEX 0 + +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + + +typedef struct { +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + psa_key_slot_t *key_slices[KEY_SLICE_COUNT]; + size_t first_free_slot_index[KEY_SLOT_VOLATILE_SLICE_COUNT]; +#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT]; +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + uint8_t key_slots_initialized; +} psa_global_data_t; + +static psa_global_data_t global_data; + +static uint8_t psa_get_key_slots_initialized(void) +{ + uint8_t initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = global_data.key_slots_initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + return initialized; +} + + + +/** The length of the given slice in the key slot table. + * + * \param slice_idx The slice number. It must satisfy + * 0 <= slice_idx < KEY_SLICE_COUNT. + * + * \return The number of elements in the given slice. + */ +static inline size_t key_slice_length(size_t slice_idx); + +/** Get a pointer to the slot where the given volatile key is located. + * + * \param key_id The key identifier. It must be a valid volatile key + * identifier. + * \return A pointer to the only slot that the given key + * can be in. Note that the slot may be empty or + * contain a different key. + */ +static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id); + +/** Get a pointer to an entry in the persistent key cache. + * + * \param slot_idx The index in the table. It must satisfy + * 0 <= slot_idx < PERSISTENT_KEY_CACHE_COUNT. + * \return A pointer to the slot containing the given + * persistent key cache entry. + */ +static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx); + +/** Get a pointer to a slot given by slice and index. + * + * \param slice_idx The slice number. It must satisfy + * 0 <= slice_idx < KEY_SLICE_COUNT. + * \param slot_idx An index in the given slice. It must satisfy + * 0 <= slot_idx < key_slice_length(slice_idx). + * + * \return A pointer to the given slot. + */ +static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx); + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + +#if defined(MBEDTLS_TEST_HOOKS) +size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(size_t slice_idx) = NULL; +#endif + +static inline size_t key_slice_length(size_t slice_idx) +{ + if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) { + return PERSISTENT_KEY_CACHE_COUNT; + } else { +#if defined(MBEDTLS_TEST_HOOKS) + if (mbedtls_test_hook_psa_volatile_key_slice_length != NULL) { + return mbedtls_test_hook_psa_volatile_key_slice_length(slice_idx); + } +#endif + return KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << slice_idx; + } +} + +static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id) +{ + size_t slice_idx = slice_index_of_volatile_key_id(key_id); + if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) { + return NULL; + } + size_t slot_idx = slot_index_of_volatile_key_id(key_id); + if (slot_idx >= key_slice_length(slice_idx)) { + return NULL; + } + psa_key_slot_t *slice = global_data.key_slices[slice_idx]; + if (slice == NULL) { + return NULL; + } + return &slice[slot_idx]; +} + +static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx) +{ + return &global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX][slot_idx]; +} + +static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx) +{ + return &global_data.key_slices[slice_idx][slot_idx]; +} + +#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + +static inline size_t key_slice_length(size_t slice_idx) +{ + (void) slice_idx; + return ARRAY_LENGTH(global_data.key_slots); +} + +static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id) +{ + MBEDTLS_STATIC_ASSERT(ARRAY_LENGTH(global_data.key_slots) <= + PSA_KEY_ID_VOLATILE_MAX - PSA_KEY_ID_VOLATILE_MIN + 1, + "The key slot array is larger than the volatile key ID range"); + return &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN]; +} + +static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx) +{ + return &global_data.key_slots[slot_idx]; +} + +static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx) +{ + (void) slice_idx; + return &global_data.key_slots[slot_idx]; +} + +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + + + +int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok) +{ + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); + + if ((PSA_KEY_ID_USER_MIN <= key_id) && + (key_id <= PSA_KEY_ID_USER_MAX)) { + return 1; + } + + if (vendor_ok && + (PSA_KEY_ID_VENDOR_MIN <= key_id) && + (key_id <= PSA_KEY_ID_VENDOR_MAX)) { + return 1; + } + + return 0; +} + +/** Get the description in memory of a key given its identifier and lock it. + * + * The descriptions of volatile keys and loaded persistent keys are + * stored in key slots. This function returns a pointer to the key slot + * containing the description of a key given its identifier. + * + * The function searches the key slots containing the description of the key + * with \p key identifier. The function does only read accesses to the key + * slots. The function does not load any persistent key thus does not access + * any storage. + * + * For volatile key identifiers, only one key slot is queried as a volatile + * key with identifier key_id can only be stored in slot of index + * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ). + * + * On success, the function locks the key slot. It is the responsibility of + * the caller to unlock the key slot when it does not access it anymore. + * + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. + * + * \param key Key identifier to query. + * \param[out] p_slot On success, `*p_slot` contains a pointer to the + * key slot containing the description of the key + * identified by \p key. + * + * \retval #PSA_SUCCESS + * The pointer to the key slot containing the description of the key + * identified by \p key was returned. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p key is not a valid key identifier. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no key with key identifier \p key in the key slots. + */ +static psa_status_t psa_get_and_lock_key_slot_in_memory( + mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); + size_t slot_idx; + psa_key_slot_t *slot = NULL; + + if (psa_key_id_is_volatile(key_id)) { + slot = get_volatile_key_slot(key_id); + + /* Check if both the PSA key identifier key_id and the owner + * identifier of key match those of the key slot. */ + if (slot != NULL && + slot->state == PSA_SLOT_FULL && + mbedtls_svc_key_id_equal(key, slot->attr.id)) { + status = PSA_SUCCESS; + } else { + status = PSA_ERROR_DOES_NOT_EXIST; + } + } else { + if (!psa_is_valid_key_id(key, 1)) { + return PSA_ERROR_INVALID_HANDLE; + } + + for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) { + slot = get_persistent_key_slot(slot_idx); + /* Only consider slots which are in a full state. */ + if ((slot->state == PSA_SLOT_FULL) && + (mbedtls_svc_key_id_equal(key, slot->attr.id))) { + break; + } + } + status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ? + PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST; + } + + if (status == PSA_SUCCESS) { + status = psa_register_read(slot); + if (status == PSA_SUCCESS) { + *p_slot = slot; + } + } + + return status; +} + +psa_status_t psa_initialize_key_slots(void) +{ +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] = + mbedtls_calloc(PERSISTENT_KEY_CACHE_COUNT, + sizeof(*global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX])); + if (global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } +#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + /* Nothing to do: program startup and psa_wipe_all_key_slots() both + * guarantee that the key slots are initialized to all-zero, which + * means that all the key slots are in a valid, empty state. The global + * data mutex is already held when calling this function, so no need to + * lock it here, to set the flag. */ +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + + global_data.key_slots_initialized = 1; + return PSA_SUCCESS; +} + +void psa_wipe_all_key_slots(void) +{ + for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) { +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + if (global_data.key_slices[slice_idx] == NULL) { + continue; + } +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) { + psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx); +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + /* When MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled, calling + * psa_wipe_key_slot() on an unused slot is useless, but it + * happens to work (because we flip the state to PENDING_DELETION). + * + * When MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, + * psa_wipe_key_slot() needs to have a valid slice_index + * field, but that value might not be correct in a + * free slot, so we must not call it. + * + * Bypass the call to psa_wipe_key_slot() if the slot is empty, + * but only if MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, to save + * a few bytes of code size otherwise. + */ + if (slot->state == PSA_SLOT_EMPTY) { + continue; + } +#endif + slot->var.occupied.registered_readers = 1; + slot->state = PSA_SLOT_PENDING_DELETION; + (void) psa_wipe_key_slot(slot); + } +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + mbedtls_free(global_data.key_slices[slice_idx]); + global_data.key_slices[slice_idx] = NULL; +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + } + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + for (size_t slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) { + global_data.first_free_slot_index[slice_idx] = 0; + } +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + + /* The global data mutex is already held when calling this function. */ + global_data.key_slots_initialized = 0; +} + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + +static psa_status_t psa_allocate_volatile_key_slot(psa_key_id_t *key_id, + psa_key_slot_t **p_slot) +{ + size_t slice_idx; + for (slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) { + if (global_data.first_free_slot_index[slice_idx] != FREE_SLOT_INDEX_NONE) { + break; + } + } + if (slice_idx == KEY_SLOT_VOLATILE_SLICE_COUNT) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + if (global_data.key_slices[slice_idx] == NULL) { + global_data.key_slices[slice_idx] = + mbedtls_calloc(key_slice_length(slice_idx), + sizeof(psa_key_slot_t)); + if (global_data.key_slices[slice_idx] == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + } + psa_key_slot_t *slice = global_data.key_slices[slice_idx]; + + size_t slot_idx = global_data.first_free_slot_index[slice_idx]; + *key_id = volatile_key_id_of_index(slice_idx, slot_idx); + + psa_key_slot_t *slot = &slice[slot_idx]; + size_t next_free = slot_idx + 1 + slot->var.free.next_free_relative_to_next; + if (next_free >= key_slice_length(slice_idx)) { + next_free = FREE_SLOT_INDEX_NONE; + } + global_data.first_free_slot_index[slice_idx] = next_free; + /* The .next_free field is not meaningful when the slot is not free, + * so give it the same content as freshly initialized memory. */ + slot->var.free.next_free_relative_to_next = 0; + + psa_status_t status = psa_key_slot_state_transition(slot, + PSA_SLOT_EMPTY, + PSA_SLOT_FILLING); + if (status != PSA_SUCCESS) { + /* The only reason for failure is if the slot state was not empty. + * This indicates that something has gone horribly wrong. + * In this case, we leave the slot out of the free list, and stop + * modifying it. This minimizes any further corruption. The slot + * is a memory leak, but that's a lesser evil. */ + return status; + } + + *p_slot = slot; + /* We assert at compile time that the slice index fits in uint8_t. */ + slot->slice_index = (uint8_t) slice_idx; + return PSA_SUCCESS; +} + +psa_status_t psa_free_key_slot(size_t slice_idx, + psa_key_slot_t *slot) +{ + + if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) { + /* This is a cache entry. We don't maintain a free list, so + * there's nothing to do. */ + return PSA_SUCCESS; + } + if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + + psa_key_slot_t *slice = global_data.key_slices[slice_idx]; + psa_key_slot_t *slice_end = slice + key_slice_length(slice_idx); + if (slot < slice || slot >= slice_end) { + /* The slot isn't actually in the slice! We can't detect that + * condition for sure, because the pointer comparison itself is + * undefined behavior in that case. That same condition makes the + * subtraction to calculate the slot index also UB. + * Give up now to avoid causing further corruption. + */ + return PSA_ERROR_CORRUPTION_DETECTED; + } + size_t slot_idx = slot - slice; + + size_t next_free = global_data.first_free_slot_index[slice_idx]; + if (next_free >= key_slice_length(slice_idx)) { + /* The slot was full. The newly freed slot thus becomes the + * end of the free list. */ + next_free = key_slice_length(slice_idx); + } + global_data.first_free_slot_index[slice_idx] = slot_idx; + slot->var.free.next_free_relative_to_next = + (int32_t) next_free - (int32_t) slot_idx - 1; + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + +psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, + psa_key_slot_t **p_slot) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t slot_idx; + psa_key_slot_t *selected_slot, *unused_persistent_key_slot; + + if (!psa_get_key_slots_initialized()) { + status = PSA_ERROR_BAD_STATE; + goto error; + } + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + if (volatile_key_id != NULL) { + return psa_allocate_volatile_key_slot(volatile_key_id, p_slot); + } +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + + /* With a dynamic key store, allocate an entry in the cache slice, + * applicable only to non-volatile keys that get cached in RAM. + * With a static key store, allocate an entry in the sole slice, + * applicable to all keys. */ + selected_slot = unused_persistent_key_slot = NULL; + for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) { + psa_key_slot_t *slot = get_key_slot(KEY_SLOT_CACHE_SLICE_INDEX, slot_idx); + if (slot->state == PSA_SLOT_EMPTY) { + selected_slot = slot; + break; + } + + if ((unused_persistent_key_slot == NULL) && + (slot->state == PSA_SLOT_FULL) && + (!psa_key_slot_has_readers(slot)) && + (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) { + unused_persistent_key_slot = slot; + } + } + + /* + * If there is no unused key slot and there is at least one unlocked key + * slot containing the description of a persistent key, recycle the first + * such key slot we encountered. If we later need to operate on the + * persistent key we are evicting now, we will reload its description from + * storage. + */ + if ((selected_slot == NULL) && + (unused_persistent_key_slot != NULL)) { + selected_slot = unused_persistent_key_slot; + psa_register_read(selected_slot); + status = psa_wipe_key_slot(selected_slot); + if (status != PSA_SUCCESS) { + goto error; + } + } + + if (selected_slot != NULL) { + status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY, + PSA_SLOT_FILLING); + if (status != PSA_SUCCESS) { + goto error; + } + +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + selected_slot->slice_index = KEY_SLOT_CACHE_SLICE_INDEX; +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + +#if !defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + if (volatile_key_id != NULL) { + /* Refresh slot_idx, for when the slot is not the original + * selected_slot but rather unused_persistent_key_slot. */ + slot_idx = selected_slot - global_data.key_slots; + *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + slot_idx; + } +#endif + *p_slot = selected_slot; + + return PSA_SUCCESS; + } + status = PSA_ERROR_INSUFFICIENT_MEMORY; + +error: + *p_slot = NULL; + + return status; +} + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *key_data = NULL; + size_t key_data_length = 0; + + status = psa_load_persistent_key(&slot->attr, + &key_data, &key_data_length); + if (status != PSA_SUCCESS) { + goto exit; + } + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Special handling is required for loading keys associated with a + * dynamically registered SE interface. */ + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) { + psa_se_key_data_storage_t *data; + + if (key_data_length != sizeof(*data)) { + status = PSA_ERROR_DATA_INVALID; + goto exit; + } + data = (psa_se_key_data_storage_t *) key_data; + status = psa_copy_key_material_into_slot( + slot, data->slot_number, sizeof(data->slot_number)); + goto exit; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + status = psa_copy_key_material_into_slot(slot, key_data, key_data_length); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + psa_free_persistent_key_data(key_data, key_data_length); + return status; +} +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + +static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE; + psa_drv_slot_number_t slot_number = 0; + size_t key_buffer_size = 0; + size_t key_buffer_length = 0; + + if (!psa_key_id_is_builtin( + MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id))) { + return PSA_ERROR_DOES_NOT_EXIST; + } + + /* Check the platform function to see whether this key actually exists */ + status = mbedtls_psa_platform_get_builtin_key( + slot->attr.id, &lifetime, &slot_number); + if (status != PSA_SUCCESS) { + return status; + } + + /* Set required key attributes to ensure get_builtin_key can retrieve the + * full attributes. */ + psa_set_key_id(&attributes, slot->attr.id); + psa_set_key_lifetime(&attributes, lifetime); + + /* Get the full key attributes from the driver in order to be able to + * calculate the required buffer size. */ + status = psa_driver_wrapper_get_builtin_key( + slot_number, &attributes, + NULL, 0, NULL); + if (status != PSA_ERROR_BUFFER_TOO_SMALL) { + /* Builtin keys cannot be defined by the attributes alone */ + if (status == PSA_SUCCESS) { + status = PSA_ERROR_CORRUPTION_DETECTED; + } + return status; + } + + /* If the key should exist according to the platform, then ask the driver + * what its expected size is. */ + status = psa_driver_wrapper_get_key_buffer_size(&attributes, + &key_buffer_size); + if (status != PSA_SUCCESS) { + return status; + } + + /* Allocate a buffer of the required size and load the builtin key directly + * into the (now properly sized) slot buffer. */ + status = psa_allocate_buffer_to_slot(slot, key_buffer_size); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_driver_wrapper_get_builtin_key( + slot_number, &attributes, + slot->key.data, slot->key.bytes, &key_buffer_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* Copy actual key length and core attributes into the slot on success */ + slot->key.bytes = key_buffer_length; + slot->attr = attributes; +exit: + if (status != PSA_SUCCESS) { + psa_remove_key_data_from_memory(slot); + } + return status; +} +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + +psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *p_slot = NULL; + if (!psa_get_key_slots_initialized()) { + return PSA_ERROR_BAD_STATE; + } + +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + /* If the key is persistent and not loaded, we cannot unlock the mutex + * between checking if the key is loaded and setting the slot as FULL, + * as otherwise another thread may load and then destroy the key + * in the meantime. */ + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + /* + * On success, the pointer to the slot is passed directly to the caller + * thus no need to unlock the key slot here. + */ + status = psa_get_and_lock_key_slot_in_memory(key, p_slot); + if (status != PSA_ERROR_DOES_NOT_EXIST) { +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; + } + + /* Loading keys from storage requires support for such a mechanism */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ + defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + + status = psa_reserve_free_key_slot(NULL, p_slot); + if (status != PSA_SUCCESS) { +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; + } + + (*p_slot)->attr.id = key; + (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; + + status = PSA_ERROR_DOES_NOT_EXIST; +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + /* Load keys in the 'builtin' range through their own interface */ + status = psa_load_builtin_key_into_slot(*p_slot); +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if (status == PSA_ERROR_DOES_NOT_EXIST) { + status = psa_load_persistent_key_into_slot(*p_slot); + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + + if (status != PSA_SUCCESS) { + psa_wipe_key_slot(*p_slot); + + /* If the key does not exist, we need to return + * PSA_ERROR_INVALID_HANDLE. */ + if (status == PSA_ERROR_DOES_NOT_EXIST) { + status = PSA_ERROR_INVALID_HANDLE; + } + } else { + /* Add implicit usage flags. */ + psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage); + + psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING, + PSA_SLOT_FULL); + status = psa_register_read(*p_slot); + } + +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + status = PSA_ERROR_INVALID_HANDLE; +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + + if (status != PSA_SUCCESS) { + *p_slot = NULL; + } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; +} + +psa_status_t psa_unregister_read(psa_key_slot_t *slot) +{ + if (slot == NULL) { + return PSA_SUCCESS; + } + if ((slot->state != PSA_SLOT_FULL) && + (slot->state != PSA_SLOT_PENDING_DELETION)) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + + /* If we are the last reader and the slot is marked for deletion, + * we must wipe the slot here. */ + if ((slot->state == PSA_SLOT_PENDING_DELETION) && + (slot->var.occupied.registered_readers == 1)) { + return psa_wipe_key_slot(slot); + } + + if (psa_key_slot_has_readers(slot)) { + slot->var.occupied.registered_readers--; + return PSA_SUCCESS; + } + + /* + * As the return error code may not be handled in case of multiple errors, + * do our best to report if there are no registered readers. Assert with + * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers: + * if the MBEDTLS_TEST_HOOKS configuration option is enabled and + * the function is called as part of the execution of a test suite, the + * execution of the test suite is stopped in error if the assertion fails. + */ + MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot)); + return PSA_ERROR_CORRUPTION_DETECTED; +} + +psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + status = psa_unregister_read(slot); +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; +} + +psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, + psa_se_drv_table_entry_t **p_drv) +{ + if (psa_key_lifetime_is_external(lifetime)) { +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Check whether a driver is registered against this lifetime */ + psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime); + if (driver != NULL) { + if (p_drv != NULL) { + *p_drv = driver; + } + return PSA_SUCCESS; + } +#else /* MBEDTLS_PSA_CRYPTO_SE_C */ + (void) p_drv; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + /* Key location for external keys gets checked by the wrapper */ + return PSA_SUCCESS; + } else { + /* Local/internal keys are always valid */ + return PSA_SUCCESS; + } +} + +psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime) +{ + if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { + /* Volatile keys are always supported */ + return PSA_SUCCESS; + } else { + /* Persistent keys require storage support */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if (PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)) { + return PSA_ERROR_INVALID_ARGUMENT; + } else { + return PSA_SUCCESS; + } +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + return PSA_ERROR_NOT_SUPPORTED; +#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ + } +} + +psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle) +{ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ + defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + psa_status_t status; + psa_key_slot_t *slot; + + status = psa_get_and_lock_key_slot(key, &slot); + if (status != PSA_SUCCESS) { + *handle = PSA_KEY_HANDLE_INIT; + if (status == PSA_ERROR_INVALID_HANDLE) { + status = PSA_ERROR_DOES_NOT_EXIST; + } + + return status; + } + + *handle = key; + + return psa_unregister_read_under_mutex(slot); + +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + (void) key; + *handle = PSA_KEY_HANDLE_INIT; + return PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ +} + +psa_status_t psa_close_key(psa_key_handle_t handle) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + if (psa_key_handle_is_null(handle)) { + return PSA_SUCCESS; + } + +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + status = psa_get_and_lock_key_slot_in_memory(handle, &slot); + if (status != PSA_SUCCESS) { + if (status == PSA_ERROR_DOES_NOT_EXIST) { + status = PSA_ERROR_INVALID_HANDLE; + } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; + } + + if (slot->var.occupied.registered_readers == 1) { + status = psa_wipe_key_slot(slot); + } else { + status = psa_unregister_read(slot); + } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + + return status; +} + +psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + status = psa_get_and_lock_key_slot_in_memory(key, &slot); + if (status != PSA_SUCCESS) { +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; + } + + if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && + (slot->var.occupied.registered_readers == 1)) { + status = psa_wipe_key_slot(slot); + } else { + status = psa_unregister_read(slot); + } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + + return status; +} + +void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) +{ + memset(stats, 0, sizeof(*stats)); + + for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) { +#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) + if (global_data.key_slices[slice_idx] == NULL) { + continue; + } +#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ + for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) { + const psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx); + if (slot->state == PSA_SLOT_EMPTY) { + ++stats->empty_slots; + continue; + } + if (psa_key_slot_has_readers(slot)) { + ++stats->locked_slots; + } + if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { + ++stats->volatile_slots; + } else { + psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id); + ++stats->persistent_slots; + if (id > stats->max_open_internal_key_id) { + stats->max_open_internal_key_id = id; + } + } + if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) != + PSA_KEY_LOCATION_LOCAL_STORAGE) { + psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id); + ++stats->external_slots; + if (id > stats->max_open_external_key_id) { + stats->max_open_external_key_id = id; + } + } + } + } +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/thirdparty/mbedtls/library/psa_crypto_storage.c b/thirdparty/mbedtls/library/psa_crypto_storage.c new file mode 100644 index 0000000000..7d1317b45a --- /dev/null +++ b/thirdparty/mbedtls/library/psa_crypto_storage.c @@ -0,0 +1,481 @@ +/* + * PSA persistent key storage + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + +#include <stdlib.h> +#include <string.h> + +#include "psa/crypto.h" +#include "psa_crypto_storage.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#include "mbedtls/platform.h" + + + +/****************************************************************/ +/* Key storage */ +/****************************************************************/ + +/* Determine a file name (ITS file identifier) for the given key identifier. + * The file name must be distinct from any file that is used for a purpose + * other than storing a key. Currently, the only such file is the random seed + * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is + * 0xFFFFFF52. */ +static psa_storage_uid_t psa_its_identifier_of_slot(mbedtls_svc_key_id_t key) +{ +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + /* Encode the owner in the upper 32 bits. This means that if + * owner values are nonzero (as they are on a PSA platform), + * no key file will ever have a value less than 0x100000000, so + * the whole range 0..0xffffffff is available for non-key files. */ + uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key); + return ((uint64_t) unsigned_owner_id << 32) | + MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); +#else + /* Use the key id directly as a file name. + * psa_is_key_id_valid() in psa_crypto_slot_management.c + * is responsible for ensuring that key identifiers do not have a + * value that is reserved for non-key files. */ + return key; +#endif +} + +/** + * \brief Load persistent data for the given key slot number. + * + * This function reads data from a storage backend and returns the data in a + * buffer. + * + * \param key Persistent identifier of the key to be loaded. This + * should be an occupied storage location. + * \param[out] data Buffer where the data is to be written. + * \param data_size Size of the \c data buffer in bytes. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription + */ +static psa_status_t psa_crypto_storage_load( + const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); + struct psa_storage_info_t data_identifier_info; + size_t data_length = 0; + + status = psa_its_get_info(data_identifier, &data_identifier_info); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_its_get(data_identifier, 0, (uint32_t) data_size, data, &data_length); + if (data_size != data_length) { + return PSA_ERROR_DATA_INVALID; + } + + return status; +} + +int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info(data_identifier, &data_identifier_info); + + if (ret == PSA_ERROR_DOES_NOT_EXIST) { + return 0; + } + return 1; +} + +/** + * \brief Store persistent data for the given key slot number. + * + * This function stores the given data buffer to a persistent storage. + * + * \param key Persistent identifier of the key to be stored. This + * should be an unoccupied storage location. + * \param[in] data Buffer containing the data to be stored. + * \param data_length The number of bytes + * that make up the data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + */ +static psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); + struct psa_storage_info_t data_identifier_info; + + if (psa_is_key_present_in_storage(key) == 1) { + return PSA_ERROR_ALREADY_EXISTS; + } + + status = psa_its_set(data_identifier, (uint32_t) data_length, data, 0); + if (status != PSA_SUCCESS) { + return PSA_ERROR_DATA_INVALID; + } + + status = psa_its_get_info(data_identifier, &data_identifier_info); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (data_identifier_info.size != data_length) { + status = PSA_ERROR_DATA_INVALID; + goto exit; + } + +exit: + if (status != PSA_SUCCESS) { + /* Remove the file in case we managed to create it but something + * went wrong. It's ok if the file doesn't exist. If the file exists + * but the removal fails, we're already reporting an error so there's + * nothing else we can do. */ + (void) psa_its_remove(data_identifier); + } + return status; +} + +psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info(data_identifier, &data_identifier_info); + if (ret == PSA_ERROR_DOES_NOT_EXIST) { + return PSA_SUCCESS; + } + + if (psa_its_remove(data_identifier) != PSA_SUCCESS) { + return PSA_ERROR_DATA_INVALID; + } + + ret = psa_its_get_info(data_identifier, &data_identifier_info); + if (ret != PSA_ERROR_DOES_NOT_EXIST) { + return PSA_ERROR_DATA_INVALID; + } + + return PSA_SUCCESS; +} + +/** + * \brief Get data length for given key slot number. + * + * \param key Persistent identifier whose stored data length + * is to be obtained. + * \param[out] data_length The number of bytes that make up the data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + */ +static psa_status_t psa_crypto_storage_get_data_length( + const mbedtls_svc_key_id_t key, + size_t *data_length) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); + struct psa_storage_info_t data_identifier_info; + + status = psa_its_get_info(data_identifier, &data_identifier_info); + if (status != PSA_SUCCESS) { + return status; + } + + *data_length = (size_t) data_identifier_info.size; + + return PSA_SUCCESS; +} + +/** + * Persistent key storage magic header. + */ +#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" +#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH (sizeof(PSA_KEY_STORAGE_MAGIC_HEADER)) + +typedef struct { + uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; + uint8_t version[4]; + uint8_t lifetime[sizeof(psa_key_lifetime_t)]; + uint8_t type[2]; + uint8_t bits[2]; + uint8_t policy[sizeof(psa_key_policy_t)]; + uint8_t data_len[4]; + uint8_t key_data[]; +} psa_persistent_key_storage_format; + +void psa_format_key_data_for_storage(const uint8_t *data, + const size_t data_length, + const psa_key_attributes_t *attr, + uint8_t *storage_data) +{ + psa_persistent_key_storage_format *storage_format = + (psa_persistent_key_storage_format *) storage_data; + + memcpy(storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, + PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH); + MBEDTLS_PUT_UINT32_LE(0, storage_format->version, 0); + MBEDTLS_PUT_UINT32_LE(attr->lifetime, storage_format->lifetime, 0); + MBEDTLS_PUT_UINT16_LE((uint16_t) attr->type, storage_format->type, 0); + MBEDTLS_PUT_UINT16_LE((uint16_t) attr->bits, storage_format->bits, 0); + MBEDTLS_PUT_UINT32_LE(attr->policy.usage, storage_format->policy, 0); + MBEDTLS_PUT_UINT32_LE(attr->policy.alg, storage_format->policy, sizeof(uint32_t)); + MBEDTLS_PUT_UINT32_LE(attr->policy.alg2, storage_format->policy, 2 * sizeof(uint32_t)); + MBEDTLS_PUT_UINT32_LE(data_length, storage_format->data_len, 0); + memcpy(storage_format->key_data, data, data_length); +} + +static psa_status_t check_magic_header(const uint8_t *data) +{ + if (memcmp(data, PSA_KEY_STORAGE_MAGIC_HEADER, + PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH) != 0) { + return PSA_ERROR_DATA_INVALID; + } + return PSA_SUCCESS; +} + +psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, + size_t storage_data_length, + uint8_t **key_data, + size_t *key_data_length, + psa_key_attributes_t *attr) +{ + psa_status_t status; + const psa_persistent_key_storage_format *storage_format = + (const psa_persistent_key_storage_format *) storage_data; + uint32_t version; + + if (storage_data_length < sizeof(*storage_format)) { + return PSA_ERROR_DATA_INVALID; + } + + status = check_magic_header(storage_data); + if (status != PSA_SUCCESS) { + return status; + } + + version = MBEDTLS_GET_UINT32_LE(storage_format->version, 0); + if (version != 0) { + return PSA_ERROR_DATA_INVALID; + } + + *key_data_length = MBEDTLS_GET_UINT32_LE(storage_format->data_len, 0); + if (*key_data_length > (storage_data_length - sizeof(*storage_format)) || + *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { + return PSA_ERROR_DATA_INVALID; + } + + if (*key_data_length == 0) { + *key_data = NULL; + } else { + *key_data = mbedtls_calloc(1, *key_data_length); + if (*key_data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + memcpy(*key_data, storage_format->key_data, *key_data_length); + } + + attr->lifetime = MBEDTLS_GET_UINT32_LE(storage_format->lifetime, 0); + attr->type = MBEDTLS_GET_UINT16_LE(storage_format->type, 0); + attr->bits = MBEDTLS_GET_UINT16_LE(storage_format->bits, 0); + attr->policy.usage = MBEDTLS_GET_UINT32_LE(storage_format->policy, 0); + attr->policy.alg = MBEDTLS_GET_UINT32_LE(storage_format->policy, sizeof(uint32_t)); + attr->policy.alg2 = MBEDTLS_GET_UINT32_LE(storage_format->policy, 2 * sizeof(uint32_t)); + + return PSA_SUCCESS; +} + +psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, + const uint8_t *data, + const size_t data_length) +{ + size_t storage_data_length; + uint8_t *storage_data; + psa_status_t status; + + /* All keys saved to persistent storage always have a key context */ + if (data == NULL || data_length == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { + return PSA_ERROR_INSUFFICIENT_STORAGE; + } + storage_data_length = data_length + sizeof(psa_persistent_key_storage_format); + + storage_data = mbedtls_calloc(1, storage_data_length); + if (storage_data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + psa_format_key_data_for_storage(data, data_length, attr, storage_data); + + status = psa_crypto_storage_store(attr->id, + storage_data, storage_data_length); + + mbedtls_zeroize_and_free(storage_data, storage_data_length); + + return status; +} + +void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length) +{ + mbedtls_zeroize_and_free(key_data, key_data_length); +} + +psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, + uint8_t **data, + size_t *data_length) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *loaded_data; + size_t storage_data_length = 0; + mbedtls_svc_key_id_t key = attr->id; + + status = psa_crypto_storage_get_data_length(key, &storage_data_length); + if (status != PSA_SUCCESS) { + return status; + } + + loaded_data = mbedtls_calloc(1, storage_data_length); + + if (loaded_data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + status = psa_crypto_storage_load(key, loaded_data, storage_data_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_parse_key_data_from_storage(loaded_data, storage_data_length, + data, data_length, attr); + + /* All keys saved to persistent storage always have a key context */ + if (status == PSA_SUCCESS && + (*data == NULL || *data_length == 0)) { + status = PSA_ERROR_STORAGE_FAILURE; + } + +exit: + mbedtls_zeroize_and_free(loaded_data, storage_data_length); + return status; +} + + + +/****************************************************************/ +/* Transactions */ +/****************************************************************/ + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + +psa_crypto_transaction_t psa_crypto_transaction; + +psa_status_t psa_crypto_save_transaction(void) +{ + struct psa_storage_info_t p_info; + psa_status_t status; + status = psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info); + if (status == PSA_SUCCESS) { + /* This shouldn't happen: we're trying to start a transaction while + * there is still a transaction that hasn't been replayed. */ + return PSA_ERROR_CORRUPTION_DETECTED; + } else if (status != PSA_ERROR_DOES_NOT_EXIST) { + return status; + } + return psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID, + sizeof(psa_crypto_transaction), + &psa_crypto_transaction, + 0); +} + +psa_status_t psa_crypto_load_transaction(void) +{ + psa_status_t status; + size_t length; + status = psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID, 0, + sizeof(psa_crypto_transaction), + &psa_crypto_transaction, &length); + if (status != PSA_SUCCESS) { + return status; + } + if (length != sizeof(psa_crypto_transaction)) { + return PSA_ERROR_DATA_INVALID; + } + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_stop_transaction(void) +{ + psa_status_t status = psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID); + /* Whether or not updating the storage succeeded, the transaction is + * finished now. It's too late to go back, so zero out the in-memory + * data. */ + memset(&psa_crypto_transaction, 0, sizeof(psa_crypto_transaction)); + return status; +} + +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + + + +/****************************************************************/ +/* Random generator state */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed, + size_t seed_size) +{ + psa_status_t status; + struct psa_storage_info_t p_info; + + status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info); + + if (PSA_ERROR_DOES_NOT_EXIST == status) { /* No seed exists */ + status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0); + } else if (PSA_SUCCESS == status) { + /* You should not be here. Seed needs to be injected only once */ + status = PSA_ERROR_NOT_PERMITTED; + } + return status; +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ diff --git a/thirdparty/mbedtls/library/psa_its_file.c b/thirdparty/mbedtls/library/psa_its_file.c new file mode 100644 index 0000000000..9567137483 --- /dev/null +++ b/thirdparty/mbedtls/library/psa_its_file.c @@ -0,0 +1,254 @@ +/* + * PSA ITS simulator over stdio files. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) + +#include "mbedtls/platform.h" + +#if defined(_WIN32) +#include <windows.h> +#endif + +#include "psa_crypto_its.h" + +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#if !defined(PSA_ITS_STORAGE_PREFIX) +#define PSA_ITS_STORAGE_PREFIX "" +#endif + +#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x" +#define PSA_ITS_STORAGE_SUFFIX ".psa_its" +#define PSA_ITS_STORAGE_FILENAME_LENGTH \ + (sizeof(PSA_ITS_STORAGE_PREFIX) - 1 + /*prefix without terminating 0*/ \ + 16 + /*UID (64-bit number in hex)*/ \ + sizeof(PSA_ITS_STORAGE_SUFFIX) - 1 + /*suffix without terminating 0*/ \ + 1 /*terminating null byte*/) +#define PSA_ITS_STORAGE_TEMP \ + PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX + +/* The maximum value of psa_storage_info_t.size */ +#define PSA_ITS_MAX_SIZE 0xffffffff + +#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0" +#define PSA_ITS_MAGIC_LENGTH 8 + +/* As rename fails on Windows if the new filepath already exists, + * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead. + * Returns 0 on success, nonzero on failure. */ +#if defined(_WIN32) +#define rename_replace_existing(oldpath, newpath) \ + (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) +#else +#define rename_replace_existing(oldpath, newpath) rename(oldpath, newpath) +#endif + +typedef struct { + uint8_t magic[PSA_ITS_MAGIC_LENGTH]; + uint8_t size[sizeof(uint32_t)]; + uint8_t flags[sizeof(psa_storage_create_flags_t)]; +} psa_its_file_header_t; + +static void psa_its_fill_filename(psa_storage_uid_t uid, char *filename) +{ + /* Break up the UID into two 32-bit pieces so as not to rely on + * long long support in snprintf. */ + mbedtls_snprintf(filename, PSA_ITS_STORAGE_FILENAME_LENGTH, + "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s", + PSA_ITS_STORAGE_PREFIX, + (unsigned) (uid >> 32), + (unsigned) (uid & 0xffffffff), + PSA_ITS_STORAGE_SUFFIX); +} + +static psa_status_t psa_its_read_file(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info, + FILE **p_stream) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + psa_its_file_header_t header; + size_t n; + + *p_stream = NULL; + psa_its_fill_filename(uid, filename); + *p_stream = fopen(filename, "rb"); + if (*p_stream == NULL) { + return PSA_ERROR_DOES_NOT_EXIST; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(*p_stream, NULL); + + n = fread(&header, 1, sizeof(header), *p_stream); + if (n != sizeof(header)) { + return PSA_ERROR_DATA_CORRUPT; + } + if (memcmp(header.magic, PSA_ITS_MAGIC_STRING, + PSA_ITS_MAGIC_LENGTH) != 0) { + return PSA_ERROR_DATA_CORRUPT; + } + + p_info->size = MBEDTLS_GET_UINT32_LE(header.size, 0); + p_info->flags = MBEDTLS_GET_UINT32_LE(header.flags, 0); + + return PSA_SUCCESS; +} + +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + psa_status_t status; + FILE *stream = NULL; + status = psa_its_read_file(uid, p_info, &stream); + if (stream != NULL) { + fclose(stream); + } + return status; +} + +psa_status_t psa_its_get(psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length) +{ + psa_status_t status; + FILE *stream = NULL; + size_t n; + struct psa_storage_info_t info; + + status = psa_its_read_file(uid, &info, &stream); + if (status != PSA_SUCCESS) { + goto exit; + } + status = PSA_ERROR_INVALID_ARGUMENT; + if (data_offset + data_length < data_offset) { + goto exit; + } +#if SIZE_MAX < 0xffffffff + if (data_offset + data_length > SIZE_MAX) { + goto exit; + } +#endif + if (data_offset + data_length > info.size) { + goto exit; + } + + status = PSA_ERROR_STORAGE_FAILURE; +#if LONG_MAX < 0xffffffff + while (data_offset > LONG_MAX) { + if (fseek(stream, LONG_MAX, SEEK_CUR) != 0) { + goto exit; + } + data_offset -= LONG_MAX; + } +#endif + if (fseek(stream, data_offset, SEEK_CUR) != 0) { + goto exit; + } + n = fread(p_data, 1, data_length, stream); + if (n != data_length) { + goto exit; + } + status = PSA_SUCCESS; + if (p_data_length != NULL) { + *p_data_length = n; + } + +exit: + if (stream != NULL) { + fclose(stream); + } + return status; +} + +psa_status_t psa_its_set(psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + if (uid == 0) { + return PSA_ERROR_INVALID_HANDLE; + } + + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream = NULL; + psa_its_file_header_t header; + size_t n; + + memcpy(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH); + MBEDTLS_PUT_UINT32_LE(data_length, header.size, 0); + MBEDTLS_PUT_UINT32_LE(create_flags, header.flags, 0); + + psa_its_fill_filename(uid, filename); + stream = fopen(PSA_ITS_STORAGE_TEMP, "wb"); + + if (stream == NULL) { + goto exit; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(stream, NULL); + + status = PSA_ERROR_INSUFFICIENT_STORAGE; + n = fwrite(&header, 1, sizeof(header), stream); + if (n != sizeof(header)) { + goto exit; + } + if (data_length != 0) { + n = fwrite(p_data, 1, data_length, stream); + if (n != data_length) { + goto exit; + } + } + status = PSA_SUCCESS; + +exit: + if (stream != NULL) { + int ret = fclose(stream); + if (status == PSA_SUCCESS && ret != 0) { + status = PSA_ERROR_INSUFFICIENT_STORAGE; + } + } + if (status == PSA_SUCCESS) { + if (rename_replace_existing(PSA_ITS_STORAGE_TEMP, filename) != 0) { + status = PSA_ERROR_STORAGE_FAILURE; + } + } + /* The temporary file may still exist, but only in failure cases where + * we're already reporting an error. So there's nothing we can do on + * failure. If the function succeeded, and in some error cases, the + * temporary file doesn't exist and so remove() is expected to fail. + * Thus we just ignore the return status of remove(). */ + (void) remove(PSA_ITS_STORAGE_TEMP); + return status; +} + +psa_status_t psa_its_remove(psa_storage_uid_t uid) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream; + psa_its_fill_filename(uid, filename); + stream = fopen(filename, "rb"); + if (stream == NULL) { + return PSA_ERROR_DOES_NOT_EXIST; + } + fclose(stream); + if (remove(filename) != 0) { + return PSA_ERROR_STORAGE_FAILURE; + } + return PSA_SUCCESS; +} + +#endif /* MBEDTLS_PSA_ITS_FILE_C */ diff --git a/thirdparty/mbedtls/library/psa_util.c b/thirdparty/mbedtls/library/psa_util.c new file mode 100644 index 0000000000..679d00ea9b --- /dev/null +++ b/thirdparty/mbedtls/library/psa_util.c @@ -0,0 +1,608 @@ +/* + * PSA hashing layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +/* This is needed for MBEDTLS_ERR_XXX macros */ +#include <mbedtls/error.h> + +#if defined(MBEDTLS_ASN1_WRITE_C) +#include <mbedtls/asn1write.h> +#include <psa/crypto_sizes.h> +#endif + +#include "psa_util_internal.h" + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) + +#include <psa/crypto.h> + +#if defined(MBEDTLS_MD_LIGHT) +#include <mbedtls/md.h> +#endif +#if defined(MBEDTLS_LMS_C) +#include <mbedtls/lms.h> +#endif +#if defined(MBEDTLS_SSL_TLS_C) && \ + (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) +#include <mbedtls/ssl.h> +#endif +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#include <mbedtls/rsa.h> +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#include <mbedtls/ecp.h> +#endif +#if defined(MBEDTLS_PK_C) +#include <mbedtls/pk.h> +#endif +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +#include <mbedtls/cipher.h> +#endif +#include <mbedtls/entropy.h> + +/* PSA_SUCCESS is kept at the top of each error table since + * it's the most common status when everything functions properly. */ +#if defined(MBEDTLS_MD_LIGHT) +const mbedtls_error_pair_t psa_to_md_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_MD_BAD_INPUT_DATA }, + { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_MD_ALLOC_FAILED } +}; +#endif + +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +const mbedtls_error_pair_t psa_to_cipher_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA }, + { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_CIPHER_ALLOC_FAILED } +}; +#endif + +#if defined(MBEDTLS_LMS_C) +const mbedtls_error_pair_t psa_to_lms_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_LMS_BAD_INPUT_DATA } +}; +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && \ + (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) +const mbedtls_error_pair_t psa_to_ssl_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_SSL_ALLOC_FAILED }, + { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE }, + { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_SSL_INVALID_MAC }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_SSL_BAD_INPUT_DATA }, + { PSA_ERROR_BAD_STATE, MBEDTLS_ERR_SSL_INTERNAL_ERROR }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL } +}; +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +const mbedtls_error_pair_t psa_to_pk_rsa_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE }, + { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_RSA_RNG_FAILED }, + { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_RSA_VERIFY_FAILED }, + { PSA_ERROR_INVALID_PADDING, MBEDTLS_ERR_RSA_INVALID_PADDING } +}; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL }, + { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_ECP_RANDOM_FAILED }, + { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_ECP_VERIFY_FAILED } +}; +#endif + +int psa_generic_status_to_mbedtls(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_NOT_PERMITTED: + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} + +int psa_status_to_mbedtls(psa_status_t status, + const mbedtls_error_pair_t *local_translations, + size_t local_errors_num, + int (*fallback_f)(psa_status_t)) +{ + for (size_t i = 0; i < local_errors_num; i++) { + if (status == local_translations[i].psa_status) { + return local_translations[i].mbedtls_error; + } + } + return fallback_f(status); +} + +#if defined(MBEDTLS_PK_C) +int psa_pk_status_to_mbedtls(psa_status_t status) +{ + switch (status) { + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_PK_INVALID_ALG; + case PSA_ERROR_NOT_PERMITTED: + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_PK_ALLOC_FAILED; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + default: + return psa_generic_status_to_mbedtls(status); + } +} +#endif /* MBEDTLS_PK_C */ + +/****************************************************************/ +/* Key management */ +/****************************************************************/ + +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, + size_t *bits) +{ + switch (grpid) { +#if defined(MBEDTLS_ECP_HAVE_SECP192R1) + case MBEDTLS_ECP_DP_SECP192R1: + *bits = 192; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP224R1) + case MBEDTLS_ECP_DP_SECP224R1: + *bits = 224; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP256R1) + case MBEDTLS_ECP_DP_SECP256R1: + *bits = 256; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP384R1) + case MBEDTLS_ECP_DP_SECP384R1: + *bits = 384; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP521R1) + case MBEDTLS_ECP_DP_SECP521R1: + *bits = 521; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_BP256R1) + case MBEDTLS_ECP_DP_BP256R1: + *bits = 256; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_BP384R1) + case MBEDTLS_ECP_DP_BP384R1: + *bits = 384; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_BP512R1) + case MBEDTLS_ECP_DP_BP512R1: + *bits = 512; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) + case MBEDTLS_ECP_DP_CURVE25519: + *bits = 255; + return PSA_ECC_FAMILY_MONTGOMERY; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP192K1) + case MBEDTLS_ECP_DP_SECP192K1: + *bits = 192; + return PSA_ECC_FAMILY_SECP_K1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP224K1) + /* secp224k1 is not and will not be supported in PSA (#3541). */ +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP256K1) + case MBEDTLS_ECP_DP_SECP256K1: + *bits = 256; + return PSA_ECC_FAMILY_SECP_K1; +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE448) + case MBEDTLS_ECP_DP_CURVE448: + *bits = 448; + return PSA_ECC_FAMILY_MONTGOMERY; +#endif + default: + *bits = 0; + return 0; + } +} + +mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family, + size_t bits) +{ + switch (family) { + case PSA_ECC_FAMILY_SECP_R1: + switch (bits) { +#if defined(PSA_WANT_ECC_SECP_R1_192) + case 192: + return MBEDTLS_ECP_DP_SECP192R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_224) + case 224: + return MBEDTLS_ECP_DP_SECP224R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_256) + case 256: + return MBEDTLS_ECP_DP_SECP256R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_384) + case 384: + return MBEDTLS_ECP_DP_SECP384R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_521) + case 521: + return MBEDTLS_ECP_DP_SECP521R1; +#endif + } + break; + + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch (bits) { +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) + case 256: + return MBEDTLS_ECP_DP_BP256R1; +#endif +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) + case 384: + return MBEDTLS_ECP_DP_BP384R1; +#endif +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) + case 512: + return MBEDTLS_ECP_DP_BP512R1; +#endif + } + break; + + case PSA_ECC_FAMILY_MONTGOMERY: + switch (bits) { +#if defined(PSA_WANT_ECC_MONTGOMERY_255) + case 255: + return MBEDTLS_ECP_DP_CURVE25519; +#endif +#if defined(PSA_WANT_ECC_MONTGOMERY_448) + case 448: + return MBEDTLS_ECP_DP_CURVE448; +#endif + } + break; + + case PSA_ECC_FAMILY_SECP_K1: + switch (bits) { +#if defined(PSA_WANT_ECC_SECP_K1_192) + case 192: + return MBEDTLS_ECP_DP_SECP192K1; +#endif +#if defined(PSA_WANT_ECC_SECP_K1_224) + /* secp224k1 is not and will not be supported in PSA (#3541). */ +#endif +#if defined(PSA_WANT_ECC_SECP_K1_256) + case 256: + return MBEDTLS_ECP_DP_SECP256K1; +#endif + } + break; + } + + return MBEDTLS_ECP_DP_NONE; +} +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ + +/* Wrapper function allowing the classic API to use the PSA RNG. + * + * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls + * `psa_generate_random(...)`. The state parameter is ignored since the + * PSA API doesn't support passing an explicit state. + */ +int mbedtls_psa_get_random(void *p_rng, + unsigned char *output, + size_t output_size) +{ + /* This function takes a pointer to the RNG state because that's what + * classic mbedtls functions using an RNG expect. The PSA RNG manages + * its own state internally and doesn't let the caller access that state. + * So we just ignore the state parameter, and in practice we'll pass + * NULL. */ + (void) p_rng; + psa_status_t status = psa_generate_random(output, output_size); + if (status == PSA_SUCCESS) { + return 0; + } else { + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + } +} + +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ + +#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) + +/** + * \brief Convert a single raw coordinate to DER ASN.1 format. The output der + * buffer is filled backward (i.e. starting from its end). + * + * \param raw_buf Buffer containing the raw coordinate to be + * converted. + * \param raw_len Length of raw_buf in bytes. This must be > 0. + * \param der_buf_start Pointer to the beginning of the buffer which + * will be filled with the DER converted data. + * \param der_buf_end End of the buffer used to store the DER output. + * + * \return On success, the amount of data (in bytes) written to + * the DER buffer. + * \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der + * buffer is too small to contain all the converted data. + * \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw + * coordinate is null (i.e. all zeros). + * + * \warning Raw and der buffer must not be overlapping. + */ +static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len, + unsigned char *der_buf_start, + unsigned char *der_buf_end) +{ + unsigned char *p = der_buf_end; + int len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Provided input MPIs should not be 0, but as a failsafe measure, still + * detect that and return error in case. */ + while (*raw_buf == 0x00) { + ++raw_buf; + --raw_len; + if (raw_len == 0) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + } + len = (int) raw_len; + + /* Copy the raw coordinate to the end of der_buf. */ + if ((p - der_buf_start) < len) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + p -= len; + memcpy(p, raw_buf, len); + + /* If MSb is 1, ASN.1 requires that we prepend a 0. */ + if (*p & 0x80) { + if ((p - der_buf_start) < 1) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + --p; + *p = 0x00; + ++len; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER)); + + return len; +} + +int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len, + unsigned char *der, size_t der_size, size_t *der_len) +{ + unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + const size_t coordinate_len = PSA_BITS_TO_BYTES(bits); + size_t len = 0; + unsigned char *p = der + der_size; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (raw_len != (2 * coordinate_len)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + if (coordinate_len > sizeof(r)) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + /* Since raw and der buffers might overlap, dump r and s before starting + * the conversion. */ + memcpy(r, raw, coordinate_len); + memcpy(s, raw + coordinate_len, coordinate_len); + + /* der buffer will initially be written starting from its end so we pick s + * first and then r. */ + ret = convert_raw_to_der_single_int(s, coordinate_len, der, p); + if (ret < 0) { + return ret; + } + p -= ret; + len += ret; + + ret = convert_raw_to_der_single_int(r, coordinate_len, der, p); + if (ret < 0) { + return ret; + } + p -= ret; + len += ret; + + /* Add ASN.1 header (len + tag). */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + /* memmove the content of der buffer to its beginnig. */ + memmove(der, p, len); + *der_len = len; + + return 0; +} + +/** + * \brief Convert a single integer from ASN.1 DER format to raw. + * + * \param der Buffer containing the DER integer value to be + * converted. + * \param der_len Length of the der buffer in bytes. + * \param raw Output buffer that will be filled with the + * converted data. This should be at least + * coordinate_size bytes and it must be zeroed before + * calling this function. + * \param coordinate_size Size (in bytes) of a single coordinate in raw + * format. + * + * \return On success, the amount of DER data parsed from the + * provided der buffer. + * \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag + * is missing in the der buffer. + * \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer + * is null (i.e. all zeros) or if the output raw buffer + * is too small to contain the converted raw value. + * + * \warning Der and raw buffers must not be overlapping. + */ +static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len, + unsigned char *raw, size_t coordinate_size) +{ + unsigned char *p = der; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t unpadded_len, padding_len = 0; + + /* Get the length of ASN.1 element (i.e. the integer we need to parse). */ + ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len, + MBEDTLS_ASN1_INTEGER); + if (ret != 0) { + return ret; + } + + /* It's invalid to have: + * - unpadded_len == 0. + * - MSb set without a leading 0x00 (leading 0x00 is checked below). */ + if (((unpadded_len == 0) || (*p & 0x80) != 0)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + + /* Skip possible leading zero */ + if (*p == 0x00) { + p++; + unpadded_len--; + /* It is not allowed to have more than 1 leading zero. + * Ignore the case in which unpadded_len = 0 because that's a 0 encoded + * in ASN.1 format (i.e. 020100). */ + if ((unpadded_len > 0) && (*p == 0x00)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + } + + if (unpadded_len > coordinate_size) { + /* Parsed number is longer than the maximum expected value. */ + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + padding_len = coordinate_size - unpadded_len; + /* raw buffer was already zeroed by the calling function so zero-padding + * operation is skipped here. */ + memcpy(raw + padding_len, p, unpadded_len); + p += unpadded_len; + + return (int) (p - der); +} + +int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len, + unsigned char *raw, size_t raw_size, size_t *raw_len) +{ + unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; + unsigned char *p = (unsigned char *) der; + size_t data_len; + size_t coordinate_size = PSA_BITS_TO_BYTES(bits); + int ret; + + /* The output raw buffer should be at least twice the size of a raw + * coordinate in order to store r and s. */ + if (raw_size < coordinate_size * 2) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + if (2 * coordinate_size > sizeof(raw_tmp)) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + /* Check that the provided input DER buffer has the right header. */ + ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return ret; + } + + memset(raw_tmp, 0, 2 * coordinate_size); + + /* Extract r */ + ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size); + if (ret < 0) { + return ret; + } + p += ret; + data_len -= ret; + + /* Extract s */ + ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size, + coordinate_size); + if (ret < 0) { + return ret; + } + p += ret; + data_len -= ret; + + /* Check that we consumed all the input der data. */ + if ((size_t) (p - der) != der_len) { + return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } + + memcpy(raw, raw_tmp, 2 * coordinate_size); + *raw_len = 2 * coordinate_size; + + return 0; +} + +#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */ diff --git a/thirdparty/miniupnpc/include/miniupnpc.h b/thirdparty/miniupnpc/include/miniupnpc.h index 808c6ad975..fd951a0836 100644 --- a/thirdparty/miniupnpc/include/miniupnpc.h +++ b/thirdparty/miniupnpc/include/miniupnpc.h @@ -1,9 +1,9 @@ -/* $Id: miniupnpc.h,v 1.63 2024/01/04 00:45:17 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.66 2024/06/08 22:13:14 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project: miniupnp * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author: Thomas Bernard - * Copyright (c) 2005-2022 Thomas Bernard + * Copyright (c) 2005-2024 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPC_H_INCLUDED @@ -20,8 +20,8 @@ #define UPNPDISCOVER_MEMORY_ERROR (-102) /* versions : */ -#define MINIUPNPC_VERSION "2.2.6" -#define MINIUPNPC_API_VERSION 17 +#define MINIUPNPC_VERSION "2.2.8" +#define MINIUPNPC_API_VERSION 18 /* Source port: Using "1" as an alias for 1900 for backwards compatibility @@ -108,9 +108,11 @@ struct UPNPUrls { * return values : * 0 = NO IGD found * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as + * 2 = A valid connected IGD has been found but its + * IP address is reserved (non routable) + * 3 = A valid IGD has been found but it reported as * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD + * 4 = an UPnP device has been found but was not recognized as an IGD * * In any non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to @@ -119,8 +121,9 @@ struct UPNPUrls { MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); + struct IGDdatas * data, + char * lanaddr, int lanaddrlen, + char * wanaddr, int wanaddrlen); /* UPNP_GetIGDFromUrl() * Used when skipping the discovery process. diff --git a/thirdparty/miniupnpc/src/addr_is_reserved.c b/thirdparty/miniupnpc/src/addr_is_reserved.c index 18c6424201..145b504823 100644 --- a/thirdparty/miniupnpc/src/addr_is_reserved.c +++ b/thirdparty/miniupnpc/src/addr_is_reserved.c @@ -3,7 +3,7 @@ * Project : miniupnp * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2021 Thomas Bernard + * copyright (c) 2005-2024 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #ifdef _WIN32 @@ -21,6 +21,9 @@ typedef unsigned long uint32_t; #include <netinet/in.h> #include <arpa/inet.h> #endif /* _WIN32 */ +#ifdef DEBUG +#include <stdio.h> +#endif /* List of IP address blocks which are private / reserved and therefore not suitable for public external IP addresses */ #define IP(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) @@ -71,8 +74,12 @@ int addr_is_reserved(const char * addr_str) address = ntohl(addr_n); for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); ++i) { - if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask)) + if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask)) { +#ifdef DEBUG + printf("IP address %s is reserved\n", addr_str); +#endif return 1; + } } return 0; diff --git a/thirdparty/miniupnpc/src/minisoap.c b/thirdparty/miniupnpc/src/minisoap.c index 903ac5ffc6..5c6bf01684 100644 --- a/thirdparty/miniupnpc/src/minisoap.c +++ b/thirdparty/miniupnpc/src/minisoap.c @@ -2,7 +2,7 @@ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2023 Thomas Bernard + * Copyright (c) 2005-2024 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * @@ -83,7 +83,7 @@ int soapPostSubmit(SOCKET fd, * Using HTTP/1.1 means we need to support chunked transfer-encoding : * When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked * transfer encoding. */ - /* Connection: Close is normally there only in HTTP/1.1 but who knows */ + /* Connection: close is normally there only in HTTP/1.1 but who knows */ portstr[0] = '\0'; if(port != 80) snprintf(portstr, sizeof(portstr), ":%hu", port); @@ -98,9 +98,8 @@ int soapPostSubmit(SOCKET fd, "Content-Type: text/xml; charset=\"utf-8\"\r\n" #endif "SOAPAction: \"%s\"\r\n" - "Connection: Close\r\n" + "Connection: close\r\n" "Cache-Control: no-cache\r\n" /* ??? */ - "Pragma: no-cache\r\n" "\r\n", url, httpversion, host, portstr, bodysize, action); if ((unsigned int)headerssize >= sizeof(headerbuf)) diff --git a/thirdparty/miniupnpc/src/minissdpc.c b/thirdparty/miniupnpc/src/minissdpc.c index 98c5b37463..57cb99962e 100644 --- a/thirdparty/miniupnpc/src/minissdpc.c +++ b/thirdparty/miniupnpc/src/minissdpc.c @@ -1,9 +1,9 @@ -/* $Id: minissdpc.c,v 1.49 2021/05/13 11:00:36 nanard Exp $ */ +/* $Id: minissdpc.c,v 1.51 2024/05/16 00:12:05 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2021 Thomas Bernard + * copyright (c) 2005-2024 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #include <stdio.h> @@ -548,7 +548,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], #ifdef _WIN32 unsigned long _ttl = (unsigned long)ttl; #endif - int linklocal = 1; + int linklocal = 0; /* try first with site-local multicast */ int sentok; if(error) @@ -1007,9 +1007,10 @@ ssdpDiscoverDevices(const char * const deviceTypes[], /* switch linklocal flag */ if(linklocal) { linklocal = 0; - --deviceIndex; } else { + /* try again with linklocal multicast */ linklocal = 1; + --deviceIndex; } } } diff --git a/thirdparty/miniupnpc/src/miniupnpc.c b/thirdparty/miniupnpc/src/miniupnpc.c index 696af93237..9da1496b37 100644 --- a/thirdparty/miniupnpc/src/miniupnpc.c +++ b/thirdparty/miniupnpc/src/miniupnpc.c @@ -3,7 +3,7 @@ * Project : miniupnp * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2021 Thomas Bernard + * copyright (c) 2005-2024 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #include <stdlib.h> @@ -92,15 +92,15 @@ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGD #endif } -/* simpleUPnPcommand2 : +/* simpleUPnPcommand : * not so simple ! * return values : * pointer - OK * NULL - error */ -static char * -simpleUPnPcommand2(SOCKET s, const char * url, const char * service, - const char * action, struct UPNParg * args, - int * bufsize, const char * httpversion) +char * +simpleUPnPcommand(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + int * bufsize) { char hostname[MAXHOSTNAMELEN+1]; unsigned short port = 0; @@ -197,15 +197,15 @@ simpleUPnPcommand2(SOCKET s, const char * url, const char * service, return NULL; } if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; - if(ISINVALID(s)) { + if(ISINVALID((SOCKET)s)) { s = connecthostport(hostname, port, 0); - if(ISINVALID(s)) { + if(ISINVALID((SOCKET)s)) { /* failed to connect */ return NULL; } } - n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); + n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, "1.1"); if(n<=0) { #ifdef DEBUG printf("Error sending SOAP request\n"); @@ -229,33 +229,6 @@ simpleUPnPcommand2(SOCKET s, const char * url, const char * service, return buf; } -/* simpleUPnPcommand : - * not so simple ! - * return values : - * pointer - OK - * NULL - error */ -char * -simpleUPnPcommand(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, - int * bufsize) -{ - char * buf; - -#if 1 - buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1"); -#else - buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.0"); - if (!buf || *bufsize == 0) - { -#if DEBUG - printf("Error or no result from SOAP request; retrying with HTTP/1.1\n"); -#endif - buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1"); - } -#endif - return buf; -} - /* upnpDiscoverDevices() : * return a chained list of all devices found or NULL if * no devices was found. @@ -534,9 +507,11 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) * -1 = Internal error * 0 = NO IGD found * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as + * 2 = A valid connected IGD has been found but its + * IP address is reserved (non routable) + * 3 = A valid IGD has been found but it reported as * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD + * 4 = an UPnP device has been found but was not recognized as an IGD * * In any positive non zero return case, the urls and data structures * passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to @@ -545,11 +520,13 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen) + struct IGDdatas * data, + char * lanaddr, int lanaddrlen, + char * wanaddr, int wanaddrlen) { struct xml_desc { char lanaddr[40]; + char wanaddr[40]; char * xml; int size; int is_igd; @@ -557,8 +534,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPDev * dev; int ndev = 0; int i; - int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ - char extIpAddr[16]; + int state = -1; /* state 1 : IGD connected. State 2 : connected with reserved IP. + * State 3 : IGD. State 4 : anything */ int status_code = -1; if(!devlist) @@ -602,7 +579,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, } } /* iterate the list to find a device depending on state */ - for(state = 1; state <= 3; state++) + for(state = 1; state <= 4; state++) { for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { @@ -611,14 +588,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); - if(desc[i].is_igd || state >= 3 ) + if(desc[i].is_igd || state >= 4 ) { int is_connected; GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); - /* in state 2 and 3 we don't test if device is connected ! */ - if(state >= 2) + /* in state 3 and 4 we don't test if device is connected ! */ + if(state >= 3) goto free_and_return; is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG @@ -626,9 +603,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, urls->controlURL, is_connected); #endif /* checks that status is connected AND there is a external IP address assigned */ - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!addr_is_reserved(extIpAddr)) + if(is_connected) { + if(state >= 2) + goto free_and_return; + if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0 + && !addr_is_reserved(desc[i].wanaddr)) goto free_and_return; } FreeUPNPUrls(urls); @@ -647,9 +626,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, is_connected); #endif - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!addr_is_reserved(extIpAddr)) + if(is_connected) { + if(state >= 2) + goto free_and_return; + if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0 + && !addr_is_reserved(desc[i].wanaddr)) goto free_and_return; } FreeUPNPUrls(urls); @@ -661,8 +642,12 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, } state = 0; free_and_return: - if (lanaddr != NULL && state >= 1 && state <= 3 && i < ndev) - strncpy(lanaddr, desc[i].lanaddr, lanaddrlen); + if (state >= 1 && state <= 4 && i < ndev) { + if (lanaddr != NULL) + strncpy(lanaddr, desc[i].lanaddr, lanaddrlen); + if (wanaddr != NULL) + strncpy(wanaddr, desc[i].wanaddr, wanaddrlen); + } for(i = 0; i < ndev; i++) free(desc[i].xml); free(desc); diff --git a/thirdparty/miniupnpc/src/miniupnpcstrings.h b/thirdparty/miniupnpc/src/miniupnpcstrings.h index f5730111af..d40c2455ba 100644 --- a/thirdparty/miniupnpc/src/miniupnpcstrings.h +++ b/thirdparty/miniupnpc/src/miniupnpcstrings.h @@ -2,7 +2,7 @@ #define MINIUPNPCSTRINGS_H_INCLUDED #define OS_STRING "Godot Engine/1.0" -#define MINIUPNPC_VERSION_STRING "2.2.7" +#define MINIUPNPC_VERSION_STRING "2.2.8" #if 0 /* according to "UPnP Device Architecture 1.0" */ diff --git a/thirdparty/miniupnpc/src/miniwget.c b/thirdparty/miniupnpc/src/miniwget.c index e76a5e516b..a7a32dfdba 100644 --- a/thirdparty/miniupnpc/src/miniwget.c +++ b/thirdparty/miniupnpc/src/miniwget.c @@ -2,7 +2,7 @@ /* Project : miniupnp * Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas Bernard - * Copyright (c) 2005-2023 Thomas Bernard + * Copyright (c) 2005-2024 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -443,9 +443,8 @@ miniwget3(const char * host, len = snprintf(buf, sizeof(buf), "GET %s HTTP/%s\r\n" "Host: %s:%d\r\n" - "Connection: Close\r\n" + "Connection: close\r\n" "User-Agent: " OS_STRING " " UPNP_VERSION_STRING " MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" - "\r\n", path, httpversion, host, port); if ((unsigned int)len >= sizeof(buf)) @@ -474,41 +473,6 @@ miniwget3(const char * host, return content; } -/* miniwget2() : - * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */ -static void * -miniwget2(const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len, - unsigned int scope_id, int * status_code) -{ - char * respbuffer; - -#if 1 - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", - scope_id, status_code); -#else - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.0", - scope_id, status_code); - if (*size == 0) - { -#ifdef DEBUG - printf("Retrying with HTTP/1.1\n"); -#endif - free(respbuffer); - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", - scope_id, status_code); - } -#endif - return respbuffer; -} - - - - /* parseURL() * arguments : * url : source string not modified @@ -639,7 +603,7 @@ miniwget(const char * url, int * size, printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", hostname, port, path, scope_id); #endif - return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code); + return miniwget3(hostname, port, path, size, 0, 0, "1.1", scope_id, status_code); } void * @@ -660,5 +624,5 @@ miniwget_getaddr(const char * url, int * size, printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", hostname, port, path, scope_id); #endif - return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code); + return miniwget3(hostname, port, path, size, addr, addrlen, "1.1", scope_id, status_code); } diff --git a/thirdparty/miniupnpc/src/win32_snprintf.h b/thirdparty/miniupnpc/src/win32_snprintf.h index 1fc284ecff..5064df63bc 100644 --- a/thirdparty/miniupnpc/src/win32_snprintf.h +++ b/thirdparty/miniupnpc/src/win32_snprintf.h @@ -23,9 +23,9 @@ (defined(_MSC_VER) && _MSC_VER < 1900) /* Visual Studio older than 2015 */ || \ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__NO_ISOCEXT)) /* mingw32 without iso c ext */ || \ (defined(__MINGW64_VERSION_MAJOR) && /* mingw-w64 not ... */ !( \ - (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0)) /* ... with ansi stdio */ || \ + (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0) /* ... with ansi stdio */ || \ (__MINGW64_VERSION_MAJOR >= 6 && defined(_UCRT)) /* ... at least 6.0.0 with ucrt */ || \ - (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT)) /* ... at least 8.0.0 with iso c ext */ || \ + (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT))) /* ... at least 8.0.0 with iso c ext */ || \ 0) || \ 0) diff --git a/thirdparty/misc/bcdec.h b/thirdparty/misc/bcdec.h new file mode 100644 index 0000000000..275ee05d94 --- /dev/null +++ b/thirdparty/misc/bcdec.h @@ -0,0 +1,1345 @@ +/* bcdec.h - v0.97 + provides functions to decompress blocks of BC compressed images + written by Sergii "iOrange" Kudlai in 2022 + + This library does not allocate memory and is trying to use as less stack as possible + + The library was never optimized specifically for speed but for the overall size + it has zero external dependencies and is not using any runtime functions + + Supported BC formats: + BC1 (also known as DXT1) + it's "binary alpha" variant BC1A (DXT1A) + BC2 (also known as DXT3) + BC3 (also known as DXT5) + BC4 (also known as ATI1N) + BC5 (also known as ATI2N) + BC6H (HDR format) + BC7 + + BC1/BC2/BC3/BC7 are expected to decompress into 4*4 RGBA blocks 8bit per component (32bit pixel) + BC4/BC5 are expected to decompress into 4*4 R/RG blocks 8bit per component (8bit and 16bit pixel) + BC6H is expected to decompress into 4*4 RGB blocks of either 32bit float or 16bit "half" per + component (96bit or 48bit pixel) + + For more info, issues and suggestions please visit https://github.com/iOrange/bcdec + + CREDITS: + Aras Pranckevicius (@aras-p) - BC1/BC3 decoders optimizations (up to 3x the speed) + - BC6H/BC7 bits pulling routines optimizations + - optimized BC6H by moving unquantize out of the loop + - Split BC6H decompression function into 'half' and + 'float' variants + + Michael Schmidt (@RunDevelopment) - Found better "magic" coefficients for integer interpolation + of reference colors in BC1 color block, that match with + the floating point interpolation. This also made it faster + than integer division by 3! + + bugfixes: + @linkmauve + + LICENSE: See end of file for license information. +*/ + +#ifndef BCDEC_HEADER_INCLUDED +#define BCDEC_HEADER_INCLUDED + +#define BCDEC_VERSION_MAJOR 0 +#define BCDEC_VERSION_MINOR 97 + +/* if BCDEC_STATIC causes problems, try defining BCDECDEF to 'inline' or 'static inline' */ +#ifndef BCDECDEF +#ifdef BCDEC_STATIC +#define BCDECDEF static +#else +#ifdef __cplusplus +#define BCDECDEF extern "C" +#else +#define BCDECDEF extern +#endif +#endif +#endif + +/* Used information sources: + https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression + https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc6h-format + https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format + https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format-mode-reference + + ! WARNING ! Khronos's BPTC partitions tables contain mistakes, do not use them! + https://www.khronos.org/registry/DataFormat/specs/1.1/dataformat.1.1.html#BPTC + + ! Use tables from here instead ! + https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt + + Leaving it here as it's a nice read + https://fgiesen.wordpress.com/2021/10/04/gpu-bcn-decoding/ + + Fast half to float function from here + https://gist.github.com/rygorous/2144712 +*/ + +#define BCDEC_BC1_BLOCK_SIZE 8 +#define BCDEC_BC2_BLOCK_SIZE 16 +#define BCDEC_BC3_BLOCK_SIZE 16 +#define BCDEC_BC4_BLOCK_SIZE 8 +#define BCDEC_BC5_BLOCK_SIZE 16 +#define BCDEC_BC6H_BLOCK_SIZE 16 +#define BCDEC_BC7_BLOCK_SIZE 16 + +#define BCDEC_BC1_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*BCDEC_BC1_BLOCK_SIZE) +#define BCDEC_BC2_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*BCDEC_BC2_BLOCK_SIZE) +#define BCDEC_BC3_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*BCDEC_BC3_BLOCK_SIZE) +#define BCDEC_BC4_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*BCDEC_BC4_BLOCK_SIZE) +#define BCDEC_BC5_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*BCDEC_BC5_BLOCK_SIZE) +#define BCDEC_BC6H_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*BCDEC_BC6H_BLOCK_SIZE) +#define BCDEC_BC7_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*BCDEC_BC7_BLOCK_SIZE) + +BCDECDEF void bcdec_bc1(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +BCDECDEF void bcdec_bc2(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +BCDECDEF void bcdec_bc6h_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); +BCDECDEF void bcdec_bc6h_half(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); +BCDECDEF void bcdec_bc7(const void* compressedBlock, void* decompressedBlock, int destinationPitch); + +#endif /* BCDEC_HEADER_INCLUDED */ + +#ifdef BCDEC_IMPLEMENTATION + +static void bcdec__color_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int onlyOpaqueMode) { + unsigned short c0, c1; + unsigned int refColors[4]; /* 0xAABBGGRR */ + unsigned char* dstColors; + unsigned int colorIndices; + int i, j, idx; + unsigned int r0, g0, b0, r1, g1, b1, r, g, b; + + c0 = ((unsigned short*)compressedBlock)[0]; + c1 = ((unsigned short*)compressedBlock)[1]; + + /* Unpack 565 ref colors */ + r0 = (c0 >> 11) & 0x1F; + g0 = (c0 >> 5) & 0x3F; + b0 = c0 & 0x1F; + + r1 = (c1 >> 11) & 0x1F; + g1 = (c1 >> 5) & 0x3F; + b1 = c1 & 0x1F; + + /* Expand 565 ref colors to 888 */ + r = (r0 * 527 + 23) >> 6; + g = (g0 * 259 + 33) >> 6; + b = (b0 * 527 + 23) >> 6; + refColors[0] = 0xFF000000 | (b << 16) | (g << 8) | r; + + r = (r1 * 527 + 23) >> 6; + g = (g1 * 259 + 33) >> 6; + b = (b1 * 527 + 23) >> 6; + refColors[1] = 0xFF000000 | (b << 16) | (g << 8) | r; + + if (c0 > c1 || onlyOpaqueMode) { /* Standard BC1 mode (also BC3 color block uses ONLY this mode) */ + /* color_2 = 2/3*color_0 + 1/3*color_1 + color_3 = 1/3*color_0 + 2/3*color_1 */ + r = ((2 * r0 + r1) * 351 + 61) >> 7; + g = ((2 * g0 + g1) * 2763 + 1039) >> 11; + b = ((2 * b0 + b1) * 351 + 61) >> 7; + refColors[2] = 0xFF000000 | (b << 16) | (g << 8) | r; + + r = ((r0 + r1 * 2) * 351 + 61) >> 7; + g = ((g0 + g1 * 2) * 2763 + 1039) >> 11; + b = ((b0 + b1 * 2) * 351 + 61) >> 7; + refColors[3] = 0xFF000000 | (b << 16) | (g << 8) | r; + } else { /* Quite rare BC1A mode */ + /* color_2 = 1/2*color_0 + 1/2*color_1; + color_3 = 0; */ + r = ((r0 + r1) * 1053 + 125) >> 8; + g = ((g0 + g1) * 4145 + 1019) >> 11; + b = ((b0 + b1) * 1053 + 125) >> 8; + refColors[2] = 0xFF000000 | (b << 16) | (g << 8) | r; + + refColors[3] = 0x00000000; + } + + colorIndices = ((unsigned int*)compressedBlock)[1]; + + /* Fill out the decompressed color block */ + dstColors = (unsigned char*)decompressedBlock; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + idx = colorIndices & 0x03; + ((unsigned int*)dstColors)[j] = refColors[idx]; + colorIndices >>= 2; + } + + dstColors += destinationPitch; + } +} + +static void bcdec__sharp_alpha_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + unsigned short* alpha; + unsigned char* decompressed; + int i, j; + + alpha = (unsigned short*)compressedBlock; + decompressed = (unsigned char*)decompressedBlock; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + decompressed[j * 4] = ((alpha[i] >> (4 * j)) & 0x0F) * 17; + } + + decompressed += destinationPitch; + } +} + +static void bcdec__smooth_alpha_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int pixelSize) { + unsigned char* decompressed; + unsigned char alpha[8]; + int i, j; + unsigned long long block, indices; + + block = *(unsigned long long*)compressedBlock; + decompressed = (unsigned char*)decompressedBlock; + + alpha[0] = block & 0xFF; + alpha[1] = (block >> 8) & 0xFF; + + if (alpha[0] > alpha[1]) { + /* 6 interpolated alpha values. */ + alpha[2] = (6 * alpha[0] + alpha[1] + 1) / 7; /* 6/7*alpha_0 + 1/7*alpha_1 */ + alpha[3] = (5 * alpha[0] + 2 * alpha[1] + 1) / 7; /* 5/7*alpha_0 + 2/7*alpha_1 */ + alpha[4] = (4 * alpha[0] + 3 * alpha[1] + 1) / 7; /* 4/7*alpha_0 + 3/7*alpha_1 */ + alpha[5] = (3 * alpha[0] + 4 * alpha[1] + 1) / 7; /* 3/7*alpha_0 + 4/7*alpha_1 */ + alpha[6] = (2 * alpha[0] + 5 * alpha[1] + 1) / 7; /* 2/7*alpha_0 + 5/7*alpha_1 */ + alpha[7] = ( alpha[0] + 6 * alpha[1] + 1) / 7; /* 1/7*alpha_0 + 6/7*alpha_1 */ + } + else { + /* 4 interpolated alpha values. */ + alpha[2] = (4 * alpha[0] + alpha[1] + 1) / 5; /* 4/5*alpha_0 + 1/5*alpha_1 */ + alpha[3] = (3 * alpha[0] + 2 * alpha[1] + 1) / 5; /* 3/5*alpha_0 + 2/5*alpha_1 */ + alpha[4] = (2 * alpha[0] + 3 * alpha[1] + 1) / 5; /* 2/5*alpha_0 + 3/5*alpha_1 */ + alpha[5] = ( alpha[0] + 4 * alpha[1] + 1) / 5; /* 1/5*alpha_0 + 4/5*alpha_1 */ + alpha[6] = 0x00; + alpha[7] = 0xFF; + } + + indices = block >> 16; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + decompressed[j * pixelSize] = alpha[indices & 0x07]; + indices >>= 3; + } + + decompressed += destinationPitch; + } +} + +typedef struct bcdec__bitstream { + unsigned long long low; + unsigned long long high; +} bcdec__bitstream_t; + +static int bcdec__bitstream_read_bits(bcdec__bitstream_t* bstream, int numBits) { + unsigned int mask = (1 << numBits) - 1; + /* Read the low N bits */ + unsigned int bits = (bstream->low & mask); + + bstream->low >>= numBits; + /* Put the low N bits of "high" into the high 64-N bits of "low". */ + bstream->low |= (bstream->high & mask) << (sizeof(bstream->high) * 8 - numBits); + bstream->high >>= numBits; + + return bits; +} + +static int bcdec__bitstream_read_bit(bcdec__bitstream_t* bstream) { + return bcdec__bitstream_read_bits(bstream, 1); +} + +/* reversed bits pulling, used in BC6H decoding + why ?? just why ??? */ +static int bcdec__bitstream_read_bits_r(bcdec__bitstream_t* bstream, int numBits) { + int bits = bcdec__bitstream_read_bits(bstream, numBits); + /* Reverse the bits. */ + int result = 0; + while (numBits--) { + result <<= 1; + result |= (bits & 1); + bits >>= 1; + } + return result; +} + + + +BCDECDEF void bcdec_bc1(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + bcdec__color_block(compressedBlock, decompressedBlock, destinationPitch, 0); +} + +BCDECDEF void bcdec_bc2(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + bcdec__color_block(((char*)compressedBlock) + 8, decompressedBlock, destinationPitch, 1); + bcdec__sharp_alpha_block(compressedBlock, ((char*)decompressedBlock) + 3, destinationPitch); +} + +BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + bcdec__color_block(((char*)compressedBlock) + 8, decompressedBlock, destinationPitch, 1); + bcdec__smooth_alpha_block(compressedBlock, ((char*)decompressedBlock) + 3, destinationPitch, 4); +} + +BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + bcdec__smooth_alpha_block(compressedBlock, decompressedBlock, destinationPitch, 1); +} + +BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + bcdec__smooth_alpha_block(compressedBlock, decompressedBlock, destinationPitch, 2); + bcdec__smooth_alpha_block(((char*)compressedBlock) + 8, ((char*)decompressedBlock) + 1, destinationPitch, 2); +} + +/* http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend */ +static int bcdec__extend_sign(int val, int bits) { + return (val << (32 - bits)) >> (32 - bits); +} + +static int bcdec__transform_inverse(int val, int a0, int bits, int isSigned) { + /* If the precision of A0 is "p" bits, then the transform algorithm is: + B0 = (B0 + A0) & ((1 << p) - 1) */ + val = (val + a0) & ((1 << bits) - 1); + if (isSigned) { + val = bcdec__extend_sign(val, bits); + } + return val; +} + +/* pretty much copy-paste from documentation */ +static int bcdec__unquantize(int val, int bits, int isSigned) { + int unq, s = 0; + + if (!isSigned) { + if (bits >= 15) { + unq = val; + } else if (!val) { + unq = 0; + } else if (val == ((1 << bits) - 1)) { + unq = 0xFFFF; + } else { + unq = ((val << 16) + 0x8000) >> bits; + } + } else { + if (bits >= 16) { + unq = val; + } else { + if (val < 0) { + s = 1; + val = -val; + } + + if (val == 0) { + unq = 0; + } else if (val >= ((1 << (bits - 1)) - 1)) { + unq = 0x7FFF; + } else { + unq = ((val << 15) + 0x4000) >> (bits - 1); + } + + if (s) { + unq = -unq; + } + } + } + return unq; +} + +static int bcdec__interpolate(int a, int b, int* weights, int index) { + return (a * (64 - weights[index]) + b * weights[index] + 32) >> 6; +} + +static unsigned short bcdec__finish_unquantize(int val, int isSigned) { + int s; + + if (!isSigned) { + return (unsigned short)((val * 31) >> 6); /* scale the magnitude by 31 / 64 */ + } else { + val = (val < 0) ? -(((-val) * 31) >> 5) : (val * 31) >> 5; /* scale the magnitude by 31 / 32 */ + s = 0; + if (val < 0) { + s = 0x8000; + val = -val; + } + return (unsigned short)(s | val); + } +} + +/* modified half_to_float_fast4 from https://gist.github.com/rygorous/2144712 */ +static float bcdec__half_to_float_quick(unsigned short half) { + typedef union { + unsigned int u; + float f; + } FP32; + + static const FP32 magic = { 113 << 23 }; + static const unsigned int shifted_exp = 0x7c00 << 13; /* exponent mask after shift */ + FP32 o; + unsigned int exp; + + o.u = (half & 0x7fff) << 13; /* exponent/mantissa bits */ + exp = shifted_exp & o.u; /* just the exponent */ + o.u += (127 - 15) << 23; /* exponent adjust */ + + /* handle exponent special cases */ + if (exp == shifted_exp) { /* Inf/NaN? */ + o.u += (128 - 16) << 23; /* extra exp adjust */ + } else if (exp == 0) { /* Zero/Denormal? */ + o.u += 1 << 23; /* extra exp adjust */ + o.f -= magic.f; /* renormalize */ + } + + o.u |= (half & 0x8000) << 16; /* sign bit */ + return o.f; +} + +BCDECDEF void bcdec_bc6h_half(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned) { + static char actual_bits_count[4][14] = { + { 10, 7, 11, 11, 11, 9, 8, 8, 8, 6, 10, 11, 12, 16 }, /* W */ + { 5, 6, 5, 4, 4, 5, 6, 5, 5, 6, 10, 9, 8, 4 }, /* dR */ + { 5, 6, 4, 5, 4, 5, 5, 6, 5, 6, 10, 9, 8, 4 }, /* dG */ + { 5, 6, 4, 4, 5, 5, 5, 5, 6, 6, 10, 9, 8, 4 } /* dB */ + }; + + /* There are 32 possible partition sets for a two-region tile. + Each 4x4 block represents a single shape. + Here also every fix-up index has MSB bit set. */ + static unsigned char partition_sets[32][4][4] = { + { {128, 0, 1, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 0, 1, 129} }, /* 0 */ + { {128, 0, 0, 1}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 0, 129} }, /* 1 */ + { {128, 1, 1, 1}, {0, 1, 1, 1}, { 0, 1, 1, 1}, {0, 1, 1, 129} }, /* 2 */ + { {128, 0, 0, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 1, 1, 129} }, /* 3 */ + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 1, 129} }, /* 4 */ + { {128, 0, 1, 1}, {0, 1, 1, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, /* 5 */ + { {128, 0, 0, 1}, {0, 0, 1, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, /* 6 */ + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 0, 1, 1}, {0, 1, 1, 129} }, /* 7 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 1}, {0, 0, 1, 129} }, /* 8 */ + { {128, 0, 1, 1}, {0, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 9 */ + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, /* 10 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 1}, {0, 1, 1, 129} }, /* 11 */ + { {128, 0, 0, 1}, {0, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 12 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 13 */ + { {128, 0, 0, 0}, {1, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 14 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 0}, {1, 1, 1, 129} }, /* 15 */ + { {128, 0, 0, 0}, {1, 0, 0, 0}, { 1, 1, 1, 0}, {1, 1, 1, 129} }, /* 16 */ + { {128, 1, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 0}, {0, 0, 0, 0} }, /* 17 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 1, 0} }, /* 18 */ + { {128, 1, 129, 1}, {0, 0, 1, 1}, { 0, 0, 0, 1}, {0, 0, 0, 0} }, /* 19 */ + { {128, 0, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 0}, {0, 0, 0, 0} }, /* 20 */ + { {128, 0, 0, 0}, {1, 0, 0, 0}, {129, 1, 0, 0}, {1, 1, 1, 0} }, /* 21 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 0, 0} }, /* 22 */ + { {128, 1, 1, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 0, 0, 129} }, /* 23 */ + { {128, 0, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 0, 0} }, /* 24 */ + { {128, 0, 0, 0}, {1, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 0, 0} }, /* 25 */ + { {128, 1, 129, 0}, {0, 1, 1, 0}, { 0, 1, 1, 0}, {0, 1, 1, 0} }, /* 26 */ + { {128, 0, 129, 1}, {0, 1, 1, 0}, { 0, 1, 1, 0}, {1, 1, 0, 0} }, /* 27 */ + { {128, 0, 0, 1}, {0, 1, 1, 1}, {129, 1, 1, 0}, {1, 0, 0, 0} }, /* 28 */ + { {128, 0, 0, 0}, {1, 1, 1, 1}, {129, 1, 1, 1}, {0, 0, 0, 0} }, /* 29 */ + { {128, 1, 129, 1}, {0, 0, 0, 1}, { 1, 0, 0, 0}, {1, 1, 1, 0} }, /* 30 */ + { {128, 0, 129, 1}, {1, 0, 0, 1}, { 1, 0, 0, 1}, {1, 1, 0, 0} } /* 31 */ + }; + + static int aWeight3[8] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + static int aWeight4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; + + bcdec__bitstream_t bstream; + int mode, partition, numPartitions, i, j, partitionSet, indexBits, index, ep_i, actualBits0Mode; + int r[4], g[4], b[4]; /* wxyz */ + unsigned short* decompressed; + int* weights; + + decompressed = (unsigned short*)decompressedBlock; + + bstream.low = ((unsigned long long*)compressedBlock)[0]; + bstream.high = ((unsigned long long*)compressedBlock)[1]; + + r[0] = r[1] = r[2] = r[3] = 0; + g[0] = g[1] = g[2] = g[3] = 0; + b[0] = b[1] = b[2] = b[3] = 0; + + mode = bcdec__bitstream_read_bits(&bstream, 2); + if (mode > 1) { + mode |= (bcdec__bitstream_read_bits(&bstream, 3) << 2); + } + + /* modes >= 11 (10 in my code) are using 0 one, others will read it from the bitstream */ + partition = 0; + + switch (mode) { + /* mode 1 */ + case 0b00: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 75 bits (10.555, 10.555, 10.555) */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* rx[4:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* gx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* bx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 5); /* ry[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 5); /* rz[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 0; + } break; + + /* mode 2 */ + case 0b01: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 75 bits (7666, 7666, 7666) */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 5; /* gy[5] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 5; /* gz[5] */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 7); /* rw[6:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 7); /* gw[6:0] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 5; /* by[5] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 7); /* bw[6:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 5; /* bz[5] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* rx[5:0] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* gx[5:0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* bx[5:0] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 6); /* ry[5:0] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 6); /* rz[5:0] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 1; + } break; + + /* mode 3 */ + case 0b00010: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (11.555, 11.444, 11.444) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* rx[4:0] */ + r[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* rw[10] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* gx[3:0] */ + g[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* gw[10] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* bx[3:0] */ + b[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* bw[10] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 5); /* ry[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 5); /* rz[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 2; + } break; + + /* mode 4 */ + case 0b00110: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (11.444, 11.555, 11.444) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* rx[3:0] */ + r[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* rw[10] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* gx[4:0] */ + g[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* gw[10] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* bx[3:0] */ + b[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* bw[10] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* ry[3:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* rz[3:0] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 3; + } break; + + /* mode 5 */ + case 0b01010: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (11.444, 11.444, 11.555) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* rx[3:0] */ + r[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* rw[10] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* gx[3:0] */ + g[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* gw[10] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* bx[4:0] */ + b[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* bw[10] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* ry[3:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* rz[3:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 4; + } break; + + /* mode 6 */ + case 0b01110: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (9555, 9555, 9555) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 9); /* rw[8:0] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 9); /* gw[8:0] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 9); /* bw[8:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* rx[4:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* gx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gx[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* bx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 5); /* ry[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 5); /* rz[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 5; + } break; + + /* mode 7 */ + case 0b10010: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (8666, 8555, 8555) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* rw[7:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* gw[7:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* bw[7:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* rx[5:0] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* gx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* bx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 6); /* ry[5:0] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 6); /* rz[5:0] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 6; + } break; + + /* mode 8 */ + case 0b10110: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (8555, 8666, 8555) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* rw[7:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* gw[7:0] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 5; /* gy[5] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* bw[7:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 5; /* gz[5] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* rx[4:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* gx[5:0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* zx[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* bx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 5); /* ry[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 5); /* rz[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 7; + } break; + + /* mode 9 */ + case 0b11010: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (8555, 8555, 8666) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* rw[7:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* gw[7:0] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 5; /* by[5] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 8); /* bw[7:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 5; /* bz[5] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* bw[4:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 5); /* gx[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* bx[5:0] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 5); /* ry[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 5); /* rz[4:0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 8; + } break; + + /* mode 10 */ + case 0b11110: { + /* Partitition indices: 46 bits + Partition: 5 bits + Color Endpoints: 72 bits (6666, 6666, 6666) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 6); /* rw[5:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gz[4] */ + b[3] |= bcdec__bitstream_read_bit(&bstream); /* bz[0] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 1; /* bz[1] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* by[4] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 6); /* gw[5:0] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 5; /* gy[5] */ + b[2] |= bcdec__bitstream_read_bit(&bstream) << 5; /* by[5] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 2; /* bz[2] */ + g[2] |= bcdec__bitstream_read_bit(&bstream) << 4; /* gy[4] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 6); /* bw[5:0] */ + g[3] |= bcdec__bitstream_read_bit(&bstream) << 5; /* gz[5] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 3; /* bz[3] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 5; /* bz[5] */ + b[3] |= bcdec__bitstream_read_bit(&bstream) << 4; /* bz[4] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* rx[5:0] */ + g[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* gy[3:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* gx[5:0] */ + g[3] |= bcdec__bitstream_read_bits(&bstream, 4); /* gz[3:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 6); /* bx[5:0] */ + b[2] |= bcdec__bitstream_read_bits(&bstream, 4); /* by[3:0] */ + r[2] |= bcdec__bitstream_read_bits(&bstream, 6); /* ry[5:0] */ + r[3] |= bcdec__bitstream_read_bits(&bstream, 6); /* rz[5:0] */ + partition = bcdec__bitstream_read_bits(&bstream, 5); /* d[4:0] */ + mode = 9; + } break; + + /* mode 11 */ + case 0b00011: { + /* Partitition indices: 63 bits + Partition: 0 bits + Color Endpoints: 60 bits (10.10, 10.10, 10.10) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 10); /* rx[9:0] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 10); /* gx[9:0] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 10); /* bx[9:0] */ + mode = 10; + } break; + + /* mode 12 */ + case 0b00111: { + /* Partitition indices: 63 bits + Partition: 0 bits + Color Endpoints: 60 bits (11.9, 11.9, 11.9) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 9); /* rx[8:0] */ + r[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* rw[10] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 9); /* gx[8:0] */ + g[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* gw[10] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 9); /* bx[8:0] */ + b[0] |= bcdec__bitstream_read_bit(&bstream) << 10; /* bw[10] */ + mode = 11; + } break; + + /* mode 13 */ + case 0b01011: { + /* Partitition indices: 63 bits + Partition: 0 bits + Color Endpoints: 60 bits (12.8, 12.8, 12.8) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 8); /* rx[7:0] */ + r[0] |= bcdec__bitstream_read_bits_r(&bstream, 2) << 10;/* rx[10:11] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 8); /* gx[7:0] */ + g[0] |= bcdec__bitstream_read_bits_r(&bstream, 2) << 10;/* gx[10:11] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 8); /* bx[7:0] */ + b[0] |= bcdec__bitstream_read_bits_r(&bstream, 2) << 10;/* bx[10:11] */ + mode = 12; + } break; + + /* mode 14 */ + case 0b01111: { + /* Partitition indices: 63 bits + Partition: 0 bits + Color Endpoints: 60 bits (16.4, 16.4, 16.4) */ + r[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* rw[9:0] */ + g[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* gw[9:0] */ + b[0] |= bcdec__bitstream_read_bits(&bstream, 10); /* bw[9:0] */ + r[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* rx[3:0] */ + r[0] |= bcdec__bitstream_read_bits_r(&bstream, 6) << 10;/* rw[10:15] */ + g[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* gx[3:0] */ + g[0] |= bcdec__bitstream_read_bits_r(&bstream, 6) << 10;/* gw[10:15] */ + b[1] |= bcdec__bitstream_read_bits(&bstream, 4); /* bx[3:0] */ + b[0] |= bcdec__bitstream_read_bits_r(&bstream, 6) << 10;/* bw[10:15] */ + mode = 13; + } break; + + default: { + /* Modes 10011, 10111, 11011, and 11111 (not shown) are reserved. + Do not use these in your encoder. If the hardware is passed blocks + with one of these modes specified, the resulting decompressed block + must contain all zeroes in all channels except for the alpha channel. */ + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + decompressed[j * 3 + 0] = 0; + decompressed[j * 3 + 1] = 0; + decompressed[j * 3 + 2] = 0; + } + decompressed += destinationPitch; + } + + return; + } + } + + numPartitions = (mode >= 10) ? 0 : 1; + + actualBits0Mode = actual_bits_count[0][mode]; + if (isSigned) { + r[0] = bcdec__extend_sign(r[0], actualBits0Mode); + g[0] = bcdec__extend_sign(g[0], actualBits0Mode); + b[0] = bcdec__extend_sign(b[0], actualBits0Mode); + } + + /* Mode 11 (like Mode 10) does not use delta compression, + and instead stores both color endpoints explicitly. */ + if ((mode != 9 && mode != 10) || isSigned) { + for (i = 1; i < (numPartitions + 1) * 2; ++i) { + r[i] = bcdec__extend_sign(r[i], actual_bits_count[1][mode]); + g[i] = bcdec__extend_sign(g[i], actual_bits_count[2][mode]); + b[i] = bcdec__extend_sign(b[i], actual_bits_count[3][mode]); + } + } + + if (mode != 9 && mode != 10) { + for (i = 1; i < (numPartitions + 1) * 2; ++i) { + r[i] = bcdec__transform_inverse(r[i], r[0], actualBits0Mode, isSigned); + g[i] = bcdec__transform_inverse(g[i], g[0], actualBits0Mode, isSigned); + b[i] = bcdec__transform_inverse(b[i], b[0], actualBits0Mode, isSigned); + } + } + + for (i = 0; i < (numPartitions + 1) * 2; ++i) { + r[i] = bcdec__unquantize(r[i], actualBits0Mode, isSigned); + g[i] = bcdec__unquantize(g[i], actualBits0Mode, isSigned); + b[i] = bcdec__unquantize(b[i], actualBits0Mode, isSigned); + } + + weights = (mode >= 10) ? aWeight4 : aWeight3; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + partitionSet = (mode >= 10) ? ((i|j) ? 0 : 128) : partition_sets[partition][i][j]; + + indexBits = (mode >= 10) ? 4 : 3; + /* fix-up index is specified with one less bit */ + /* The fix-up index for subset 0 is always index 0 */ + if (partitionSet & 0x80) { + indexBits--; + } + partitionSet &= 0x01; + + index = bcdec__bitstream_read_bits(&bstream, indexBits); + + ep_i = partitionSet * 2; + decompressed[j * 3 + 0] = bcdec__finish_unquantize( + bcdec__interpolate(r[ep_i], r[ep_i+1], weights, index), isSigned); + decompressed[j * 3 + 1] = bcdec__finish_unquantize( + bcdec__interpolate(g[ep_i], g[ep_i+1], weights, index), isSigned); + decompressed[j * 3 + 2] = bcdec__finish_unquantize( + bcdec__interpolate(b[ep_i], b[ep_i+1], weights, index), isSigned); + } + + decompressed += destinationPitch; + } +} + +BCDECDEF void bcdec_bc6h_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned) { + unsigned short block[16*3]; + float* decompressed; + const unsigned short* b; + int i, j; + + bcdec_bc6h_half(compressedBlock, block, 4*3, isSigned); + b = block; + decompressed = (float*)decompressedBlock; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + decompressed[j * 3 + 0] = bcdec__half_to_float_quick(*b++); + decompressed[j * 3 + 1] = bcdec__half_to_float_quick(*b++); + decompressed[j * 3 + 2] = bcdec__half_to_float_quick(*b++); + } + decompressed += destinationPitch; + } +} + +static void bcdec__swap_values(int* a, int* b) { + a[0] ^= b[0], b[0] ^= a[0], a[0] ^= b[0]; +} + +BCDECDEF void bcdec_bc7(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { + static char actual_bits_count[2][8] = { + { 4, 6, 5, 7, 5, 7, 7, 5 }, /* RGBA */ + { 0, 0, 0, 0, 6, 8, 7, 5 }, /* Alpha */ + }; + + /* There are 64 possible partition sets for a two-region tile. + Each 4x4 block represents a single shape. + Here also every fix-up index has MSB bit set. */ + static unsigned char partition_sets[2][64][4][4] = { + { /* Partition table for 2-subset BPTC */ + { {128, 0, 1, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 0, 1, 129} }, /* 0 */ + { {128, 0, 0, 1}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 0, 129} }, /* 1 */ + { {128, 1, 1, 1}, {0, 1, 1, 1}, { 0, 1, 1, 1}, {0, 1, 1, 129} }, /* 2 */ + { {128, 0, 0, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 1, 1, 129} }, /* 3 */ + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 1, 129} }, /* 4 */ + { {128, 0, 1, 1}, {0, 1, 1, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, /* 5 */ + { {128, 0, 0, 1}, {0, 0, 1, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, /* 6 */ + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 0, 1, 1}, {0, 1, 1, 129} }, /* 7 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 1}, {0, 0, 1, 129} }, /* 8 */ + { {128, 0, 1, 1}, {0, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 9 */ + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, /* 10 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 1}, {0, 1, 1, 129} }, /* 11 */ + { {128, 0, 0, 1}, {0, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 12 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 13 */ + { {128, 0, 0, 0}, {1, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, /* 14 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 0}, {1, 1, 1, 129} }, /* 15 */ + { {128, 0, 0, 0}, {1, 0, 0, 0}, { 1, 1, 1, 0}, {1, 1, 1, 129} }, /* 16 */ + { {128, 1, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 0}, {0, 0, 0, 0} }, /* 17 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 1, 0} }, /* 18 */ + { {128, 1, 129, 1}, {0, 0, 1, 1}, { 0, 0, 0, 1}, {0, 0, 0, 0} }, /* 19 */ + { {128, 0, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 0}, {0, 0, 0, 0} }, /* 20 */ + { {128, 0, 0, 0}, {1, 0, 0, 0}, {129, 1, 0, 0}, {1, 1, 1, 0} }, /* 21 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 0, 0} }, /* 22 */ + { {128, 1, 1, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 0, 0, 129} }, /* 23 */ + { {128, 0, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 0, 0} }, /* 24 */ + { {128, 0, 0, 0}, {1, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 0, 0} }, /* 25 */ + { {128, 1, 129, 0}, {0, 1, 1, 0}, { 0, 1, 1, 0}, {0, 1, 1, 0} }, /* 26 */ + { {128, 0, 129, 1}, {0, 1, 1, 0}, { 0, 1, 1, 0}, {1, 1, 0, 0} }, /* 27 */ + { {128, 0, 0, 1}, {0, 1, 1, 1}, {129, 1, 1, 0}, {1, 0, 0, 0} }, /* 28 */ + { {128, 0, 0, 0}, {1, 1, 1, 1}, {129, 1, 1, 1}, {0, 0, 0, 0} }, /* 29 */ + { {128, 1, 129, 1}, {0, 0, 0, 1}, { 1, 0, 0, 0}, {1, 1, 1, 0} }, /* 30 */ + { {128, 0, 129, 1}, {1, 0, 0, 1}, { 1, 0, 0, 1}, {1, 1, 0, 0} }, /* 31 */ + { {128, 1, 0, 1}, {0, 1, 0, 1}, { 0, 1, 0, 1}, {0, 1, 0, 129} }, /* 32 */ + { {128, 0, 0, 0}, {1, 1, 1, 1}, { 0, 0, 0, 0}, {1, 1, 1, 129} }, /* 33 */ + { {128, 1, 0, 1}, {1, 0, 129, 0}, { 0, 1, 0, 1}, {1, 0, 1, 0} }, /* 34 */ + { {128, 0, 1, 1}, {0, 0, 1, 1}, {129, 1, 0, 0}, {1, 1, 0, 0} }, /* 35 */ + { {128, 0, 129, 1}, {1, 1, 0, 0}, { 0, 0, 1, 1}, {1, 1, 0, 0} }, /* 36 */ + { {128, 1, 0, 1}, {0, 1, 0, 1}, {129, 0, 1, 0}, {1, 0, 1, 0} }, /* 37 */ + { {128, 1, 1, 0}, {1, 0, 0, 1}, { 0, 1, 1, 0}, {1, 0, 0, 129} }, /* 38 */ + { {128, 1, 0, 1}, {1, 0, 1, 0}, { 1, 0, 1, 0}, {0, 1, 0, 129} }, /* 39 */ + { {128, 1, 129, 1}, {0, 0, 1, 1}, { 1, 1, 0, 0}, {1, 1, 1, 0} }, /* 40 */ + { {128, 0, 0, 1}, {0, 0, 1, 1}, {129, 1, 0, 0}, {1, 0, 0, 0} }, /* 41 */ + { {128, 0, 129, 1}, {0, 0, 1, 0}, { 0, 1, 0, 0}, {1, 1, 0, 0} }, /* 42 */ + { {128, 0, 129, 1}, {1, 0, 1, 1}, { 1, 1, 0, 1}, {1, 1, 0, 0} }, /* 43 */ + { {128, 1, 129, 0}, {1, 0, 0, 1}, { 1, 0, 0, 1}, {0, 1, 1, 0} }, /* 44 */ + { {128, 0, 1, 1}, {1, 1, 0, 0}, { 1, 1, 0, 0}, {0, 0, 1, 129} }, /* 45 */ + { {128, 1, 1, 0}, {0, 1, 1, 0}, { 1, 0, 0, 1}, {1, 0, 0, 129} }, /* 46 */ + { {128, 0, 0, 0}, {0, 1, 129, 0}, { 0, 1, 1, 0}, {0, 0, 0, 0} }, /* 47 */ + { {128, 1, 0, 0}, {1, 1, 129, 0}, { 0, 1, 0, 0}, {0, 0, 0, 0} }, /* 48 */ + { {128, 0, 129, 0}, {0, 1, 1, 1}, { 0, 0, 1, 0}, {0, 0, 0, 0} }, /* 49 */ + { {128, 0, 0, 0}, {0, 0, 129, 0}, { 0, 1, 1, 1}, {0, 0, 1, 0} }, /* 50 */ + { {128, 0, 0, 0}, {0, 1, 0, 0}, {129, 1, 1, 0}, {0, 1, 0, 0} }, /* 51 */ + { {128, 1, 1, 0}, {1, 1, 0, 0}, { 1, 0, 0, 1}, {0, 0, 1, 129} }, /* 52 */ + { {128, 0, 1, 1}, {0, 1, 1, 0}, { 1, 1, 0, 0}, {1, 0, 0, 129} }, /* 53 */ + { {128, 1, 129, 0}, {0, 0, 1, 1}, { 1, 0, 0, 1}, {1, 1, 0, 0} }, /* 54 */ + { {128, 0, 129, 1}, {1, 0, 0, 1}, { 1, 1, 0, 0}, {0, 1, 1, 0} }, /* 55 */ + { {128, 1, 1, 0}, {1, 1, 0, 0}, { 1, 1, 0, 0}, {1, 0, 0, 129} }, /* 56 */ + { {128, 1, 1, 0}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {1, 0, 0, 129} }, /* 57 */ + { {128, 1, 1, 1}, {1, 1, 1, 0}, { 1, 0, 0, 0}, {0, 0, 0, 129} }, /* 58 */ + { {128, 0, 0, 1}, {1, 0, 0, 0}, { 1, 1, 1, 0}, {0, 1, 1, 129} }, /* 59 */ + { {128, 0, 0, 0}, {1, 1, 1, 1}, { 0, 0, 1, 1}, {0, 0, 1, 129} }, /* 60 */ + { {128, 0, 129, 1}, {0, 0, 1, 1}, { 1, 1, 1, 1}, {0, 0, 0, 0} }, /* 61 */ + { {128, 0, 129, 0}, {0, 0, 1, 0}, { 1, 1, 1, 0}, {1, 1, 1, 0} }, /* 62 */ + { {128, 1, 0, 0}, {0, 1, 0, 0}, { 0, 1, 1, 1}, {0, 1, 1, 129} } /* 63 */ + }, + { /* Partition table for 3-subset BPTC */ + { {128, 0, 1, 129}, {0, 0, 1, 1}, { 0, 2, 2, 1}, { 2, 2, 2, 130} }, /* 0 */ + { {128, 0, 0, 129}, {0, 0, 1, 1}, {130, 2, 1, 1}, { 2, 2, 2, 1} }, /* 1 */ + { {128, 0, 0, 0}, {2, 0, 0, 1}, {130, 2, 1, 1}, { 2, 2, 1, 129} }, /* 2 */ + { {128, 2, 2, 130}, {0, 0, 2, 2}, { 0, 0, 1, 1}, { 0, 1, 1, 129} }, /* 3 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 1, 2, 2}, { 1, 1, 2, 130} }, /* 4 */ + { {128, 0, 1, 129}, {0, 0, 1, 1}, { 0, 0, 2, 2}, { 0, 0, 2, 130} }, /* 5 */ + { {128, 0, 2, 130}, {0, 0, 2, 2}, { 1, 1, 1, 1}, { 1, 1, 1, 129} }, /* 6 */ + { {128, 0, 1, 1}, {0, 0, 1, 1}, {130, 2, 1, 1}, { 2, 2, 1, 129} }, /* 7 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 1, 1, 1}, { 2, 2, 2, 130} }, /* 8 */ + { {128, 0, 0, 0}, {1, 1, 1, 1}, {129, 1, 1, 1}, { 2, 2, 2, 130} }, /* 9 */ + { {128, 0, 0, 0}, {1, 1, 129, 1}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, /* 10 */ + { {128, 0, 1, 2}, {0, 0, 129, 2}, { 0, 0, 1, 2}, { 0, 0, 1, 130} }, /* 11 */ + { {128, 1, 1, 2}, {0, 1, 129, 2}, { 0, 1, 1, 2}, { 0, 1, 1, 130} }, /* 12 */ + { {128, 1, 2, 2}, {0, 129, 2, 2}, { 0, 1, 2, 2}, { 0, 1, 2, 130} }, /* 13 */ + { {128, 0, 1, 129}, {0, 1, 1, 2}, { 1, 1, 2, 2}, { 1, 2, 2, 130} }, /* 14 */ + { {128, 0, 1, 129}, {2, 0, 0, 1}, {130, 2, 0, 0}, { 2, 2, 2, 0} }, /* 15 */ + { {128, 0, 0, 129}, {0, 0, 1, 1}, { 0, 1, 1, 2}, { 1, 1, 2, 130} }, /* 16 */ + { {128, 1, 1, 129}, {0, 0, 1, 1}, {130, 0, 0, 1}, { 2, 2, 0, 0} }, /* 17 */ + { {128, 0, 0, 0}, {1, 1, 2, 2}, {129, 1, 2, 2}, { 1, 1, 2, 130} }, /* 18 */ + { {128, 0, 2, 130}, {0, 0, 2, 2}, { 0, 0, 2, 2}, { 1, 1, 1, 129} }, /* 19 */ + { {128, 1, 1, 129}, {0, 1, 1, 1}, { 0, 2, 2, 2}, { 0, 2, 2, 130} }, /* 20 */ + { {128, 0, 0, 129}, {0, 0, 0, 1}, {130, 2, 2, 1}, { 2, 2, 2, 1} }, /* 21 */ + { {128, 0, 0, 0}, {0, 0, 129, 1}, { 0, 1, 2, 2}, { 0, 1, 2, 130} }, /* 22 */ + { {128, 0, 0, 0}, {1, 1, 0, 0}, {130, 2, 129, 0}, { 2, 2, 1, 0} }, /* 23 */ + { {128, 1, 2, 130}, {0, 129, 2, 2}, { 0, 0, 1, 1}, { 0, 0, 0, 0} }, /* 24 */ + { {128, 0, 1, 2}, {0, 0, 1, 2}, {129, 1, 2, 2}, { 2, 2, 2, 130} }, /* 25 */ + { {128, 1, 1, 0}, {1, 2, 130, 1}, {129, 2, 2, 1}, { 0, 1, 1, 0} }, /* 26 */ + { {128, 0, 0, 0}, {0, 1, 129, 0}, { 1, 2, 130, 1}, { 1, 2, 2, 1} }, /* 27 */ + { {128, 0, 2, 2}, {1, 1, 0, 2}, {129, 1, 0, 2}, { 0, 0, 2, 130} }, /* 28 */ + { {128, 1, 1, 0}, {0, 129, 1, 0}, { 2, 0, 0, 2}, { 2, 2, 2, 130} }, /* 29 */ + { {128, 0, 1, 1}, {0, 1, 2, 2}, { 0, 1, 130, 2}, { 0, 0, 1, 129} }, /* 30 */ + { {128, 0, 0, 0}, {2, 0, 0, 0}, {130, 2, 1, 1}, { 2, 2, 2, 129} }, /* 31 */ + { {128, 0, 0, 0}, {0, 0, 0, 2}, {129, 1, 2, 2}, { 1, 2, 2, 130} }, /* 32 */ + { {128, 2, 2, 130}, {0, 0, 2, 2}, { 0, 0, 1, 2}, { 0, 0, 1, 129} }, /* 33 */ + { {128, 0, 1, 129}, {0, 0, 1, 2}, { 0, 0, 2, 2}, { 0, 2, 2, 130} }, /* 34 */ + { {128, 1, 2, 0}, {0, 129, 2, 0}, { 0, 1, 130, 0}, { 0, 1, 2, 0} }, /* 35 */ + { {128, 0, 0, 0}, {1, 1, 129, 1}, { 2, 2, 130, 2}, { 0, 0, 0, 0} }, /* 36 */ + { {128, 1, 2, 0}, {1, 2, 0, 1}, {130, 0, 129, 2}, { 0, 1, 2, 0} }, /* 37 */ + { {128, 1, 2, 0}, {2, 0, 1, 2}, {129, 130, 0, 1}, { 0, 1, 2, 0} }, /* 38 */ + { {128, 0, 1, 1}, {2, 2, 0, 0}, { 1, 1, 130, 2}, { 0, 0, 1, 129} }, /* 39 */ + { {128, 0, 1, 1}, {1, 1, 130, 2}, { 2, 2, 0, 0}, { 0, 0, 1, 129} }, /* 40 */ + { {128, 1, 0, 129}, {0, 1, 0, 1}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, /* 41 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, {130, 1, 2, 1}, { 2, 1, 2, 129} }, /* 42 */ + { {128, 0, 2, 2}, {1, 129, 2, 2}, { 0, 0, 2, 2}, { 1, 1, 2, 130} }, /* 43 */ + { {128, 0, 2, 130}, {0, 0, 1, 1}, { 0, 0, 2, 2}, { 0, 0, 1, 129} }, /* 44 */ + { {128, 2, 2, 0}, {1, 2, 130, 1}, { 0, 2, 2, 0}, { 1, 2, 2, 129} }, /* 45 */ + { {128, 1, 0, 1}, {2, 2, 130, 2}, { 2, 2, 2, 2}, { 0, 1, 0, 129} }, /* 46 */ + { {128, 0, 0, 0}, {2, 1, 2, 1}, {130, 1, 2, 1}, { 2, 1, 2, 129} }, /* 47 */ + { {128, 1, 0, 129}, {0, 1, 0, 1}, { 0, 1, 0, 1}, { 2, 2, 2, 130} }, /* 48 */ + { {128, 2, 2, 130}, {0, 1, 1, 1}, { 0, 2, 2, 2}, { 0, 1, 1, 129} }, /* 49 */ + { {128, 0, 0, 2}, {1, 129, 1, 2}, { 0, 0, 0, 2}, { 1, 1, 1, 130} }, /* 50 */ + { {128, 0, 0, 0}, {2, 129, 1, 2}, { 2, 1, 1, 2}, { 2, 1, 1, 130} }, /* 51 */ + { {128, 2, 2, 2}, {0, 129, 1, 1}, { 0, 1, 1, 1}, { 0, 2, 2, 130} }, /* 52 */ + { {128, 0, 0, 2}, {1, 1, 1, 2}, {129, 1, 1, 2}, { 0, 0, 0, 130} }, /* 53 */ + { {128, 1, 1, 0}, {0, 129, 1, 0}, { 0, 1, 1, 0}, { 2, 2, 2, 130} }, /* 54 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 2, 1, 129, 2}, { 2, 1, 1, 130} }, /* 55 */ + { {128, 1, 1, 0}, {0, 129, 1, 0}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, /* 56 */ + { {128, 0, 2, 2}, {0, 0, 1, 1}, { 0, 0, 129, 1}, { 0, 0, 2, 130} }, /* 57 */ + { {128, 0, 2, 2}, {1, 1, 2, 2}, {129, 1, 2, 2}, { 0, 0, 2, 130} }, /* 58 */ + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 0}, { 2, 129, 1, 130} }, /* 59 */ + { {128, 0, 0, 130}, {0, 0, 0, 1}, { 0, 0, 0, 2}, { 0, 0, 0, 129} }, /* 60 */ + { {128, 2, 2, 2}, {1, 2, 2, 2}, { 0, 2, 2, 2}, {129, 2, 2, 130} }, /* 61 */ + { {128, 1, 0, 129}, {2, 2, 2, 2}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, /* 62 */ + { {128, 1, 1, 129}, {2, 0, 1, 1}, {130, 2, 0, 1}, { 2, 2, 2, 0} } /* 63 */ + } + }; + + static int aWeight2[] = { 0, 21, 43, 64 }; + static int aWeight3[] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + static int aWeight4[] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; + + static unsigned char sModeHasPBits = 0b11001011; + + bcdec__bitstream_t bstream; + int mode, partition, numPartitions, numEndpoints, i, j, k, rotation, partitionSet; + int indexSelectionBit, indexBits, indexBits2, index, index2; + int endpoints[6][4]; + char indices[4][4]; + int r, g, b, a; + int* weights, * weights2; + unsigned char* decompressed; + + decompressed = (unsigned char*)decompressedBlock; + + bstream.low = ((unsigned long long*)compressedBlock)[0]; + bstream.high = ((unsigned long long*)compressedBlock)[1]; + + for (mode = 0; mode < 8 && (0 == bcdec__bitstream_read_bit(&bstream)); ++mode); + + /* unexpected mode, clear the block (transparent black) */ + if (mode >= 8) { + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + decompressed[j * 4 + 0] = 0; + decompressed[j * 4 + 1] = 0; + decompressed[j * 4 + 2] = 0; + decompressed[j * 4 + 3] = 0; + } + decompressed += destinationPitch; + } + + return; + } + + partition = 0; + numPartitions = 1; + rotation = 0; + indexSelectionBit = 0; + + if (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 7) { + numPartitions = (mode == 0 || mode == 2) ? 3 : 2; + partition = bcdec__bitstream_read_bits(&bstream, (mode == 0) ? 4 : 6); + } + + numEndpoints = numPartitions * 2; + + if (mode == 4 || mode == 5) { + rotation = bcdec__bitstream_read_bits(&bstream, 2); + + if (mode == 4) { + indexSelectionBit = bcdec__bitstream_read_bit(&bstream); + } + } + + /* Extract endpoints */ + /* RGB */ + for (i = 0; i < 3; ++i) { + for (j = 0; j < numEndpoints; ++j) { + endpoints[j][i] = bcdec__bitstream_read_bits(&bstream, actual_bits_count[0][mode]); + } + } + /* Alpha (if any) */ + if (actual_bits_count[1][mode] > 0) { + for (j = 0; j < numEndpoints; ++j) { + endpoints[j][3] = bcdec__bitstream_read_bits(&bstream, actual_bits_count[1][mode]); + } + } + + /* Fully decode endpoints */ + /* First handle modes that have P-bits */ + if (mode == 0 || mode == 1 || mode == 3 || mode == 6 || mode == 7) { + for (i = 0; i < numEndpoints; ++i) { + /* component-wise left-shift */ + for (j = 0; j < 4; ++j) { + endpoints[i][j] <<= 1; + } + } + + /* if P-bit is shared */ + if (mode == 1) { + i = bcdec__bitstream_read_bit(&bstream); + j = bcdec__bitstream_read_bit(&bstream); + + /* rgb component-wise insert pbits */ + for (k = 0; k < 3; ++k) { + endpoints[0][k] |= i; + endpoints[1][k] |= i; + endpoints[2][k] |= j; + endpoints[3][k] |= j; + } + } else if (sModeHasPBits & (1 << mode)) { + /* unique P-bit per endpoint */ + for (i = 0; i < numEndpoints; ++i) { + j = bcdec__bitstream_read_bit(&bstream); + for (k = 0; k < 4; ++k) { + endpoints[i][k] |= j; + } + } + } + } + + for (i = 0; i < numEndpoints; ++i) { + /* get color components precision including pbit */ + j = actual_bits_count[0][mode] + ((sModeHasPBits >> mode) & 1); + + for (k = 0; k < 3; ++k) { + /* left shift endpoint components so that their MSB lies in bit 7 */ + endpoints[i][k] = endpoints[i][k] << (8 - j); + /* Replicate each component's MSB into the LSBs revealed by the left-shift operation above */ + endpoints[i][k] = endpoints[i][k] | (endpoints[i][k] >> j); + } + + /* get alpha component precision including pbit */ + j = actual_bits_count[1][mode] + ((sModeHasPBits >> mode) & 1); + + /* left shift endpoint components so that their MSB lies in bit 7 */ + endpoints[i][3] = endpoints[i][3] << (8 - j); + /* Replicate each component's MSB into the LSBs revealed by the left-shift operation above */ + endpoints[i][3] = endpoints[i][3] | (endpoints[i][3] >> j); + } + + /* If this mode does not explicitly define the alpha component */ + /* set alpha equal to 1.0 */ + if (!actual_bits_count[1][mode]) { + for (j = 0; j < numEndpoints; ++j) { + endpoints[j][3] = 0xFF; + } + } + + /* Determine weights tables */ + indexBits = (mode == 0 || mode == 1) ? 3 : ((mode == 6) ? 4 : 2); + indexBits2 = (mode == 4) ? 3 : ((mode == 5) ? 2 : 0); + weights = (indexBits == 2) ? aWeight2 : ((indexBits == 3) ? aWeight3 : aWeight4); + weights2 = (indexBits2 == 2) ? aWeight2 : aWeight3; + + /* Quite inconvenient that indices aren't interleaved so we have to make 2 passes here */ + /* Pass #1: collecting color indices */ + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + partitionSet = (numPartitions == 1) ? ((i | j) ? 0 : 128) : partition_sets[numPartitions - 2][partition][i][j]; + + indexBits = (mode == 0 || mode == 1) ? 3 : ((mode == 6) ? 4 : 2); + /* fix-up index is specified with one less bit */ + /* The fix-up index for subset 0 is always index 0 */ + if (partitionSet & 0x80) { + indexBits--; + } + + indices[i][j] = bcdec__bitstream_read_bits(&bstream, indexBits); + } + } + + /* Pass #2: reading alpha indices (if any) and interpolating & rotating */ + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + partitionSet = (numPartitions == 1) ? ((i|j) ? 0 : 128) : partition_sets[numPartitions - 2][partition][i][j]; + partitionSet &= 0x03; + + index = indices[i][j]; + + if (!indexBits2) { + r = bcdec__interpolate(endpoints[partitionSet * 2][0], endpoints[partitionSet * 2 + 1][0], weights, index); + g = bcdec__interpolate(endpoints[partitionSet * 2][1], endpoints[partitionSet * 2 + 1][1], weights, index); + b = bcdec__interpolate(endpoints[partitionSet * 2][2], endpoints[partitionSet * 2 + 1][2], weights, index); + a = bcdec__interpolate(endpoints[partitionSet * 2][3], endpoints[partitionSet * 2 + 1][3], weights, index); + } else { + index2 = bcdec__bitstream_read_bits(&bstream, (i|j) ? indexBits2 : (indexBits2 - 1)); + /* The index value for interpolating color comes from the secondary index bits for the texel + if the mode has an index selection bit and its value is one, and from the primary index bits otherwise. + The alpha index comes from the secondary index bits if the block has a secondary index and + the block either doesn’t have an index selection bit or that bit is zero, and from the primary index bits otherwise. */ + if (!indexSelectionBit) { + r = bcdec__interpolate(endpoints[partitionSet * 2][0], endpoints[partitionSet * 2 + 1][0], weights, index); + g = bcdec__interpolate(endpoints[partitionSet * 2][1], endpoints[partitionSet * 2 + 1][1], weights, index); + b = bcdec__interpolate(endpoints[partitionSet * 2][2], endpoints[partitionSet * 2 + 1][2], weights, index); + a = bcdec__interpolate(endpoints[partitionSet * 2][3], endpoints[partitionSet * 2 + 1][3], weights2, index2); + } else { + r = bcdec__interpolate(endpoints[partitionSet * 2][0], endpoints[partitionSet * 2 + 1][0], weights2, index2); + g = bcdec__interpolate(endpoints[partitionSet * 2][1], endpoints[partitionSet * 2 + 1][1], weights2, index2); + b = bcdec__interpolate(endpoints[partitionSet * 2][2], endpoints[partitionSet * 2 + 1][2], weights2, index2); + a = bcdec__interpolate(endpoints[partitionSet * 2][3], endpoints[partitionSet * 2 + 1][3], weights, index); + } + } + + switch (rotation) { + case 1: { /* 01 – Block format is Scalar(R) Vector(AGB) - swap A and R */ + bcdec__swap_values(&a, &r); + } break; + case 2: { /* 10 – Block format is Scalar(G) Vector(RAB) - swap A and G */ + bcdec__swap_values(&a, &g); + } break; + case 3: { /* 11 - Block format is Scalar(B) Vector(RGA) - swap A and B */ + bcdec__swap_values(&a, &b); + } break; + } + + decompressed[j * 4 + 0] = r; + decompressed[j * 4 + 1] = g; + decompressed[j * 4 + 2] = b; + decompressed[j * 4 + 3] = a; + } + + decompressed += destinationPitch; + } +} + +#endif /* BCDEC_IMPLEMENTATION */ + +/* LICENSE: + +This software is available under 2 licenses -- choose whichever you prefer. + +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License + +Copyright (c) 2022 Sergii Kudlai + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------------------------------------ +ALTERNATIVE B - The Unlicense + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <https://unlicense.org> + +*/ diff --git a/thirdparty/openxr/COPYING.adoc b/thirdparty/openxr/COPYING.adoc index 18c85fa6c7..d700a19d7b 100644 --- a/thirdparty/openxr/COPYING.adoc +++ b/thirdparty/openxr/COPYING.adoc @@ -6,7 +6,7 @@ This document is shared across a number of OpenXR GitHub projects, as the set of files in those projects is partially overlapping. -(There is a single "source of truth" internal Khronos GitLab repo these +(There is a single "source of truth" internal Khronos GitLab monorepo these GitHub repositories interact with.) == Licenses @@ -17,7 +17,7 @@ https://reuse.software/spec/[REUSE 3.0 specification] with clear copyright holders and license identifier listed for each file, preferably in each file. Where this is not possible, or e.g. when we are using files unmodified from -other open-source projects, license data is listed: +other open source projects, license data is listed: * in an adjacent file of the same name, with the additional extension "`.license`" diff --git a/thirdparty/openxr/include/openxr/openxr.h b/thirdparty/openxr/include/openxr/openxr.h index 9ac66d8c69..f094b0f72b 100644 --- a/thirdparty/openxr/include/openxr/openxr.h +++ b/thirdparty/openxr/include/openxr/openxr.h @@ -26,7 +26,7 @@ extern "C" { ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL)) // OpenXR current version number. -#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 1, 38) +#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 1, 41) // OpenXR 1.0 version number #define XR_API_VERSION_1_0 XR_MAKE_VERSION(1, 0, XR_VERSION_PATCH(XR_CURRENT_API_VERSION)) @@ -242,6 +242,11 @@ typedef enum XrResult { XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML = -1000139004, XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML = -1000139005, XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML = -1000139006, + XR_ERROR_SPATIAL_ANCHORS_PERMISSION_DENIED_ML = -1000140000, + XR_ERROR_SPATIAL_ANCHORS_NOT_LOCALIZED_ML = -1000140001, + XR_ERROR_SPATIAL_ANCHORS_OUT_OF_MAP_BOUNDS_ML = -1000140002, + XR_ERROR_SPATIAL_ANCHORS_SPACE_NOT_LOCATABLE_ML = -1000140003, + XR_ERROR_SPATIAL_ANCHORS_ANCHOR_NOT_FOUND_ML = -1000141000, XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT = -1000142001, XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT = -1000142002, XR_SCENE_MARKER_DATA_NOT_STRING_MSFT = 1000147000, @@ -258,6 +263,10 @@ typedef enum XrResult { XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT = -1000429001, XR_ERROR_FUTURE_PENDING_EXT = -1000469001, XR_ERROR_FUTURE_INVALID_EXT = -1000469002, + XR_ERROR_SYSTEM_NOTIFICATION_PERMISSION_DENIED_ML = -1000473000, + XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML = -1000473001, + XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML = -1000474000, + XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML = -1000474001, XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED_KHR = XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED, XR_ERROR_PERMISSION_INSUFFICIENT_KHR = XR_ERROR_PERMISSION_INSUFFICIENT, XR_RESULT_MAX_ENUM = 0x7FFFFFFF @@ -346,6 +355,9 @@ typedef enum XrStructureType { XR_TYPE_GRAPHICS_BINDING_D3D12_KHR = 1000028000, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR = 1000028001, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR = 1000028002, + XR_TYPE_GRAPHICS_BINDING_METAL_KHR = 1000029000, + XR_TYPE_SWAPCHAIN_IMAGE_METAL_KHR = 1000029001, + XR_TYPE_GRAPHICS_REQUIREMENTS_METAL_KHR = 1000029002, XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT = 1000030000, XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT = 1000030001, XR_TYPE_VISIBILITY_MASK_KHR = 1000031000, @@ -492,6 +504,22 @@ typedef enum XrStructureType { XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML = 1000139002, XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML = 1000139003, XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML = 1000139004, + XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML = 1000140000, + XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML = 1000140001, + XR_TYPE_SPATIAL_ANCHOR_STATE_ML = 1000140002, + XR_TYPE_SPATIAL_ANCHORS_CREATE_STORAGE_INFO_ML = 1000141000, + XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML = 1000141001, + XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML = 1000141002, + XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_UUIDS_ML = 1000141003, + XR_TYPE_SPATIAL_ANCHORS_PUBLISH_INFO_ML = 1000141004, + XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML = 1000141005, + XR_TYPE_SPATIAL_ANCHORS_DELETE_INFO_ML = 1000141006, + XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML = 1000141007, + XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_INFO_ML = 1000141008, + XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML = 1000141009, + XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_DETAILS_ML = 1000141010, + XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_DETAILS_ML = 1000141011, + XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_DETAILS_ML = 1000141012, XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML = 1000472000, XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML = 1000472001, XR_TYPE_USER_CALIBRATION_ENABLE_EVENTS_INFO_ML = 1000472002, @@ -599,6 +627,11 @@ typedef enum XrStructureType { XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC = 1000318002, XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC = 1000319000, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC = 1000319001, + XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_HTC = 1000320000, + XR_TYPE_BODY_TRACKER_CREATE_INFO_HTC = 1000320001, + XR_TYPE_BODY_JOINTS_LOCATE_INFO_HTC = 1000320002, + XR_TYPE_BODY_JOINT_LOCATIONS_HTC = 1000320003, + XR_TYPE_BODY_SKELETON_HTC = 1000320004, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT = 1000373000, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX = 1000375000, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX = 1000375001, @@ -617,6 +650,19 @@ typedef enum XrStructureType { XR_TYPE_FUTURE_POLL_RESULT_EXT = 1000469003, XR_TYPE_EVENT_DATA_USER_PRESENCE_CHANGED_EXT = 1000470000, XR_TYPE_SYSTEM_USER_PRESENCE_PROPERTIES_EXT = 1000470001, + XR_TYPE_SYSTEM_NOTIFICATIONS_SET_INFO_ML = 1000473000, + XR_TYPE_WORLD_MESH_DETECTOR_CREATE_INFO_ML = 1000474001, + XR_TYPE_WORLD_MESH_STATE_REQUEST_INFO_ML = 1000474002, + XR_TYPE_WORLD_MESH_BLOCK_STATE_ML = 1000474003, + XR_TYPE_WORLD_MESH_STATE_REQUEST_COMPLETION_ML = 1000474004, + XR_TYPE_WORLD_MESH_BUFFER_RECOMMENDED_SIZE_INFO_ML = 1000474005, + XR_TYPE_WORLD_MESH_BUFFER_SIZE_ML = 1000474006, + XR_TYPE_WORLD_MESH_BUFFER_ML = 1000474007, + XR_TYPE_WORLD_MESH_BLOCK_REQUEST_ML = 1000474008, + XR_TYPE_WORLD_MESH_GET_INFO_ML = 1000474009, + XR_TYPE_WORLD_MESH_BLOCK_ML = 1000474010, + XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML = 1000474011, + XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML = 1000474012, XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN2_KHR = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR, @@ -713,6 +759,7 @@ typedef enum XrObjectType { XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB = 1000118004, XR_OBJECT_TYPE_MARKER_DETECTOR_ML = 1000138000, XR_OBJECT_TYPE_EXPORTED_LOCALIZATION_MAP_ML = 1000139000, + XR_OBJECT_TYPE_SPATIAL_ANCHORS_STORAGE_ML = 1000141000, XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT = 1000142000, XR_OBJECT_TYPE_FACE_TRACKER_FB = 1000201000, XR_OBJECT_TYPE_EYE_TRACKER_FB = 1000202000, @@ -723,7 +770,9 @@ typedef enum XrObjectType { XR_OBJECT_TYPE_ENVIRONMENT_DEPTH_PROVIDER_META = 1000291000, XR_OBJECT_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_META = 1000291001, XR_OBJECT_TYPE_PASSTHROUGH_HTC = 1000317000, + XR_OBJECT_TYPE_BODY_TRACKER_HTC = 1000320000, XR_OBJECT_TYPE_PLANE_DETECTOR_EXT = 1000429000, + XR_OBJECT_TYPE_WORLD_MESH_DETECTOR_ML = 1000474000, XR_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF } XrObjectType; typedef XrFlags64 XrInstanceCreateFlags; @@ -2184,7 +2233,7 @@ typedef struct XrEventDataMainSessionVisibilityChangedEXTX { // XR_VARJO_quad_views is a preprocessor guard. Do not pass it to API calls. #define XR_VARJO_quad_views 1 -#define XR_VARJO_quad_views_SPEC_VERSION 1 +#define XR_VARJO_quad_views_SPEC_VERSION 2 #define XR_VARJO_QUAD_VIEWS_EXTENSION_NAME "XR_VARJO_quad_views" @@ -4982,6 +5031,245 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetExportedLocalizationMapDataML( #endif /* !XR_NO_PROTOTYPES */ +// XR_ML_spatial_anchors is a preprocessor guard. Do not pass it to API calls. +#define XR_ML_spatial_anchors 1 +XR_DEFINE_OPAQUE_64(XrFutureEXT) +#define XR_ML_spatial_anchors_SPEC_VERSION 1 +#define XR_ML_SPATIAL_ANCHORS_EXTENSION_NAME "XR_ML_spatial_anchors" + +typedef enum XrSpatialAnchorConfidenceML { + XR_SPATIAL_ANCHOR_CONFIDENCE_LOW_ML = 0, + XR_SPATIAL_ANCHOR_CONFIDENCE_MEDIUM_ML = 1, + XR_SPATIAL_ANCHOR_CONFIDENCE_HIGH_ML = 2, + XR_SPATIAL_ANCHOR_CONFIDENCE_MAX_ENUM_ML = 0x7FFFFFFF +} XrSpatialAnchorConfidenceML; +typedef struct XR_MAY_ALIAS XrSpatialAnchorsCreateInfoBaseHeaderML { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrSpatialAnchorsCreateInfoBaseHeaderML; + +typedef struct XrSpatialAnchorsCreateInfoFromPoseML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace baseSpace; + XrPosef poseInBaseSpace; + XrTime time; +} XrSpatialAnchorsCreateInfoFromPoseML; + +typedef struct XrCreateSpatialAnchorsCompletionML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; + uint32_t spaceCount; + XrSpace* spaces; +} XrCreateSpatialAnchorsCompletionML; + +typedef struct XrSpatialAnchorStateML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrSpatialAnchorConfidenceML confidence; +} XrSpatialAnchorStateML; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorsAsyncML)(XrSession session, const XrSpatialAnchorsCreateInfoBaseHeaderML* createInfo, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorsCompleteML)(XrSession session, XrFutureEXT future, XrCreateSpatialAnchorsCompletionML* completion); +typedef XrResult (XRAPI_PTR *PFN_xrGetSpatialAnchorStateML)(XrSpace anchor, XrSpatialAnchorStateML* state); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorsAsyncML( + XrSession session, + const XrSpatialAnchorsCreateInfoBaseHeaderML* createInfo, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorsCompleteML( + XrSession session, + XrFutureEXT future, + XrCreateSpatialAnchorsCompletionML* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetSpatialAnchorStateML( + XrSpace anchor, + XrSpatialAnchorStateML* state); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_ML_spatial_anchors_storage is a preprocessor guard. Do not pass it to API calls. +#define XR_ML_spatial_anchors_storage 1 +XR_DEFINE_HANDLE(XrSpatialAnchorsStorageML) +#define XR_ML_spatial_anchors_storage_SPEC_VERSION 1 +#define XR_ML_SPATIAL_ANCHORS_STORAGE_EXTENSION_NAME "XR_ML_spatial_anchors_storage" +typedef struct XrSpatialAnchorsCreateStorageInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrSpatialAnchorsCreateStorageInfoML; + +typedef struct XR_MAY_ALIAS XrSpatialAnchorsQueryInfoBaseHeaderML { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrSpatialAnchorsQueryInfoBaseHeaderML; + +typedef struct XrSpatialAnchorsQueryInfoRadiusML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace baseSpace; + XrVector3f center; + XrTime time; + float radius; +} XrSpatialAnchorsQueryInfoRadiusML; + +typedef struct XrSpatialAnchorsQueryCompletionML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; + uint32_t uuidCapacityInput; + uint32_t uuidCountOutput; + XrUuidEXT* uuids; +} XrSpatialAnchorsQueryCompletionML; + +typedef struct XrSpatialAnchorsCreateInfoFromUuidsML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpatialAnchorsStorageML storage; + uint32_t uuidCount; + const XrUuidEXT* uuids; +} XrSpatialAnchorsCreateInfoFromUuidsML; + +typedef struct XrSpatialAnchorsPublishInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t anchorCount; + const XrSpace* anchors; + uint64_t expiration; +} XrSpatialAnchorsPublishInfoML; + +typedef struct XrSpatialAnchorsPublishCompletionML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; + uint32_t uuidCount; + XrUuidEXT* uuids; +} XrSpatialAnchorsPublishCompletionML; + +typedef struct XrSpatialAnchorsDeleteInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t uuidCount; + const XrUuidEXT* uuids; +} XrSpatialAnchorsDeleteInfoML; + +typedef struct XrSpatialAnchorsDeleteCompletionML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; +} XrSpatialAnchorsDeleteCompletionML; + +typedef struct XrSpatialAnchorsUpdateExpirationInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t uuidCount; + const XrUuidEXT* uuids; + uint64_t expiration; +} XrSpatialAnchorsUpdateExpirationInfoML; + +typedef struct XrSpatialAnchorsUpdateExpirationCompletionML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; +} XrSpatialAnchorsUpdateExpirationCompletionML; + +typedef struct XrSpatialAnchorCompletionResultML { + XrUuidEXT uuid; + XrResult result; +} XrSpatialAnchorCompletionResultML; + +// XrSpatialAnchorsPublishCompletionDetailsML extends XrSpatialAnchorsPublishCompletionML +typedef struct XrSpatialAnchorsPublishCompletionDetailsML { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t resultCount; + XrSpatialAnchorCompletionResultML* results; +} XrSpatialAnchorsPublishCompletionDetailsML; + +// XrSpatialAnchorsDeleteCompletionDetailsML extends XrSpatialAnchorsDeleteCompletionML +typedef struct XrSpatialAnchorsDeleteCompletionDetailsML { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t resultCount; + XrSpatialAnchorCompletionResultML* results; +} XrSpatialAnchorsDeleteCompletionDetailsML; + +// XrSpatialAnchorsUpdateExpirationCompletionDetailsML extends XrSpatialAnchorsUpdateExpirationCompletionML +typedef struct XrSpatialAnchorsUpdateExpirationCompletionDetailsML { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t resultCount; + XrSpatialAnchorCompletionResultML* results; +} XrSpatialAnchorsUpdateExpirationCompletionDetailsML; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorsStorageML)(XrSession session, const XrSpatialAnchorsCreateStorageInfoML* createInfo, XrSpatialAnchorsStorageML* storage); +typedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorsStorageML)(XrSpatialAnchorsStorageML storage); +typedef XrResult (XRAPI_PTR *PFN_xrQuerySpatialAnchorsAsyncML)(XrSpatialAnchorsStorageML storage, const XrSpatialAnchorsQueryInfoBaseHeaderML* queryInfo, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrQuerySpatialAnchorsCompleteML)(XrSpatialAnchorsStorageML storage, XrFutureEXT future, XrSpatialAnchorsQueryCompletionML* completion); +typedef XrResult (XRAPI_PTR *PFN_xrPublishSpatialAnchorsAsyncML)(XrSpatialAnchorsStorageML storage, const XrSpatialAnchorsPublishInfoML* publishInfo, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrPublishSpatialAnchorsCompleteML)(XrSpatialAnchorsStorageML storage, XrFutureEXT future, XrSpatialAnchorsPublishCompletionML* completion); +typedef XrResult (XRAPI_PTR *PFN_xrDeleteSpatialAnchorsAsyncML)(XrSpatialAnchorsStorageML storage, const XrSpatialAnchorsDeleteInfoML* deleteInfo, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrDeleteSpatialAnchorsCompleteML)(XrSpatialAnchorsStorageML storage, XrFutureEXT future, XrSpatialAnchorsDeleteCompletionML* completion); +typedef XrResult (XRAPI_PTR *PFN_xrUpdateSpatialAnchorsExpirationAsyncML)(XrSpatialAnchorsStorageML storage, const XrSpatialAnchorsUpdateExpirationInfoML* updateInfo, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrUpdateSpatialAnchorsExpirationCompleteML)(XrSpatialAnchorsStorageML storage, XrFutureEXT future, XrSpatialAnchorsUpdateExpirationCompletionML* completion); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorsStorageML( + XrSession session, + const XrSpatialAnchorsCreateStorageInfoML* createInfo, + XrSpatialAnchorsStorageML* storage); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialAnchorsStorageML( + XrSpatialAnchorsStorageML storage); + +XRAPI_ATTR XrResult XRAPI_CALL xrQuerySpatialAnchorsAsyncML( + XrSpatialAnchorsStorageML storage, + const XrSpatialAnchorsQueryInfoBaseHeaderML* queryInfo, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrQuerySpatialAnchorsCompleteML( + XrSpatialAnchorsStorageML storage, + XrFutureEXT future, + XrSpatialAnchorsQueryCompletionML* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrPublishSpatialAnchorsAsyncML( + XrSpatialAnchorsStorageML storage, + const XrSpatialAnchorsPublishInfoML* publishInfo, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrPublishSpatialAnchorsCompleteML( + XrSpatialAnchorsStorageML storage, + XrFutureEXT future, + XrSpatialAnchorsPublishCompletionML* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrDeleteSpatialAnchorsAsyncML( + XrSpatialAnchorsStorageML storage, + const XrSpatialAnchorsDeleteInfoML* deleteInfo, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrDeleteSpatialAnchorsCompleteML( + XrSpatialAnchorsStorageML storage, + XrFutureEXT future, + XrSpatialAnchorsDeleteCompletionML* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrUpdateSpatialAnchorsExpirationAsyncML( + XrSpatialAnchorsStorageML storage, + const XrSpatialAnchorsUpdateExpirationInfoML* updateInfo, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrUpdateSpatialAnchorsExpirationCompleteML( + XrSpatialAnchorsStorageML storage, + XrFutureEXT future, + XrSpatialAnchorsUpdateExpirationCompletionML* completion); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + // XR_MSFT_spatial_anchor_persistence is a preprocessor guard. Do not pass it to API calls. #define XR_MSFT_spatial_anchor_persistence 1 XR_DEFINE_HANDLE(XrSpatialAnchorStoreConnectionMSFT) @@ -7052,6 +7340,131 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetSpatialAnchorNameHTC( #endif /* !XR_NO_PROTOTYPES */ +// XR_HTC_body_tracking is a preprocessor guard. Do not pass it to API calls. +#define XR_HTC_body_tracking 1 + +#define XR_BODY_JOINT_COUNT_HTC 26 + +XR_DEFINE_HANDLE(XrBodyTrackerHTC) +#define XR_HTC_body_tracking_SPEC_VERSION 1 +#define XR_HTC_BODY_TRACKING_EXTENSION_NAME "XR_HTC_body_tracking" + +typedef enum XrBodyJointHTC { + XR_BODY_JOINT_PELVIS_HTC = 0, + XR_BODY_JOINT_LEFT_HIP_HTC = 1, + XR_BODY_JOINT_LEFT_KNEE_HTC = 2, + XR_BODY_JOINT_LEFT_ANKLE_HTC = 3, + XR_BODY_JOINT_LEFT_FEET_HTC = 4, + XR_BODY_JOINT_RIGHT_HIP_HTC = 5, + XR_BODY_JOINT_RIGHT_KNEE_HTC = 6, + XR_BODY_JOINT_RIGHT_ANKLE_HTC = 7, + XR_BODY_JOINT_RIGHT_FEET_HTC = 8, + XR_BODY_JOINT_WAIST_HTC = 9, + XR_BODY_JOINT_SPINE_LOWER_HTC = 10, + XR_BODY_JOINT_SPINE_MIDDLE_HTC = 11, + XR_BODY_JOINT_SPINE_HIGH_HTC = 12, + XR_BODY_JOINT_CHEST_HTC = 13, + XR_BODY_JOINT_NECK_HTC = 14, + XR_BODY_JOINT_HEAD_HTC = 15, + XR_BODY_JOINT_LEFT_CLAVICLE_HTC = 16, + XR_BODY_JOINT_LEFT_SCAPULA_HTC = 17, + XR_BODY_JOINT_LEFT_ARM_HTC = 18, + XR_BODY_JOINT_LEFT_ELBOW_HTC = 19, + XR_BODY_JOINT_LEFT_WRIST_HTC = 20, + XR_BODY_JOINT_RIGHT_CLAVICLE_HTC = 21, + XR_BODY_JOINT_RIGHT_SCAPULA_HTC = 22, + XR_BODY_JOINT_RIGHT_ARM_HTC = 23, + XR_BODY_JOINT_RIGHT_ELBOW_HTC = 24, + XR_BODY_JOINT_RIGHT_WRIST_HTC = 25, + XR_BODY_JOINT_MAX_ENUM_HTC = 0x7FFFFFFF +} XrBodyJointHTC; + +typedef enum XrBodyJointSetHTC { + XR_BODY_JOINT_SET_FULL_HTC = 0, + XR_BODY_JOINT_SET_MAX_ENUM_HTC = 0x7FFFFFFF +} XrBodyJointSetHTC; + +typedef enum XrBodyJointConfidenceHTC { + XR_BODY_JOINT_CONFIDENCE_NONE_HTC = 0, + XR_BODY_JOINT_CONFIDENCE_LOW_HTC = 1, + XR_BODY_JOINT_CONFIDENCE_HIGH_HTC = 2, + XR_BODY_JOINT_CONFIDENCE_MAX_ENUM_HTC = 0x7FFFFFFF +} XrBodyJointConfidenceHTC; +// XrSystemBodyTrackingPropertiesHTC extends XrSystemProperties +typedef struct XrSystemBodyTrackingPropertiesHTC { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsBodyTracking; +} XrSystemBodyTrackingPropertiesHTC; + +typedef struct XrBodyTrackerCreateInfoHTC { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrBodyJointSetHTC bodyJointSet; +} XrBodyTrackerCreateInfoHTC; + +typedef struct XrBodyJointsLocateInfoHTC { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace baseSpace; + XrTime time; +} XrBodyJointsLocateInfoHTC; + +typedef struct XrBodyJointLocationHTC { + XrSpaceLocationFlags locationFlags; + XrPosef pose; +} XrBodyJointLocationHTC; + +typedef struct XrBodyJointLocationsHTC { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrSpaceLocationFlags combinedLocationFlags; + XrBodyJointConfidenceHTC confidenceLevel; + uint32_t jointLocationCount; + XrBodyJointLocationHTC* jointLocations; + uint32_t skeletonGenerationId; +} XrBodyJointLocationsHTC; + +typedef struct XrBodySkeletonJointHTC { + XrPosef pose; +} XrBodySkeletonJointHTC; + +typedef struct XrBodySkeletonHTC { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t jointCount; + XrBodySkeletonJointHTC* joints; +} XrBodySkeletonHTC; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateBodyTrackerHTC)(XrSession session, const XrBodyTrackerCreateInfoHTC* createInfo, XrBodyTrackerHTC* bodyTracker); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyBodyTrackerHTC)(XrBodyTrackerHTC bodyTracker); +typedef XrResult (XRAPI_PTR *PFN_xrLocateBodyJointsHTC)(XrBodyTrackerHTC bodyTracker, const XrBodyJointsLocateInfoHTC* locateInfo, XrBodyJointLocationsHTC* locations); +typedef XrResult (XRAPI_PTR *PFN_xrGetBodySkeletonHTC)(XrBodyTrackerHTC bodyTracker, XrSpace baseSpace, uint32_t skeletonGenerationId, XrBodySkeletonHTC* skeleton); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateBodyTrackerHTC( + XrSession session, + const XrBodyTrackerCreateInfoHTC* createInfo, + XrBodyTrackerHTC* bodyTracker); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroyBodyTrackerHTC( + XrBodyTrackerHTC bodyTracker); + +XRAPI_ATTR XrResult XRAPI_CALL xrLocateBodyJointsHTC( + XrBodyTrackerHTC bodyTracker, + const XrBodyJointsLocateInfoHTC* locateInfo, + XrBodyJointLocationsHTC* locations); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetBodySkeletonHTC( + XrBodyTrackerHTC bodyTracker, + XrSpace baseSpace, + uint32_t skeletonGenerationId, + XrBodySkeletonHTC* skeleton); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + // XR_EXT_active_action_set_priority is a preprocessor guard. Do not pass it to API calls. #define XR_EXT_active_action_set_priority 1 #define XR_EXT_active_action_set_priority_SPEC_VERSION 1 @@ -7313,7 +7726,6 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetPlanePolygonBufferEXT( // XR_EXT_future is a preprocessor guard. Do not pass it to API calls. #define XR_EXT_future 1 -XR_DEFINE_OPAQUE_64(XrFutureEXT) #define XR_EXT_future_SPEC_VERSION 1 #define XR_EXT_FUTURE_EXTENSION_NAME "XR_EXT_future" #define XR_NULL_FUTURE_EXT 0 @@ -7440,6 +7852,232 @@ XRAPI_ATTR XrResult XRAPI_CALL xrEnableUserCalibrationEventsML( #endif /* !XR_NO_PROTOTYPES */ +// XR_ML_system_notifications is a preprocessor guard. Do not pass it to API calls. +#define XR_ML_system_notifications 1 +#define XR_ML_system_notifications_SPEC_VERSION 1 +#define XR_ML_SYSTEM_NOTIFICATIONS_EXTENSION_NAME "XR_ML_system_notifications" +typedef struct XrSystemNotificationsSetInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrBool32 suppressNotifications; +} XrSystemNotificationsSetInfoML; + +typedef XrResult (XRAPI_PTR *PFN_xrSetSystemNotificationsML)(XrInstance instance, const XrSystemNotificationsSetInfoML* info); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrSetSystemNotificationsML( + XrInstance instance, + const XrSystemNotificationsSetInfoML* info); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_ML_world_mesh_detection is a preprocessor guard. Do not pass it to API calls. +#define XR_ML_world_mesh_detection 1 +XR_DEFINE_HANDLE(XrWorldMeshDetectorML) +#define XR_ML_world_mesh_detection_SPEC_VERSION 1 +#define XR_ML_WORLD_MESH_DETECTION_EXTENSION_NAME "XR_ML_world_mesh_detection" + +typedef enum XrWorldMeshDetectorLodML { + XR_WORLD_MESH_DETECTOR_LOD_MINIMUM_ML = 0, + XR_WORLD_MESH_DETECTOR_LOD_MEDIUM_ML = 1, + XR_WORLD_MESH_DETECTOR_LOD_MAXIMUM_ML = 2, + XR_WORLD_MESH_DETECTOR_LOD_MAX_ENUM_ML = 0x7FFFFFFF +} XrWorldMeshDetectorLodML; + +typedef enum XrWorldMeshBlockStatusML { + XR_WORLD_MESH_BLOCK_STATUS_NEW_ML = 0, + XR_WORLD_MESH_BLOCK_STATUS_UPDATED_ML = 1, + XR_WORLD_MESH_BLOCK_STATUS_DELETED_ML = 2, + XR_WORLD_MESH_BLOCK_STATUS_UNCHANGED_ML = 3, + XR_WORLD_MESH_BLOCK_STATUS_MAX_ENUM_ML = 0x7FFFFFFF +} XrWorldMeshBlockStatusML; + +typedef enum XrWorldMeshBlockResultML { + XR_WORLD_MESH_BLOCK_RESULT_SUCCESS_ML = 0, + XR_WORLD_MESH_BLOCK_RESULT_FAILED_ML = 1, + XR_WORLD_MESH_BLOCK_RESULT_PENDING_ML = 2, + XR_WORLD_MESH_BLOCK_RESULT_PARTIAL_UPDATE_ML = 3, + XR_WORLD_MESH_BLOCK_RESULT_MAX_ENUM_ML = 0x7FFFFFFF +} XrWorldMeshBlockResultML; +typedef XrFlags64 XrWorldMeshDetectorFlagsML; + +// Flag bits for XrWorldMeshDetectorFlagsML +static const XrWorldMeshDetectorFlagsML XR_WORLD_MESH_DETECTOR_POINT_CLOUD_BIT_ML = 0x00000001; +static const XrWorldMeshDetectorFlagsML XR_WORLD_MESH_DETECTOR_COMPUTE_NORMALS_BIT_ML = 0x00000002; +static const XrWorldMeshDetectorFlagsML XR_WORLD_MESH_DETECTOR_COMPUTE_CONFIDENCE_BIT_ML = 0x00000004; +static const XrWorldMeshDetectorFlagsML XR_WORLD_MESH_DETECTOR_PLANARIZE_BIT_ML = 0x00000008; +static const XrWorldMeshDetectorFlagsML XR_WORLD_MESH_DETECTOR_REMOVE_MESH_SKIRT_BIT_ML = 0x00000010; +static const XrWorldMeshDetectorFlagsML XR_WORLD_MESH_DETECTOR_INDEX_ORDER_CW_BIT_ML = 0x00000020; + +typedef struct XrWorldMeshDetectorCreateInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrWorldMeshDetectorCreateInfoML; + +typedef struct XrWorldMeshBlockStateML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrUuidEXT uuid; + XrPosef meshBoundingBoxCenter; + XrExtent3DfEXT meshBoundingBoxExtents; + XrTime lastUpdateTime; + XrWorldMeshBlockStatusML status; +} XrWorldMeshBlockStateML; + +typedef struct XrWorldMeshStateRequestInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace baseSpace; + XrTime time; + XrPosef boundingBoxCenter; + XrExtent3DfEXT boundingBoxExtents; +} XrWorldMeshStateRequestInfoML; + +typedef struct XrWorldMeshStateRequestCompletionML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; + XrTime timestamp; + uint32_t meshBlockStateCapacityInput; + uint32_t meshBlockStateCountOutput; + XrWorldMeshBlockStateML* meshBlockStates; +} XrWorldMeshStateRequestCompletionML; + +typedef struct XrWorldMeshBufferRecommendedSizeInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t maxBlockCount; +} XrWorldMeshBufferRecommendedSizeInfoML; + +typedef struct XrWorldMeshBufferSizeML { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t size; +} XrWorldMeshBufferSizeML; + +typedef struct XrWorldMeshBufferML { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t bufferSize; + void* XR_MAY_ALIAS buffer; +} XrWorldMeshBufferML; + +typedef struct XrWorldMeshBlockRequestML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrUuidEXT uuid; + XrWorldMeshDetectorLodML lod; +} XrWorldMeshBlockRequestML; + +typedef struct XrWorldMeshGetInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrWorldMeshDetectorFlagsML flags; + float fillHoleLength; + float disconnectedComponentArea; + uint32_t blockCount; + XrWorldMeshBlockRequestML* blocks; +} XrWorldMeshGetInfoML; + +typedef struct XrWorldMeshBlockML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrUuidEXT uuid; + XrWorldMeshBlockResultML blockResult; + XrWorldMeshDetectorLodML lod; + XrWorldMeshDetectorFlagsML flags; + uint32_t indexCount; + uint16_t* indexBuffer; + uint32_t vertexCount; + XrVector3f* vertexBuffer; + uint32_t normalCount; + XrVector3f* normalBuffer; + uint32_t confidenceCount; + float* confidenceBuffer; +} XrWorldMeshBlockML; + +typedef struct XrWorldMeshRequestCompletionInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace meshSpace; + XrTime meshSpaceLocateTime; +} XrWorldMeshRequestCompletionInfoML; + +typedef struct XrWorldMeshRequestCompletionML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; + uint32_t blockCount; + XrWorldMeshBlockML* blocks; +} XrWorldMeshRequestCompletionML; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateWorldMeshDetectorML)(XrSession session, const XrWorldMeshDetectorCreateInfoML* createInfo, XrWorldMeshDetectorML* detector); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyWorldMeshDetectorML)(XrWorldMeshDetectorML detector); +typedef XrResult (XRAPI_PTR *PFN_xrRequestWorldMeshStateAsyncML)(XrWorldMeshDetectorML detector, const XrWorldMeshStateRequestInfoML* stateRequest, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrRequestWorldMeshStateCompleteML)(XrWorldMeshDetectorML detector, XrFutureEXT future, XrWorldMeshStateRequestCompletionML* completion); +typedef XrResult (XRAPI_PTR *PFN_xrGetWorldMeshBufferRecommendSizeML)(XrWorldMeshDetectorML detector, const XrWorldMeshBufferRecommendedSizeInfoML* sizeInfo, XrWorldMeshBufferSizeML* size); +typedef XrResult (XRAPI_PTR *PFN_xrAllocateWorldMeshBufferML)(XrWorldMeshDetectorML detector, const XrWorldMeshBufferSizeML* size, XrWorldMeshBufferML* buffer); +typedef XrResult (XRAPI_PTR *PFN_xrFreeWorldMeshBufferML)(XrWorldMeshDetectorML detector, const XrWorldMeshBufferML* buffer); +typedef XrResult (XRAPI_PTR *PFN_xrRequestWorldMeshAsyncML)(XrWorldMeshDetectorML detector, const XrWorldMeshGetInfoML* getInfo, XrWorldMeshBufferML* buffer, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrRequestWorldMeshCompleteML)(XrWorldMeshDetectorML detector, const XrWorldMeshRequestCompletionInfoML* completionInfo, XrFutureEXT future, XrWorldMeshRequestCompletionML* completion); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateWorldMeshDetectorML( + XrSession session, + const XrWorldMeshDetectorCreateInfoML* createInfo, + XrWorldMeshDetectorML* detector); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroyWorldMeshDetectorML( + XrWorldMeshDetectorML detector); + +XRAPI_ATTR XrResult XRAPI_CALL xrRequestWorldMeshStateAsyncML( + XrWorldMeshDetectorML detector, + const XrWorldMeshStateRequestInfoML* stateRequest, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrRequestWorldMeshStateCompleteML( + XrWorldMeshDetectorML detector, + XrFutureEXT future, + XrWorldMeshStateRequestCompletionML* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetWorldMeshBufferRecommendSizeML( + XrWorldMeshDetectorML detector, + const XrWorldMeshBufferRecommendedSizeInfoML* sizeInfo, + XrWorldMeshBufferSizeML* size); + +XRAPI_ATTR XrResult XRAPI_CALL xrAllocateWorldMeshBufferML( + XrWorldMeshDetectorML detector, + const XrWorldMeshBufferSizeML* size, + XrWorldMeshBufferML* buffer); + +XRAPI_ATTR XrResult XRAPI_CALL xrFreeWorldMeshBufferML( + XrWorldMeshDetectorML detector, + const XrWorldMeshBufferML* buffer); + +XRAPI_ATTR XrResult XRAPI_CALL xrRequestWorldMeshAsyncML( + XrWorldMeshDetectorML detector, + const XrWorldMeshGetInfoML* getInfo, + XrWorldMeshBufferML* buffer, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrRequestWorldMeshCompleteML( + XrWorldMeshDetectorML detector, + const XrWorldMeshRequestCompletionInfoML* completionInfo, + XrFutureEXT future, + XrWorldMeshRequestCompletionML* completion); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_ML_view_configuration_depth_range_change is a preprocessor guard. Do not pass it to API calls. +#define XR_ML_view_configuration_depth_range_change 1 +#define XR_ML_view_configuration_depth_range_change_SPEC_VERSION 1 +#define XR_ML_VIEW_CONFIGURATION_DEPTH_RANGE_CHANGE_EXTENSION_NAME "XR_ML_view_configuration_depth_range_change" + + // XR_YVR_controller_interaction is a preprocessor guard. Do not pass it to API calls. #define XR_YVR_controller_interaction 1 #define XR_YVR_controller_interaction_SPEC_VERSION 1 diff --git a/thirdparty/openxr/include/openxr/openxr_platform.h b/thirdparty/openxr/include/openxr/openxr_platform.h index cbe1008906..dfd74aa5d2 100644 --- a/thirdparty/openxr/include/openxr/openxr_platform.h +++ b/thirdparty/openxr/include/openxr/openxr_platform.h @@ -356,6 +356,43 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR( #endif /* !XR_NO_PROTOTYPES */ #endif /* XR_USE_GRAPHICS_API_D3D12 */ +#ifdef XR_USE_GRAPHICS_API_METAL + +// XR_KHR_metal_enable is a preprocessor guard. Do not pass it to API calls. +#define XR_KHR_metal_enable 1 +#define XR_KHR_metal_enable_SPEC_VERSION 1 +#define XR_KHR_METAL_ENABLE_EXTENSION_NAME "XR_KHR_metal_enable" +// XrGraphicsBindingMetalKHR extends XrSessionCreateInfo +typedef struct XrGraphicsBindingMetalKHR { + XrStructureType type; + const void* XR_MAY_ALIAS next; + void* XR_MAY_ALIAS commandQueue; +} XrGraphicsBindingMetalKHR; + +typedef struct XrSwapchainImageMetalKHR { + XrStructureType type; + const void* XR_MAY_ALIAS next; + void* XR_MAY_ALIAS texture; +} XrSwapchainImageMetalKHR; + +typedef struct XrGraphicsRequirementsMetalKHR { + XrStructureType type; + void* XR_MAY_ALIAS next; + void* XR_MAY_ALIAS metalDevice; +} XrGraphicsRequirementsMetalKHR; + +typedef XrResult (XRAPI_PTR *PFN_xrGetMetalGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsMetalKHR* graphicsRequirements); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrGetMetalGraphicsRequirementsKHR( + XrInstance instance, + XrSystemId systemId, + XrGraphicsRequirementsMetalKHR* graphicsRequirements); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ +#endif /* XR_USE_GRAPHICS_API_METAL */ + #ifdef XR_USE_PLATFORM_WIN32 // XR_KHR_win32_convert_performance_counter_time is a preprocessor guard. Do not pass it to API calls. diff --git a/thirdparty/openxr/include/openxr/openxr_reflection.h b/thirdparty/openxr/include/openxr/openxr_reflection.h index b9d45689a7..4bea81c236 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection.h @@ -128,6 +128,11 @@ XR_ENUM_STR(XrResult); _(XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML, -1000139004) \ _(XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML, -1000139005) \ _(XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML, -1000139006) \ + _(XR_ERROR_SPATIAL_ANCHORS_PERMISSION_DENIED_ML, -1000140000) \ + _(XR_ERROR_SPATIAL_ANCHORS_NOT_LOCALIZED_ML, -1000140001) \ + _(XR_ERROR_SPATIAL_ANCHORS_OUT_OF_MAP_BOUNDS_ML, -1000140002) \ + _(XR_ERROR_SPATIAL_ANCHORS_SPACE_NOT_LOCATABLE_ML, -1000140003) \ + _(XR_ERROR_SPATIAL_ANCHORS_ANCHOR_NOT_FOUND_ML, -1000141000) \ _(XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT, -1000142001) \ _(XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT, -1000142002) \ _(XR_SCENE_MARKER_DATA_NOT_STRING_MSFT, 1000147000) \ @@ -144,6 +149,10 @@ XR_ENUM_STR(XrResult); _(XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT, -1000429001) \ _(XR_ERROR_FUTURE_PENDING_EXT, -1000469001) \ _(XR_ERROR_FUTURE_INVALID_EXT, -1000469002) \ + _(XR_ERROR_SYSTEM_NOTIFICATION_PERMISSION_DENIED_ML, -1000473000) \ + _(XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML, -1000473001) \ + _(XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML, -1000474000) \ + _(XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML, -1000474001) \ _(XR_RESULT_MAX_ENUM, 0x7FFFFFFF) #define XR_LIST_ENUM_XrStructureType(_) \ @@ -229,6 +238,9 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_GRAPHICS_BINDING_D3D12_KHR, 1000028000) \ _(XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR, 1000028001) \ _(XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR, 1000028002) \ + _(XR_TYPE_GRAPHICS_BINDING_METAL_KHR, 1000029000) \ + _(XR_TYPE_SWAPCHAIN_IMAGE_METAL_KHR, 1000029001) \ + _(XR_TYPE_GRAPHICS_REQUIREMENTS_METAL_KHR, 1000029002) \ _(XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT, 1000030000) \ _(XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT, 1000030001) \ _(XR_TYPE_VISIBILITY_MASK_KHR, 1000031000) \ @@ -375,6 +387,22 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML, 1000139002) \ _(XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML, 1000139003) \ _(XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML, 1000139004) \ + _(XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML, 1000140000) \ + _(XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML, 1000140001) \ + _(XR_TYPE_SPATIAL_ANCHOR_STATE_ML, 1000140002) \ + _(XR_TYPE_SPATIAL_ANCHORS_CREATE_STORAGE_INFO_ML, 1000141000) \ + _(XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML, 1000141001) \ + _(XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML, 1000141002) \ + _(XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_UUIDS_ML, 1000141003) \ + _(XR_TYPE_SPATIAL_ANCHORS_PUBLISH_INFO_ML, 1000141004) \ + _(XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML, 1000141005) \ + _(XR_TYPE_SPATIAL_ANCHORS_DELETE_INFO_ML, 1000141006) \ + _(XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML, 1000141007) \ + _(XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_INFO_ML, 1000141008) \ + _(XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML, 1000141009) \ + _(XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_DETAILS_ML, 1000141010) \ + _(XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_DETAILS_ML, 1000141011) \ + _(XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_DETAILS_ML, 1000141012) \ _(XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML, 1000472000) \ _(XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML, 1000472001) \ _(XR_TYPE_USER_CALIBRATION_ENABLE_EVENTS_INFO_ML, 1000472002) \ @@ -482,6 +510,11 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC, 1000318002) \ _(XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC, 1000319000) \ _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC, 1000319001) \ + _(XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_HTC, 1000320000) \ + _(XR_TYPE_BODY_TRACKER_CREATE_INFO_HTC, 1000320001) \ + _(XR_TYPE_BODY_JOINTS_LOCATE_INFO_HTC, 1000320002) \ + _(XR_TYPE_BODY_JOINT_LOCATIONS_HTC, 1000320003) \ + _(XR_TYPE_BODY_SKELETON_HTC, 1000320004) \ _(XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT, 1000373000) \ _(XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX, 1000375000) \ _(XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX, 1000375001) \ @@ -500,6 +533,19 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_FUTURE_POLL_RESULT_EXT, 1000469003) \ _(XR_TYPE_EVENT_DATA_USER_PRESENCE_CHANGED_EXT, 1000470000) \ _(XR_TYPE_SYSTEM_USER_PRESENCE_PROPERTIES_EXT, 1000470001) \ + _(XR_TYPE_SYSTEM_NOTIFICATIONS_SET_INFO_ML, 1000473000) \ + _(XR_TYPE_WORLD_MESH_DETECTOR_CREATE_INFO_ML, 1000474001) \ + _(XR_TYPE_WORLD_MESH_STATE_REQUEST_INFO_ML, 1000474002) \ + _(XR_TYPE_WORLD_MESH_BLOCK_STATE_ML, 1000474003) \ + _(XR_TYPE_WORLD_MESH_STATE_REQUEST_COMPLETION_ML, 1000474004) \ + _(XR_TYPE_WORLD_MESH_BUFFER_RECOMMENDED_SIZE_INFO_ML, 1000474005) \ + _(XR_TYPE_WORLD_MESH_BUFFER_SIZE_ML, 1000474006) \ + _(XR_TYPE_WORLD_MESH_BUFFER_ML, 1000474007) \ + _(XR_TYPE_WORLD_MESH_BLOCK_REQUEST_ML, 1000474008) \ + _(XR_TYPE_WORLD_MESH_GET_INFO_ML, 1000474009) \ + _(XR_TYPE_WORLD_MESH_BLOCK_ML, 1000474010) \ + _(XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML, 1000474011) \ + _(XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML, 1000474012) \ _(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF) #define XR_LIST_ENUM_XrFormFactor(_) \ @@ -579,6 +625,7 @@ XR_ENUM_STR(XrResult); _(XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB, 1000118004) \ _(XR_OBJECT_TYPE_MARKER_DETECTOR_ML, 1000138000) \ _(XR_OBJECT_TYPE_EXPORTED_LOCALIZATION_MAP_ML, 1000139000) \ + _(XR_OBJECT_TYPE_SPATIAL_ANCHORS_STORAGE_ML, 1000141000) \ _(XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT, 1000142000) \ _(XR_OBJECT_TYPE_FACE_TRACKER_FB, 1000201000) \ _(XR_OBJECT_TYPE_EYE_TRACKER_FB, 1000202000) \ @@ -589,7 +636,9 @@ XR_ENUM_STR(XrResult); _(XR_OBJECT_TYPE_ENVIRONMENT_DEPTH_PROVIDER_META, 1000291000) \ _(XR_OBJECT_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_META, 1000291001) \ _(XR_OBJECT_TYPE_PASSTHROUGH_HTC, 1000317000) \ + _(XR_OBJECT_TYPE_BODY_TRACKER_HTC, 1000320000) \ _(XR_OBJECT_TYPE_PLANE_DETECTOR_EXT, 1000429000) \ + _(XR_OBJECT_TYPE_WORLD_MESH_DETECTOR_ML, 1000474000) \ _(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF) #define XR_LIST_ENUM_XrLoaderInterfaceStructs(_) \ @@ -1053,6 +1102,12 @@ XR_ENUM_STR(XrResult); _(XR_LOCALIZATION_MAP_CONFIDENCE_EXCELLENT_ML, 3) \ _(XR_LOCALIZATION_MAP_CONFIDENCE_MAX_ENUM_ML, 0x7FFFFFFF) +#define XR_LIST_ENUM_XrSpatialAnchorConfidenceML(_) \ + _(XR_SPATIAL_ANCHOR_CONFIDENCE_LOW_ML, 0) \ + _(XR_SPATIAL_ANCHOR_CONFIDENCE_MEDIUM_ML, 1) \ + _(XR_SPATIAL_ANCHOR_CONFIDENCE_HIGH_ML, 2) \ + _(XR_SPATIAL_ANCHOR_CONFIDENCE_MAX_ENUM_ML, 0x7FFFFFFF) + #define XR_LIST_ENUM_XrSceneMarkerTypeMSFT(_) \ _(XR_SCENE_MARKER_TYPE_QR_CODE_MSFT, 1) \ _(XR_SCENE_MARKER_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF) @@ -1363,6 +1418,45 @@ XR_ENUM_STR(XrResult); _(XR_FOVEATION_LEVEL_HIGH_HTC, 3) \ _(XR_FOVEATION_LEVEL_MAX_ENUM_HTC, 0x7FFFFFFF) +#define XR_LIST_ENUM_XrBodyJointHTC(_) \ + _(XR_BODY_JOINT_PELVIS_HTC, 0) \ + _(XR_BODY_JOINT_LEFT_HIP_HTC, 1) \ + _(XR_BODY_JOINT_LEFT_KNEE_HTC, 2) \ + _(XR_BODY_JOINT_LEFT_ANKLE_HTC, 3) \ + _(XR_BODY_JOINT_LEFT_FEET_HTC, 4) \ + _(XR_BODY_JOINT_RIGHT_HIP_HTC, 5) \ + _(XR_BODY_JOINT_RIGHT_KNEE_HTC, 6) \ + _(XR_BODY_JOINT_RIGHT_ANKLE_HTC, 7) \ + _(XR_BODY_JOINT_RIGHT_FEET_HTC, 8) \ + _(XR_BODY_JOINT_WAIST_HTC, 9) \ + _(XR_BODY_JOINT_SPINE_LOWER_HTC, 10) \ + _(XR_BODY_JOINT_SPINE_MIDDLE_HTC, 11) \ + _(XR_BODY_JOINT_SPINE_HIGH_HTC, 12) \ + _(XR_BODY_JOINT_CHEST_HTC, 13) \ + _(XR_BODY_JOINT_NECK_HTC, 14) \ + _(XR_BODY_JOINT_HEAD_HTC, 15) \ + _(XR_BODY_JOINT_LEFT_CLAVICLE_HTC, 16) \ + _(XR_BODY_JOINT_LEFT_SCAPULA_HTC, 17) \ + _(XR_BODY_JOINT_LEFT_ARM_HTC, 18) \ + _(XR_BODY_JOINT_LEFT_ELBOW_HTC, 19) \ + _(XR_BODY_JOINT_LEFT_WRIST_HTC, 20) \ + _(XR_BODY_JOINT_RIGHT_CLAVICLE_HTC, 21) \ + _(XR_BODY_JOINT_RIGHT_SCAPULA_HTC, 22) \ + _(XR_BODY_JOINT_RIGHT_ARM_HTC, 23) \ + _(XR_BODY_JOINT_RIGHT_ELBOW_HTC, 24) \ + _(XR_BODY_JOINT_RIGHT_WRIST_HTC, 25) \ + _(XR_BODY_JOINT_MAX_ENUM_HTC, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrBodyJointSetHTC(_) \ + _(XR_BODY_JOINT_SET_FULL_HTC, 0) \ + _(XR_BODY_JOINT_SET_MAX_ENUM_HTC, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrBodyJointConfidenceHTC(_) \ + _(XR_BODY_JOINT_CONFIDENCE_NONE_HTC, 0) \ + _(XR_BODY_JOINT_CONFIDENCE_LOW_HTC, 1) \ + _(XR_BODY_JOINT_CONFIDENCE_HIGH_HTC, 2) \ + _(XR_BODY_JOINT_CONFIDENCE_MAX_ENUM_HTC, 0x7FFFFFFF) + #define XR_LIST_ENUM_XrForceFeedbackCurlLocationMNDX(_) \ _(XR_FORCE_FEEDBACK_CURL_LOCATION_THUMB_CURL_MNDX, 0) \ _(XR_FORCE_FEEDBACK_CURL_LOCATION_INDEX_CURL_MNDX, 1) \ @@ -1418,6 +1512,26 @@ XR_ENUM_STR(XrResult); _(XR_EYE_CALIBRATION_STATUS_FINE_ML, 3) \ _(XR_EYE_CALIBRATION_STATUS_MAX_ENUM_ML, 0x7FFFFFFF) +#define XR_LIST_ENUM_XrWorldMeshDetectorLodML(_) \ + _(XR_WORLD_MESH_DETECTOR_LOD_MINIMUM_ML, 0) \ + _(XR_WORLD_MESH_DETECTOR_LOD_MEDIUM_ML, 1) \ + _(XR_WORLD_MESH_DETECTOR_LOD_MAXIMUM_ML, 2) \ + _(XR_WORLD_MESH_DETECTOR_LOD_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrWorldMeshBlockStatusML(_) \ + _(XR_WORLD_MESH_BLOCK_STATUS_NEW_ML, 0) \ + _(XR_WORLD_MESH_BLOCK_STATUS_UPDATED_ML, 1) \ + _(XR_WORLD_MESH_BLOCK_STATUS_DELETED_ML, 2) \ + _(XR_WORLD_MESH_BLOCK_STATUS_UNCHANGED_ML, 3) \ + _(XR_WORLD_MESH_BLOCK_STATUS_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrWorldMeshBlockResultML(_) \ + _(XR_WORLD_MESH_BLOCK_RESULT_SUCCESS_ML, 0) \ + _(XR_WORLD_MESH_BLOCK_RESULT_FAILED_ML, 1) \ + _(XR_WORLD_MESH_BLOCK_RESULT_PENDING_ML, 2) \ + _(XR_WORLD_MESH_BLOCK_RESULT_PARTIAL_UPDATE_ML, 3) \ + _(XR_WORLD_MESH_BLOCK_RESULT_MAX_ENUM_ML, 0x7FFFFFFF) + #define XR_LIST_BITS_XrInstanceCreateFlags(_) #define XR_LIST_BITS_XrSessionCreateFlags(_) @@ -1622,6 +1736,14 @@ XR_ENUM_STR(XrResult); #define XR_LIST_BITS_XrPlaneDetectorFlagsEXT(_) \ _(XR_PLANE_DETECTOR_ENABLE_CONTOUR_BIT_EXT, 0x00000001) \ +#define XR_LIST_BITS_XrWorldMeshDetectorFlagsML(_) \ + _(XR_WORLD_MESH_DETECTOR_POINT_CLOUD_BIT_ML, 0x00000001) \ + _(XR_WORLD_MESH_DETECTOR_COMPUTE_NORMALS_BIT_ML, 0x00000002) \ + _(XR_WORLD_MESH_DETECTOR_COMPUTE_CONFIDENCE_BIT_ML, 0x00000004) \ + _(XR_WORLD_MESH_DETECTOR_PLANARIZE_BIT_ML, 0x00000008) \ + _(XR_WORLD_MESH_DETECTOR_REMOVE_MESH_SKIRT_BIT_ML, 0x00000010) \ + _(XR_WORLD_MESH_DETECTOR_INDEX_ORDER_CW_BIT_ML, 0x00000020) \ + /// Calls your macro with the name of each member of XrApiLayerProperties, in order. #define XR_LIST_STRUCT_XrApiLayerProperties(_) \ _(type) \ @@ -2442,6 +2564,24 @@ XR_ENUM_STR(XrResult); _(adapterLuid) \ _(minFeatureLevel) \ +/// Calls your macro with the name of each member of XrGraphicsBindingMetalKHR, in order. +#define XR_LIST_STRUCT_XrGraphicsBindingMetalKHR(_) \ + _(type) \ + _(next) \ + _(commandQueue) \ + +/// Calls your macro with the name of each member of XrSwapchainImageMetalKHR, in order. +#define XR_LIST_STRUCT_XrSwapchainImageMetalKHR(_) \ + _(type) \ + _(next) \ + _(texture) \ + +/// Calls your macro with the name of each member of XrGraphicsRequirementsMetalKHR, in order. +#define XR_LIST_STRUCT_XrGraphicsRequirementsMetalKHR(_) \ + _(type) \ + _(next) \ + _(metalDevice) \ + /// Calls your macro with the name of each member of XrVisibilityMaskKHR, in order. #define XR_LIST_STRUCT_XrVisibilityMaskKHR(_) \ _(type) \ @@ -3711,6 +3851,138 @@ XR_ENUM_STR(XrResult); _(next) \ _(enabled) \ +/// Calls your macro with the name of each member of XrSpatialAnchorsCreateInfoBaseHeaderML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsCreateInfoBaseHeaderML(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsCreateInfoFromPoseML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsCreateInfoFromPoseML(_) \ + _(type) \ + _(next) \ + _(baseSpace) \ + _(poseInBaseSpace) \ + _(time) \ + +/// Calls your macro with the name of each member of XrCreateSpatialAnchorsCompletionML, in order. +#define XR_LIST_STRUCT_XrCreateSpatialAnchorsCompletionML(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + _(spaceCount) \ + _(spaces) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorStateML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorStateML(_) \ + _(type) \ + _(next) \ + _(confidence) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsCreateStorageInfoML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsCreateStorageInfoML(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsQueryInfoBaseHeaderML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsQueryInfoBaseHeaderML(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsQueryInfoRadiusML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsQueryInfoRadiusML(_) \ + _(type) \ + _(next) \ + _(baseSpace) \ + _(center) \ + _(time) \ + _(radius) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsQueryCompletionML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsQueryCompletionML(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + _(uuidCapacityInput) \ + _(uuidCountOutput) \ + _(uuids) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsCreateInfoFromUuidsML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsCreateInfoFromUuidsML(_) \ + _(type) \ + _(next) \ + _(storage) \ + _(uuidCount) \ + _(uuids) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsPublishInfoML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsPublishInfoML(_) \ + _(type) \ + _(next) \ + _(anchorCount) \ + _(anchors) \ + _(expiration) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsPublishCompletionML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsPublishCompletionML(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + _(uuidCount) \ + _(uuids) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsDeleteInfoML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsDeleteInfoML(_) \ + _(type) \ + _(next) \ + _(uuidCount) \ + _(uuids) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsDeleteCompletionML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsDeleteCompletionML(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsUpdateExpirationInfoML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsUpdateExpirationInfoML(_) \ + _(type) \ + _(next) \ + _(uuidCount) \ + _(uuids) \ + _(expiration) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsUpdateExpirationCompletionML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsUpdateExpirationCompletionML(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorCompletionResultML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorCompletionResultML(_) \ + _(uuid) \ + _(result) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsPublishCompletionDetailsML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsPublishCompletionDetailsML(_) \ + _(type) \ + _(next) \ + _(resultCount) \ + _(results) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsDeleteCompletionDetailsML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsDeleteCompletionDetailsML(_) \ + _(type) \ + _(next) \ + _(resultCount) \ + _(results) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorsUpdateExpirationCompletionDetailsML, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorsUpdateExpirationCompletionDetailsML(_) \ + _(type) \ + _(next) \ + _(resultCount) \ + _(results) \ + /// Calls your macro with the name of each member of XrSpatialAnchorPersistenceNameMSFT, in order. #define XR_LIST_STRUCT_XrSpatialAnchorPersistenceNameMSFT(_) \ _(name) \ @@ -4571,6 +4843,51 @@ XR_ENUM_STR(XrResult); _(poseInSpace) \ _(name) \ +/// Calls your macro with the name of each member of XrSystemBodyTrackingPropertiesHTC, in order. +#define XR_LIST_STRUCT_XrSystemBodyTrackingPropertiesHTC(_) \ + _(type) \ + _(next) \ + _(supportsBodyTracking) \ + +/// Calls your macro with the name of each member of XrBodyTrackerCreateInfoHTC, in order. +#define XR_LIST_STRUCT_XrBodyTrackerCreateInfoHTC(_) \ + _(type) \ + _(next) \ + _(bodyJointSet) \ + +/// Calls your macro with the name of each member of XrBodyJointsLocateInfoHTC, in order. +#define XR_LIST_STRUCT_XrBodyJointsLocateInfoHTC(_) \ + _(type) \ + _(next) \ + _(baseSpace) \ + _(time) \ + +/// Calls your macro with the name of each member of XrBodyJointLocationHTC, in order. +#define XR_LIST_STRUCT_XrBodyJointLocationHTC(_) \ + _(locationFlags) \ + _(pose) \ + +/// Calls your macro with the name of each member of XrBodyJointLocationsHTC, in order. +#define XR_LIST_STRUCT_XrBodyJointLocationsHTC(_) \ + _(type) \ + _(next) \ + _(combinedLocationFlags) \ + _(confidenceLevel) \ + _(jointLocationCount) \ + _(jointLocations) \ + _(skeletonGenerationId) \ + +/// Calls your macro with the name of each member of XrBodySkeletonJointHTC, in order. +#define XR_LIST_STRUCT_XrBodySkeletonJointHTC(_) \ + _(pose) \ + +/// Calls your macro with the name of each member of XrBodySkeletonHTC, in order. +#define XR_LIST_STRUCT_XrBodySkeletonHTC(_) \ + _(type) \ + _(next) \ + _(jointCount) \ + _(joints) \ + /// Calls your macro with the name of each member of XrActiveActionSetPriorityEXT, in order. #define XR_LIST_STRUCT_XrActiveActionSetPriorityEXT(_) \ _(actionSet) \ @@ -4739,6 +5056,114 @@ XR_ENUM_STR(XrResult); _(next) \ _(enabled) \ +/// Calls your macro with the name of each member of XrSystemNotificationsSetInfoML, in order. +#define XR_LIST_STRUCT_XrSystemNotificationsSetInfoML(_) \ + _(type) \ + _(next) \ + _(suppressNotifications) \ + +/// Calls your macro with the name of each member of XrWorldMeshDetectorCreateInfoML, in order. +#define XR_LIST_STRUCT_XrWorldMeshDetectorCreateInfoML(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrWorldMeshBlockStateML, in order. +#define XR_LIST_STRUCT_XrWorldMeshBlockStateML(_) \ + _(type) \ + _(next) \ + _(uuid) \ + _(meshBoundingBoxCenter) \ + _(meshBoundingBoxExtents) \ + _(lastUpdateTime) \ + _(status) \ + +/// Calls your macro with the name of each member of XrWorldMeshStateRequestInfoML, in order. +#define XR_LIST_STRUCT_XrWorldMeshStateRequestInfoML(_) \ + _(type) \ + _(next) \ + _(baseSpace) \ + _(time) \ + _(boundingBoxCenter) \ + _(boundingBoxExtents) \ + +/// Calls your macro with the name of each member of XrWorldMeshStateRequestCompletionML, in order. +#define XR_LIST_STRUCT_XrWorldMeshStateRequestCompletionML(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + _(timestamp) \ + _(meshBlockStateCapacityInput) \ + _(meshBlockStateCountOutput) \ + _(meshBlockStates) \ + +/// Calls your macro with the name of each member of XrWorldMeshBufferRecommendedSizeInfoML, in order. +#define XR_LIST_STRUCT_XrWorldMeshBufferRecommendedSizeInfoML(_) \ + _(type) \ + _(next) \ + _(maxBlockCount) \ + +/// Calls your macro with the name of each member of XrWorldMeshBufferSizeML, in order. +#define XR_LIST_STRUCT_XrWorldMeshBufferSizeML(_) \ + _(type) \ + _(next) \ + _(size) \ + +/// Calls your macro with the name of each member of XrWorldMeshBufferML, in order. +#define XR_LIST_STRUCT_XrWorldMeshBufferML(_) \ + _(type) \ + _(next) \ + _(bufferSize) \ + _(buffer) \ + +/// Calls your macro with the name of each member of XrWorldMeshBlockRequestML, in order. +#define XR_LIST_STRUCT_XrWorldMeshBlockRequestML(_) \ + _(type) \ + _(next) \ + _(uuid) \ + _(lod) \ + +/// Calls your macro with the name of each member of XrWorldMeshGetInfoML, in order. +#define XR_LIST_STRUCT_XrWorldMeshGetInfoML(_) \ + _(type) \ + _(next) \ + _(flags) \ + _(fillHoleLength) \ + _(disconnectedComponentArea) \ + _(blockCount) \ + _(blocks) \ + +/// Calls your macro with the name of each member of XrWorldMeshBlockML, in order. +#define XR_LIST_STRUCT_XrWorldMeshBlockML(_) \ + _(type) \ + _(next) \ + _(uuid) \ + _(blockResult) \ + _(lod) \ + _(flags) \ + _(indexCount) \ + _(indexBuffer) \ + _(vertexCount) \ + _(vertexBuffer) \ + _(normalCount) \ + _(normalBuffer) \ + _(confidenceCount) \ + _(confidenceBuffer) \ + +/// Calls your macro with the name of each member of XrWorldMeshRequestCompletionInfoML, in order. +#define XR_LIST_STRUCT_XrWorldMeshRequestCompletionInfoML(_) \ + _(type) \ + _(next) \ + _(meshSpace) \ + _(meshSpaceLocateTime) \ + +/// Calls your macro with the name of each member of XrWorldMeshRequestCompletionML, in order. +#define XR_LIST_STRUCT_XrWorldMeshRequestCompletionML(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + _(blockCount) \ + _(blocks) \ + /// Calls your macro with the structure type name and the XrStructureType constant for @@ -4747,6 +5172,7 @@ XR_ENUM_STR(XrResult); XR_LIST_STRUCTURE_TYPES_CORE(_) \ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \ + XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_METAL(_) \ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \ @@ -4962,6 +5388,22 @@ XR_ENUM_STR(XrResult); _(XrMapLocalizationRequestInfoML, XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML) \ _(XrLocalizationMapImportInfoML, XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML) \ _(XrLocalizationEnableEventsInfoML, XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML) \ + _(XrSpatialAnchorsCreateInfoFromPoseML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML) \ + _(XrCreateSpatialAnchorsCompletionML, XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML) \ + _(XrSpatialAnchorStateML, XR_TYPE_SPATIAL_ANCHOR_STATE_ML) \ + _(XrSpatialAnchorsCreateStorageInfoML, XR_TYPE_SPATIAL_ANCHORS_CREATE_STORAGE_INFO_ML) \ + _(XrSpatialAnchorsQueryInfoRadiusML, XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML) \ + _(XrSpatialAnchorsQueryCompletionML, XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML) \ + _(XrSpatialAnchorsCreateInfoFromUuidsML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_UUIDS_ML) \ + _(XrSpatialAnchorsPublishInfoML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_INFO_ML) \ + _(XrSpatialAnchorsPublishCompletionML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML) \ + _(XrSpatialAnchorsDeleteInfoML, XR_TYPE_SPATIAL_ANCHORS_DELETE_INFO_ML) \ + _(XrSpatialAnchorsDeleteCompletionML, XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML) \ + _(XrSpatialAnchorsUpdateExpirationInfoML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_INFO_ML) \ + _(XrSpatialAnchorsUpdateExpirationCompletionML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML) \ + _(XrSpatialAnchorsPublishCompletionDetailsML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_DETAILS_ML) \ + _(XrSpatialAnchorsDeleteCompletionDetailsML, XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_DETAILS_ML) \ + _(XrSpatialAnchorsUpdateExpirationCompletionDetailsML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_DETAILS_ML) \ _(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \ _(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \ _(XrSceneMarkersMSFT, XR_TYPE_SCENE_MARKERS_MSFT) \ @@ -5061,6 +5503,11 @@ XR_ENUM_STR(XrResult); _(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \ _(XrSystemAnchorPropertiesHTC, XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC) \ _(XrSpatialAnchorCreateInfoHTC, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC) \ + _(XrSystemBodyTrackingPropertiesHTC, XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_HTC) \ + _(XrBodyTrackerCreateInfoHTC, XR_TYPE_BODY_TRACKER_CREATE_INFO_HTC) \ + _(XrBodyJointsLocateInfoHTC, XR_TYPE_BODY_JOINTS_LOCATE_INFO_HTC) \ + _(XrBodyJointLocationsHTC, XR_TYPE_BODY_JOINT_LOCATIONS_HTC) \ + _(XrBodySkeletonHTC, XR_TYPE_BODY_SKELETON_HTC) \ _(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \ _(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \ _(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \ @@ -5082,6 +5529,19 @@ XR_ENUM_STR(XrResult); _(XrEventDataHeadsetFitChangedML, XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML) \ _(XrEventDataEyeCalibrationChangedML, XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML) \ _(XrUserCalibrationEnableEventsInfoML, XR_TYPE_USER_CALIBRATION_ENABLE_EVENTS_INFO_ML) \ + _(XrSystemNotificationsSetInfoML, XR_TYPE_SYSTEM_NOTIFICATIONS_SET_INFO_ML) \ + _(XrWorldMeshDetectorCreateInfoML, XR_TYPE_WORLD_MESH_DETECTOR_CREATE_INFO_ML) \ + _(XrWorldMeshBlockStateML, XR_TYPE_WORLD_MESH_BLOCK_STATE_ML) \ + _(XrWorldMeshStateRequestInfoML, XR_TYPE_WORLD_MESH_STATE_REQUEST_INFO_ML) \ + _(XrWorldMeshStateRequestCompletionML, XR_TYPE_WORLD_MESH_STATE_REQUEST_COMPLETION_ML) \ + _(XrWorldMeshBufferRecommendedSizeInfoML, XR_TYPE_WORLD_MESH_BUFFER_RECOMMENDED_SIZE_INFO_ML) \ + _(XrWorldMeshBufferSizeML, XR_TYPE_WORLD_MESH_BUFFER_SIZE_ML) \ + _(XrWorldMeshBufferML, XR_TYPE_WORLD_MESH_BUFFER_ML) \ + _(XrWorldMeshBlockRequestML, XR_TYPE_WORLD_MESH_BLOCK_REQUEST_ML) \ + _(XrWorldMeshGetInfoML, XR_TYPE_WORLD_MESH_GET_INFO_ML) \ + _(XrWorldMeshBlockML, XR_TYPE_WORLD_MESH_BLOCK_ML) \ + _(XrWorldMeshRequestCompletionInfoML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML) \ + _(XrWorldMeshRequestCompletionML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML) \ #if defined(XR_USE_GRAPHICS_API_D3D11) @@ -5108,6 +5568,18 @@ XR_ENUM_STR(XrResult); #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) #endif +#if defined(XR_USE_GRAPHICS_API_METAL) +/// Implementation detail of XR_LIST_STRUCTURE_TYPES() +/// Structure types available only when XR_USE_GRAPHICS_API_METAL is defined +#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_METAL(_) \ + _(XrGraphicsBindingMetalKHR, XR_TYPE_GRAPHICS_BINDING_METAL_KHR) \ + _(XrSwapchainImageMetalKHR, XR_TYPE_SWAPCHAIN_IMAGE_METAL_KHR) \ + _(XrGraphicsRequirementsMetalKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_METAL_KHR) \ + +#else +#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_METAL(_) +#endif + #if defined(XR_USE_GRAPHICS_API_OPENGL) /// Implementation detail of XR_LIST_STRUCTURE_TYPES() /// Structure types available only when XR_USE_GRAPHICS_API_OPENGL is defined @@ -5264,6 +5736,7 @@ XR_ENUM_STR(XrResult); _(XR_KHR_vulkan_enable, 26) \ _(XR_KHR_D3D11_enable, 28) \ _(XR_KHR_D3D12_enable, 29) \ + _(XR_KHR_metal_enable, 30) \ _(XR_EXT_eye_gaze_interaction, 31) \ _(XR_KHR_visibility_mask, 32) \ _(XR_EXTX_overlay, 34) \ @@ -5340,6 +5813,8 @@ XR_ENUM_STR(XrResult); _(XR_ML_compat, 138) \ _(XR_ML_marker_understanding, 139) \ _(XR_ML_localization_map, 140) \ + _(XR_ML_spatial_anchors, 141) \ + _(XR_ML_spatial_anchors_storage, 142) \ _(XR_MSFT_spatial_anchor_persistence, 143) \ _(XR_MSFT_scene_marker, 148) \ _(XR_ULTRALEAP_hand_tracking_forearm, 150) \ @@ -5390,6 +5865,7 @@ XR_ENUM_STR(XrResult); _(XR_HTC_passthrough, 318) \ _(XR_HTC_foveation, 319) \ _(XR_HTC_anchor, 320) \ + _(XR_HTC_body_tracking, 321) \ _(XR_EXT_active_action_set_priority, 374) \ _(XR_MNDX_force_feedback_curl, 376) \ _(XR_BD_controller_interaction, 385) \ @@ -5401,6 +5877,9 @@ XR_ENUM_STR(XrResult); _(XR_EXT_user_presence, 471) \ _(XR_KHR_locate_spaces, 472) \ _(XR_ML_user_calibration, 473) \ + _(XR_ML_system_notifications, 474) \ + _(XR_ML_world_mesh_detection, 475) \ + _(XR_ML_view_configuration_depth_range_change, 484) \ _(XR_YVR_controller_interaction, 498) \ _(XR_EXT_composition_layer_inverted_alpha, 555) \ _(XR_KHR_maintenance1, 711) \ @@ -5546,6 +6025,14 @@ XR_ENUM_STR(XrResult); _(GetD3D12GraphicsRequirementsKHR, KHR_D3D12_enable) \ +/// For every function defined by XR_KHR_metal_enable in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_KHR_metal_enable(_) \ + _(GetMetalGraphicsRequirementsKHR, KHR_metal_enable) \ + + /// For every function defined by XR_KHR_visibility_mask in this version of the spec, /// calls your macro with the function name and extension name. /// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, @@ -5932,6 +6419,33 @@ XR_ENUM_STR(XrResult); _(GetExportedLocalizationMapDataML, ML_localization_map) \ +/// For every function defined by XR_ML_spatial_anchors in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_ML_spatial_anchors(_) \ + _(CreateSpatialAnchorsAsyncML, ML_spatial_anchors) \ + _(CreateSpatialAnchorsCompleteML, ML_spatial_anchors) \ + _(GetSpatialAnchorStateML, ML_spatial_anchors) \ + + +/// For every function defined by XR_ML_spatial_anchors_storage in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_ML_spatial_anchors_storage(_) \ + _(CreateSpatialAnchorsStorageML, ML_spatial_anchors_storage) \ + _(DestroySpatialAnchorsStorageML, ML_spatial_anchors_storage) \ + _(QuerySpatialAnchorsAsyncML, ML_spatial_anchors_storage) \ + _(QuerySpatialAnchorsCompleteML, ML_spatial_anchors_storage) \ + _(PublishSpatialAnchorsAsyncML, ML_spatial_anchors_storage) \ + _(PublishSpatialAnchorsCompleteML, ML_spatial_anchors_storage) \ + _(DeleteSpatialAnchorsAsyncML, ML_spatial_anchors_storage) \ + _(DeleteSpatialAnchorsCompleteML, ML_spatial_anchors_storage) \ + _(UpdateSpatialAnchorsExpirationAsyncML, ML_spatial_anchors_storage) \ + _(UpdateSpatialAnchorsExpirationCompleteML, ML_spatial_anchors_storage) \ + + /// For every function defined by XR_MSFT_spatial_anchor_persistence in this version of the spec, /// calls your macro with the function name and extension name. /// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, @@ -6220,6 +6734,17 @@ XR_ENUM_STR(XrResult); _(GetSpatialAnchorNameHTC, HTC_anchor) \ +/// For every function defined by XR_HTC_body_tracking in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_HTC_body_tracking(_) \ + _(CreateBodyTrackerHTC, HTC_body_tracking) \ + _(DestroyBodyTrackerHTC, HTC_body_tracking) \ + _(LocateBodyJointsHTC, HTC_body_tracking) \ + _(GetBodySkeletonHTC, HTC_body_tracking) \ + + /// For every function defined by XR_MNDX_force_feedback_curl in this version of the spec, /// calls your macro with the function name and extension name. /// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, @@ -6258,6 +6783,30 @@ XR_ENUM_STR(XrResult); _(EnableUserCalibrationEventsML, ML_user_calibration) \ +/// For every function defined by XR_ML_system_notifications in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_ML_system_notifications(_) \ + _(SetSystemNotificationsML, ML_system_notifications) \ + + +/// For every function defined by XR_ML_world_mesh_detection in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_ML_world_mesh_detection(_) \ + _(CreateWorldMeshDetectorML, ML_world_mesh_detection) \ + _(DestroyWorldMeshDetectorML, ML_world_mesh_detection) \ + _(RequestWorldMeshStateAsyncML, ML_world_mesh_detection) \ + _(RequestWorldMeshStateCompleteML, ML_world_mesh_detection) \ + _(GetWorldMeshBufferRecommendSizeML, ML_world_mesh_detection) \ + _(AllocateWorldMeshBufferML, ML_world_mesh_detection) \ + _(FreeWorldMeshBufferML, ML_world_mesh_detection) \ + _(RequestWorldMeshAsyncML, ML_world_mesh_detection) \ + _(RequestWorldMeshCompleteML, ML_world_mesh_detection) \ + + #endif diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h index 50466abc1b..bffab47cc5 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h @@ -238,6 +238,53 @@ This file contains expansion macros (X Macros) for OpenXR structures that have a +/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpatialAnchorsCreateInfoBaseHeaderML +#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML(_avail, _unavail) \ + _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML_CORE(_avail, _unavail) \ + + +// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML() +#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML_CORE(_avail, _unavail) \ + _avail(XrSpatialAnchorsCreateInfoFromPoseML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML) \ + _avail(XrSpatialAnchorsCreateInfoFromUuidsML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_UUIDS_ML) \ + + + + + +/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrFutureCompletionBaseHeaderEXT +#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT(_avail, _unavail) \ + _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT_CORE(_avail, _unavail) \ + + +// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT() +#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT_CORE(_avail, _unavail) \ + _avail(XrCreateSpatialAnchorsCompletionML, XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML) \ + _avail(XrSpatialAnchorsQueryCompletionML, XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML) \ + _avail(XrSpatialAnchorsPublishCompletionML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML) \ + _avail(XrSpatialAnchorsDeleteCompletionML, XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML) \ + _avail(XrSpatialAnchorsUpdateExpirationCompletionML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML) \ + _avail(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \ + _avail(XrWorldMeshStateRequestCompletionML, XR_TYPE_WORLD_MESH_STATE_REQUEST_COMPLETION_ML) \ + _avail(XrWorldMeshRequestCompletionML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML) \ + + + + + +/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpatialAnchorsQueryInfoBaseHeaderML +#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML(_avail, _unavail) \ + _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML_CORE(_avail, _unavail) \ + + +// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML() +#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML_CORE(_avail, _unavail) \ + _avail(XrSpatialAnchorsQueryInfoRadiusML, XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML) \ + + + + + /// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpaceQueryInfoBaseHeaderFB #define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB(_avail, _unavail) \ _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB_CORE(_avail, _unavail) \ @@ -265,18 +312,5 @@ This file contains expansion macros (X Macros) for OpenXR structures that have a -/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrFutureCompletionBaseHeaderEXT -#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT(_avail, _unavail) \ - _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT_CORE(_avail, _unavail) \ - - -// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT() -#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT_CORE(_avail, _unavail) \ - _avail(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \ - - - - - #endif diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h index e87e55b560..b1ab8e7779 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection_structs.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h @@ -27,6 +27,7 @@ This file contains expansion macros (X Macros) for OpenXR structures. _impl_XR_LIST_ALL_STRUCTURE_TYPES_CORE(_avail, _unavail) \ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \ + _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_METAL(_avail, _unavail) \ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_avail, _unavail) \ _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_avail, _unavail) \ @@ -242,6 +243,22 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrMapLocalizationRequestInfoML, XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML) \ _avail(XrLocalizationMapImportInfoML, XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML) \ _avail(XrLocalizationEnableEventsInfoML, XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML) \ + _avail(XrSpatialAnchorsCreateInfoFromPoseML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML) \ + _avail(XrCreateSpatialAnchorsCompletionML, XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML) \ + _avail(XrSpatialAnchorStateML, XR_TYPE_SPATIAL_ANCHOR_STATE_ML) \ + _avail(XrSpatialAnchorsCreateStorageInfoML, XR_TYPE_SPATIAL_ANCHORS_CREATE_STORAGE_INFO_ML) \ + _avail(XrSpatialAnchorsQueryInfoRadiusML, XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML) \ + _avail(XrSpatialAnchorsQueryCompletionML, XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML) \ + _avail(XrSpatialAnchorsCreateInfoFromUuidsML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_UUIDS_ML) \ + _avail(XrSpatialAnchorsPublishInfoML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_INFO_ML) \ + _avail(XrSpatialAnchorsPublishCompletionML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML) \ + _avail(XrSpatialAnchorsDeleteInfoML, XR_TYPE_SPATIAL_ANCHORS_DELETE_INFO_ML) \ + _avail(XrSpatialAnchorsDeleteCompletionML, XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML) \ + _avail(XrSpatialAnchorsUpdateExpirationInfoML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_INFO_ML) \ + _avail(XrSpatialAnchorsUpdateExpirationCompletionML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML) \ + _avail(XrSpatialAnchorsPublishCompletionDetailsML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_DETAILS_ML) \ + _avail(XrSpatialAnchorsDeleteCompletionDetailsML, XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_DETAILS_ML) \ + _avail(XrSpatialAnchorsUpdateExpirationCompletionDetailsML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_DETAILS_ML) \ _avail(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \ _avail(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \ _avail(XrSceneMarkersMSFT, XR_TYPE_SCENE_MARKERS_MSFT) \ @@ -341,6 +358,11 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \ _avail(XrSystemAnchorPropertiesHTC, XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC) \ _avail(XrSpatialAnchorCreateInfoHTC, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC) \ + _avail(XrSystemBodyTrackingPropertiesHTC, XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_HTC) \ + _avail(XrBodyTrackerCreateInfoHTC, XR_TYPE_BODY_TRACKER_CREATE_INFO_HTC) \ + _avail(XrBodyJointsLocateInfoHTC, XR_TYPE_BODY_JOINTS_LOCATE_INFO_HTC) \ + _avail(XrBodyJointLocationsHTC, XR_TYPE_BODY_JOINT_LOCATIONS_HTC) \ + _avail(XrBodySkeletonHTC, XR_TYPE_BODY_SKELETON_HTC) \ _avail(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \ _avail(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \ _avail(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \ @@ -362,6 +384,19 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrEventDataHeadsetFitChangedML, XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML) \ _avail(XrEventDataEyeCalibrationChangedML, XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML) \ _avail(XrUserCalibrationEnableEventsInfoML, XR_TYPE_USER_CALIBRATION_ENABLE_EVENTS_INFO_ML) \ + _avail(XrSystemNotificationsSetInfoML, XR_TYPE_SYSTEM_NOTIFICATIONS_SET_INFO_ML) \ + _avail(XrWorldMeshDetectorCreateInfoML, XR_TYPE_WORLD_MESH_DETECTOR_CREATE_INFO_ML) \ + _avail(XrWorldMeshBlockStateML, XR_TYPE_WORLD_MESH_BLOCK_STATE_ML) \ + _avail(XrWorldMeshStateRequestInfoML, XR_TYPE_WORLD_MESH_STATE_REQUEST_INFO_ML) \ + _avail(XrWorldMeshStateRequestCompletionML, XR_TYPE_WORLD_MESH_STATE_REQUEST_COMPLETION_ML) \ + _avail(XrWorldMeshBufferRecommendedSizeInfoML, XR_TYPE_WORLD_MESH_BUFFER_RECOMMENDED_SIZE_INFO_ML) \ + _avail(XrWorldMeshBufferSizeML, XR_TYPE_WORLD_MESH_BUFFER_SIZE_ML) \ + _avail(XrWorldMeshBufferML, XR_TYPE_WORLD_MESH_BUFFER_ML) \ + _avail(XrWorldMeshBlockRequestML, XR_TYPE_WORLD_MESH_BLOCK_REQUEST_ML) \ + _avail(XrWorldMeshGetInfoML, XR_TYPE_WORLD_MESH_GET_INFO_ML) \ + _avail(XrWorldMeshBlockML, XR_TYPE_WORLD_MESH_BLOCK_ML) \ + _avail(XrWorldMeshRequestCompletionInfoML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML) \ + _avail(XrWorldMeshRequestCompletionML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML) \ #if defined(XR_USE_GRAPHICS_API_D3D11) @@ -392,6 +427,20 @@ This file contains expansion macros (X Macros) for OpenXR structures. #endif +#if defined(XR_USE_GRAPHICS_API_METAL) +#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_METAL(_avail, _unavail) \ + _avail(XrGraphicsBindingMetalKHR, XR_TYPE_GRAPHICS_BINDING_METAL_KHR) \ + _avail(XrSwapchainImageMetalKHR, XR_TYPE_SWAPCHAIN_IMAGE_METAL_KHR) \ + _avail(XrGraphicsRequirementsMetalKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_METAL_KHR) \ + +#else +#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_METAL(_avail, _unavail) \ + _unavail(XrGraphicsBindingMetalKHR, XR_TYPE_GRAPHICS_BINDING_METAL_KHR) \ + _unavail(XrSwapchainImageMetalKHR, XR_TYPE_SWAPCHAIN_IMAGE_METAL_KHR) \ + _unavail(XrGraphicsRequirementsMetalKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_METAL_KHR) \ + +#endif + #if defined(XR_USE_GRAPHICS_API_OPENGL) #define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \ _avail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \ diff --git a/thirdparty/openxr/src/common/platform_utils.hpp b/thirdparty/openxr/src/common/platform_utils.hpp index d047c17d9d..19cd41cbb2 100644 --- a/thirdparty/openxr/src/common/platform_utils.hpp +++ b/thirdparty/openxr/src/common/platform_utils.hpp @@ -91,21 +91,22 @@ namespace detail { static inline char* ImplGetEnv(const char* name) { return getenv(name); } +// clang-format off static inline char* ImplGetSecureEnv(const char* name) { #ifdef HAVE_SECURE_GETENV return secure_getenv(name); #elif defined(HAVE___SECURE_GETENV) return __secure_getenv(name); #else -// clang-format off #pragma message( \ "Warning: Falling back to non-secure getenv for environmental" \ "lookups! Consider updating to a different libc.") - // clang-format on return ImplGetEnv(name); #endif } +// clang-format on + } // namespace detail #endif // defined(XR_OS_LINUX) || defined(XR_OS_APPLE) diff --git a/thirdparty/openxr/src/common/xr_linear.h b/thirdparty/openxr/src/common/xr_linear.h index 2b295ed304..cc525d3357 100644 --- a/thirdparty/openxr/src/common/xr_linear.h +++ b/thirdparty/openxr/src/common/xr_linear.h @@ -134,7 +134,7 @@ static const XrColor4f XrColorCyan = {0.0f, 1.0f, 1.0f, 1.0f}; static const XrColor4f XrColorLightGrey = {0.7f, 0.7f, 0.7f, 1.0f}; static const XrColor4f XrColorDarkGrey = {0.3f, 0.3f, 0.3f, 1.0f}; -typedef enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D } GraphicsAPI; +typedef enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D, GRAPHICS_METAL } GraphicsAPI; // Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience. typedef struct XrMatrix4x4f { diff --git a/thirdparty/openxr/src/loader/android_utilities.cpp b/thirdparty/openxr/src/loader/android_utilities.cpp index 5c9b846b5a..1f7424b8e6 100644 --- a/thirdparty/openxr/src/loader/android_utilities.cpp +++ b/thirdparty/openxr/src/loader/android_utilities.cpp @@ -15,6 +15,7 @@ #include <openxr/openxr.h> +#include <dlfcn.h> #include <sstream> #include <vector> #include <android/log.h> @@ -82,7 +83,6 @@ static Uri makeContentUri(bool systemBroker, int majorVersion, const char *abi) .appendPath(abi) .appendPath(RUNTIMES_PATH) .appendPath(TABLE_PATH); - ContentUris::appendId(builder, 0); return builder.build(); } @@ -175,7 +175,6 @@ static inline jni::Array<std::string> makeArray(std::initializer_list<const char } return ret; } -static constexpr auto TAG = "OpenXR-Loader"; #if defined(__arm__) static constexpr auto ABI = "armeabi-v7l"; @@ -313,26 +312,41 @@ int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &conte cursor.moveToFirst(); - auto filename = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::SO_FILENAME)); - auto libDir = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::NATIVE_LIB_DIR)); - auto packageName = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::PACKAGE_NAME)); - - auto hasFunctions = cursor.getInt(cursor.getColumnIndex(active_runtime::Columns::HAS_FUNCTIONS)) == 1; - __android_log_print(ANDROID_LOG_INFO, TAG, "Got runtime: package: %s, so filename: %s, native lib dir: %s, has functions: %s", - packageName.c_str(), filename.c_str(), libDir.c_str(), (hasFunctions ? "yes" : "no")); + do { + auto filename = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::SO_FILENAME)); + auto libDir = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::NATIVE_LIB_DIR)); + auto packageName = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::PACKAGE_NAME)); + + auto hasFunctions = cursor.getInt(cursor.getColumnIndex(active_runtime::Columns::HAS_FUNCTIONS)) == 1; + ALOGI("Got runtime: package: %s, so filename: %s, native lib dir: %s, has functions: %s", packageName.c_str(), + filename.c_str(), libDir.c_str(), (hasFunctions ? "yes" : "no")); + + auto lib_path = libDir + "/" + filename; + auto *lib = dlopen(lib_path.c_str(), RTLD_LAZY | RTLD_LOCAL); + if (lib) { + // we found a runtime that we can dlopen, use it. + dlclose(lib); + + JsonManifestBuilder builder{"runtime", lib_path}; + if (hasFunctions) { + int result = populateFunctions(context, systemBroker, packageName, builder); + if (result != 0) { + ALOGW("Unable to populate functions from runtime: %s, checking for more records...", lib_path.c_str()); + continue; + } + } + virtualManifest = builder.build(); + cursor.close(); + return 0; + } + // this runtime was not accessible, see if the broker has more runtimes on + // offer. + ALOGV("Unable to open broker provided runtime at %s, checking for more records...", lib_path.c_str()); + } while (cursor.moveToNext()); - auto lib_path = libDir + "/" + filename; + ALOGE("Unable to open any of the broker provided runtimes."); cursor.close(); - - JsonManifestBuilder builder{"runtime", lib_path}; - if (hasFunctions) { - int result = populateFunctions(context, systemBroker, packageName, builder); - if (result != 0) { - return result; - } - } - virtualManifest = builder.build(); - return 0; + return -1; } } // namespace openxr_android diff --git a/thirdparty/openxr/src/loader/loader_core.cpp b/thirdparty/openxr/src/loader/loader_core.cpp index 8bf2609a08..a0d81b28dc 100644 --- a/thirdparty/openxr/src/loader/loader_core.cpp +++ b/thirdparty/openxr/src/loader/loader_core.cpp @@ -334,7 +334,7 @@ static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrDestroyInstance(XrInstance instanc return result; } - const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + const std::unique_ptr<XrGeneratedDispatchTableCore> &dispatch_table = loader_instance->DispatchTable(); // If we allocated a default debug utils messenger, free it XrDebugUtilsMessengerEXT messenger = loader_instance->DefaultDebugUtilsMessenger(); @@ -546,7 +546,7 @@ LoaderTrampolineSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const Xr return result; } LoaderLogger::GetInstance().BeginLabelRegion(session, labelInfo); - const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + const std::unique_ptr<XrGeneratedDispatchTableCore> &dispatch_table = loader_instance->DispatchTable(); if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) { return dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo); } @@ -567,7 +567,7 @@ static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineSessionEndDebugUtilsLabelR } LoaderLogger::GetInstance().EndLabelRegion(session); - const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + const std::unique_ptr<XrGeneratedDispatchTableCore> &dispatch_table = loader_instance->DispatchTable(); if (nullptr != dispatch_table->SessionEndDebugUtilsLabelRegionEXT) { return dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session); } @@ -597,7 +597,7 @@ LoaderTrampolineSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebug LoaderLogger::GetInstance().InsertLabel(session, labelInfo); - const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + const std::unique_ptr<XrGeneratedDispatchTableCore> &dispatch_table = loader_instance->DispatchTable(); if (nullptr != dispatch_table->SessionInsertDebugUtilsLabelEXT) { return dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo); } @@ -643,7 +643,7 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstan "xrCreateDebugUtilsMessengerEXT", "invalid messenger pointer"); return XR_ERROR_VALIDATION_FAILURE; } - const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance); + const XrGeneratedDispatchTableCore *dispatch_table = RuntimeInterface::GetDispatchTable(instance); XrResult result = XR_SUCCESS; // This extension is supported entirely by the loader which means the runtime may or may not support it. if (nullptr != dispatch_table->CreateDebugUtilsMessengerEXT) { @@ -664,7 +664,7 @@ XRLOADER_ABI_CATCH_FALLBACK XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY { LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader terminator"); - const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger); + const XrGeneratedDispatchTableCore *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger); XrResult result = XR_SUCCESS; LoaderLogger::GetInstance().RemoveLogRecorder(MakeHandleGeneric(messenger)); RuntimeInterface::GetRuntime().ForgetDebugMessenger(messenger); @@ -684,7 +684,7 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT( XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes, const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY { LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Entering loader terminator"); - const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance); + const XrGeneratedDispatchTableCore *dispatch_table = RuntimeInterface::GetDispatchTable(instance); XrResult result = XR_SUCCESS; if (nullptr != dispatch_table->SubmitDebugUtilsMessageEXT) { result = dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData); @@ -701,7 +701,7 @@ XRLOADER_ABI_CATCH_FALLBACK XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY { LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Entering loader terminator"); - const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance); + const XrGeneratedDispatchTableCore *dispatch_table = RuntimeInterface::GetDispatchTable(instance); XrResult result = XR_SUCCESS; if (nullptr != dispatch_table->SetDebugUtilsObjectNameEXT) { result = dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo); diff --git a/thirdparty/openxr/src/loader/loader_instance.cpp b/thirdparty/openxr/src/loader/loader_instance.cpp index f18230087f..09521ecf47 100644 --- a/thirdparty/openxr/src/loader/loader_instance.cpp +++ b/thirdparty/openxr/src/loader/loader_instance.cpp @@ -278,12 +278,12 @@ LoaderInstance::LoaderInstance(XrInstance instance, const XrInstanceCreateInfo* : _runtime_instance(instance), _topmost_gipa(topmost_gipa), _api_layer_interfaces(std::move(api_layer_interfaces)), - _dispatch_table(new XrGeneratedDispatchTable{}) { + _dispatch_table(new XrGeneratedDispatchTableCore{}) { for (uint32_t ext = 0; ext < create_info->enabledExtensionCount; ++ext) { _enabled_extensions.push_back(create_info->enabledExtensionNames[ext]); } - GeneratedXrPopulateDispatchTable(_dispatch_table.get(), instance, topmost_gipa); + GeneratedXrPopulateDispatchTableCore(_dispatch_table.get(), instance, topmost_gipa); } LoaderInstance::~LoaderInstance() { diff --git a/thirdparty/openxr/src/loader/loader_instance.hpp b/thirdparty/openxr/src/loader/loader_instance.hpp index b99e6b047f..93cd5dc6a4 100644 --- a/thirdparty/openxr/src/loader/loader_instance.hpp +++ b/thirdparty/openxr/src/loader/loader_instance.hpp @@ -23,7 +23,7 @@ #include <vector> class ApiLayerInterface; -struct XrGeneratedDispatchTable; +struct XrGeneratedDispatchTableCore; class LoaderInstance; // Manage the single loader instance that is available. @@ -54,7 +54,7 @@ class LoaderInstance { virtual ~LoaderInstance(); XrInstance GetInstanceHandle() { return _runtime_instance; } - const std::unique_ptr<XrGeneratedDispatchTable>& DispatchTable() { return _dispatch_table; } + const std::unique_ptr<XrGeneratedDispatchTableCore>& DispatchTable() { return _dispatch_table; } std::vector<std::unique_ptr<ApiLayerInterface>>& LayerInterfaces() { return _api_layer_interfaces; } bool ExtensionIsEnabled(const std::string& extension); XrDebugUtilsMessengerEXT DefaultDebugUtilsMessenger() { return _messenger; } @@ -71,7 +71,7 @@ class LoaderInstance { std::vector<std::string> _enabled_extensions; std::vector<std::unique_ptr<ApiLayerInterface>> _api_layer_interfaces; - std::unique_ptr<XrGeneratedDispatchTable> _dispatch_table; + std::unique_ptr<XrGeneratedDispatchTableCore> _dispatch_table; // Internal debug messenger created during xrCreateInstance XrDebugUtilsMessengerEXT _messenger{XR_NULL_HANDLE}; }; diff --git a/thirdparty/openxr/src/loader/manifest_file.cpp b/thirdparty/openxr/src/loader/manifest_file.cpp index 4e3e5b4947..ca212d3435 100644 --- a/thirdparty/openxr/src/loader/manifest_file.cpp +++ b/thirdparty/openxr/src/loader/manifest_file.cpp @@ -75,11 +75,12 @@ static inline bool StringEndsWith(const std::string &value, const std::string &e } // If the file found is a manifest file name, add it to the out_files manifest list. -static void AddIfJson(const std::string &full_file, std::vector<std::string> &manifest_files) { +static bool AddIfJson(const std::string &full_file, std::vector<std::string> &manifest_files) { if (full_file.empty() || !StringEndsWith(full_file, ".json")) { - return; + return false; } manifest_files.push_back(full_file); + return true; } // Check the current path for any manifest files. If the provided search_path is a directory, look for @@ -381,7 +382,6 @@ static void ReadRuntimeDataFilesInRegistry(const std::string &runtime_registry_l if (ERROR_SUCCESS != open_value) { LoaderLogger::LogWarningMessage("", "ReadRuntimeDataFilesInRegistry - failed to open registry key " + full_registry_location); - return; } @@ -391,7 +391,23 @@ static void ReadRuntimeDataFilesInRegistry(const std::string &runtime_registry_l LoaderLogger::LogWarningMessage( "", "ReadRuntimeDataFilesInRegistry - failed to read registry value " + default_runtime_value_name); } else { - AddFilesInPath(wide_to_utf8(value_w), false, manifest_files); + // Not using AddFilesInPath here (as only api_layer manifest paths allow multiple + // separated paths) + // Small time-of-check vs time-of-use issue here but it mainly only affects the error message. + // It does not introduce a security defect. + std::string activeRuntimePath = wide_to_utf8(value_w); + if (FileSysUtilsIsRegularFile(activeRuntimePath)) { + // If the file exists, try to add it + std::string absolute_path; + FileSysUtilsGetAbsolutePath(activeRuntimePath, absolute_path); + if (!AddIfJson(absolute_path, manifest_files)) { + LoaderLogger::LogErrorMessage( + "", "ReadRuntimeDataFilesInRegistry - registry runtime path is not json " + activeRuntimePath); + } + } else { + LoaderLogger::LogErrorMessage( + "", "ReadRuntimeDataFilesInRegistry - registry runtime path does not exist " + activeRuntimePath); + } } RegCloseKey(hkey); @@ -757,8 +773,7 @@ void ApiLayerManifestFile::AddManifestFilesAndroid(const std::string &openxr_com } std::istringstream json_stream(std::string{buf, length}); - CreateIfValid(ManifestFileType::MANIFEST_TYPE_EXPLICIT_API_LAYER, filename, json_stream, - &ApiLayerManifestFile::LocateLibraryInAssets, manifest_files); + CreateIfValid(type, filename, json_stream, &ApiLayerManifestFile::LocateLibraryInAssets, manifest_files); } } #endif // defined(XR_USE_PLATFORM_ANDROID) && defined(XR_KHR_LOADER_INIT_SUPPORT) diff --git a/thirdparty/openxr/src/loader/runtime_interface.cpp b/thirdparty/openxr/src/loader/runtime_interface.cpp index a0296c738c..32feea6dde 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.cpp +++ b/thirdparty/openxr/src/loader/runtime_interface.cpp @@ -126,6 +126,10 @@ XrResult RuntimeInterface::TryLoadingSingleRuntime(const std::string& openxr_com XrResult res = XR_ERROR_RUNTIME_FAILURE; if (nullptr != negotiate) { res = negotiate(&loader_info, &runtime_info); + } else { + std::string error_message = "RuntimeInterface::LoadRuntime failed to find negotiate function "; + error_message += function_name; + LoaderLogger::LogErrorMessage(openxr_command, error_message); } // If we supposedly succeeded, but got a nullptr for GetInstanceProcAddr // then something still went wrong, so return with an error. @@ -270,8 +274,8 @@ XrResult RuntimeInterface::GetInstanceProcAddr(XrInstance instance, const char* return GetInstance()->_get_instance_proc_addr(instance, name, function); } -const XrGeneratedDispatchTable* RuntimeInterface::GetDispatchTable(XrInstance instance) { - XrGeneratedDispatchTable* table = nullptr; +const XrGeneratedDispatchTableCore* RuntimeInterface::GetDispatchTable(XrInstance instance) { + XrGeneratedDispatchTableCore* table = nullptr; std::lock_guard<std::mutex> mlock(GetInstance()->_dispatch_table_mutex); auto it = GetInstance()->_dispatch_table_map.find(instance); if (it != GetInstance()->_dispatch_table_map.end()) { @@ -280,7 +284,7 @@ const XrGeneratedDispatchTable* RuntimeInterface::GetDispatchTable(XrInstance in return table; } -const XrGeneratedDispatchTable* RuntimeInterface::GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger) { +const XrGeneratedDispatchTableCore* RuntimeInterface::GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger) { XrInstance runtime_instance = XR_NULL_HANDLE; { std::lock_guard<std::mutex> mlock(GetInstance()->_messenger_to_instance_mutex); @@ -349,8 +353,8 @@ XrResult RuntimeInterface::CreateInstance(const XrInstanceCreateInfo* info, XrIn res = rt_xrCreateInstance(info, instance); if (XR_SUCCEEDED(res)) { create_succeeded = true; - std::unique_ptr<XrGeneratedDispatchTable> dispatch_table(new XrGeneratedDispatchTable()); - GeneratedXrPopulateDispatchTable(dispatch_table.get(), *instance, _get_instance_proc_addr); + std::unique_ptr<XrGeneratedDispatchTableCore> dispatch_table(new XrGeneratedDispatchTableCore()); + GeneratedXrPopulateDispatchTableCore(dispatch_table.get(), *instance, _get_instance_proc_addr); std::lock_guard<std::mutex> mlock(_dispatch_table_mutex); _dispatch_table_map[*instance] = std::move(dispatch_table); } diff --git a/thirdparty/openxr/src/loader/runtime_interface.hpp b/thirdparty/openxr/src/loader/runtime_interface.hpp index 093f8ba767..3d45b12946 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.hpp +++ b/thirdparty/openxr/src/loader/runtime_interface.hpp @@ -24,7 +24,7 @@ class Value; } class RuntimeManifestFile; -struct XrGeneratedDispatchTable; +struct XrGeneratedDispatchTableCore; class RuntimeInterface { public: @@ -37,8 +37,8 @@ class RuntimeInterface { static XrResult GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function); // Get the direct dispatch table to this runtime, without API layers or loader terminators. - static const XrGeneratedDispatchTable* GetDispatchTable(XrInstance instance); - static const XrGeneratedDispatchTable* GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger); + static const XrGeneratedDispatchTableCore* GetDispatchTable(XrInstance instance); + static const XrGeneratedDispatchTableCore* GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger); void GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties); bool SupportsExtension(const std::string& extension_name); @@ -66,7 +66,7 @@ class RuntimeInterface { LoaderPlatformLibraryHandle _runtime_library; PFN_xrGetInstanceProcAddr _get_instance_proc_addr; - std::unordered_map<XrInstance, std::unique_ptr<XrGeneratedDispatchTable>> _dispatch_table_map; + std::unordered_map<XrInstance, std::unique_ptr<XrGeneratedDispatchTableCore>> _dispatch_table_map; std::mutex _dispatch_table_mutex; std::unordered_map<XrDebugUtilsMessengerEXT, XrInstance> _messenger_to_instance_map; std::mutex _messenger_to_instance_mutex; diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.cpp b/thirdparty/openxr/src/loader/xr_generated_loader.cpp index 7bddbdc3ea..d7f1ed18c1 100644 --- a/thirdparty/openxr/src/loader/xr_generated_loader.cpp +++ b/thirdparty/openxr/src/loader/xr_generated_loader.cpp @@ -697,4 +697,17 @@ extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback( } XRLOADER_ABI_CATCH_FALLBACK +extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpaces( + XrSession session, + const XrSpacesLocateInfo* locateInfo, + XrSpaceLocations* spaceLocations) XRLOADER_ABI_TRY { + LoaderInstance* loader_instance; + XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrLocateSpaces"); + if (XR_SUCCEEDED(result)) { + result = loader_instance->DispatchTable()->LocateSpaces(session, locateInfo, spaceLocations); + } + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.hpp b/thirdparty/openxr/src/loader/xr_generated_loader.hpp index 68a6b9470d..9a6c915421 100644 --- a/thirdparty/openxr/src/loader/xr_generated_loader.hpp +++ b/thirdparty/openxr/src/loader/xr_generated_loader.hpp @@ -245,6 +245,10 @@ extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback( extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback( XrSession session, const XrHapticActionInfo* hapticActionInfo); +extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpaces( + XrSession session, + const XrSpacesLocateInfo* locateInfo, + XrSpaceLocations* spaceLocations); #ifdef __cplusplus } // extern "C" #endif diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table_core.c b/thirdparty/openxr/src/xr_generated_dispatch_table_core.c index e73e8b2b95..aaf854704b 100644 --- a/thirdparty/openxr/src/xr_generated_dispatch_table_core.c +++ b/thirdparty/openxr/src/xr_generated_dispatch_table_core.c @@ -37,7 +37,7 @@ extern "C" { #endif // Helper function to populate an instance dispatch table -void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table, +void GeneratedXrPopulateDispatchTableCore(struct XrGeneratedDispatchTableCore *table, XrInstance instance, PFN_xrGetInstanceProcAddr get_inst_proc_addr) { @@ -96,6 +96,9 @@ void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table, (get_inst_proc_addr(instance, "xrApplyHapticFeedback", (PFN_xrVoidFunction*)&table->ApplyHapticFeedback)); (get_inst_proc_addr(instance, "xrStopHapticFeedback", (PFN_xrVoidFunction*)&table->StopHapticFeedback)); + // ---- Core 1.1 commands + (get_inst_proc_addr(instance, "xrLocateSpaces", (PFN_xrVoidFunction*)&table->LocateSpaces)); + // ---- XR_EXT_debug_utils extension commands (get_inst_proc_addr(instance, "xrSetDebugUtilsObjectNameEXT", (PFN_xrVoidFunction*)&table->SetDebugUtilsObjectNameEXT)); (get_inst_proc_addr(instance, "xrCreateDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->CreateDebugUtilsMessengerEXT)); diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table_core.h b/thirdparty/openxr/src/xr_generated_dispatch_table_core.h index 5871231267..69abf10b93 100644 --- a/thirdparty/openxr/src/xr_generated_dispatch_table_core.h +++ b/thirdparty/openxr/src/xr_generated_dispatch_table_core.h @@ -38,7 +38,7 @@ extern "C" { #endif // Generated dispatch table -struct XrGeneratedDispatchTable { +struct XrGeneratedDispatchTableCore { // ---- Core 1.0 commands PFN_xrGetInstanceProcAddr GetInstanceProcAddr; @@ -97,6 +97,9 @@ struct XrGeneratedDispatchTable { PFN_xrApplyHapticFeedback ApplyHapticFeedback; PFN_xrStopHapticFeedback StopHapticFeedback; + // ---- Core 1.1 commands + PFN_xrLocateSpaces LocateSpaces; + // ---- XR_EXT_debug_utils extension commands PFN_xrSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT; PFN_xrCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT; @@ -109,7 +112,7 @@ struct XrGeneratedDispatchTable { // Prototype for dispatch table helper function -void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table, +void GeneratedXrPopulateDispatchTableCore(struct XrGeneratedDispatchTableCore *table, XrInstance instance, PFN_xrGetInstanceProcAddr get_inst_proc_addr); diff --git a/thirdparty/squish/LICENSE.txt b/thirdparty/squish/LICENSE.txt deleted file mode 100644 index e491e36226..0000000000 --- a/thirdparty/squish/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/thirdparty/squish/alpha.cpp b/thirdparty/squish/alpha.cpp deleted file mode 100644 index 7039c1a3b8..0000000000 --- a/thirdparty/squish/alpha.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "alpha.h" - -#include <climits> -#include <algorithm> - -namespace squish { - -static int FloatToInt( float a, int limit ) -{ - // use ANSI round-to-zero behaviour to get round-to-nearest - int i = ( int )( a + 0.5f ); - - // clamp to the limit - if( i < 0 ) - i = 0; - else if( i > limit ) - i = limit; - - // done - return i; -} - -void CompressAlphaDxt3( u8 const* rgba, int mask, void* block ) -{ - u8* bytes = reinterpret_cast< u8* >( block ); - - // quantise and pack the alpha values pairwise - for( int i = 0; i < 8; ++i ) - { - // quantise down to 4 bits - float alpha1 = ( float )rgba[8*i + 3] * ( 15.0f/255.0f ); - float alpha2 = ( float )rgba[8*i + 7] * ( 15.0f/255.0f ); - int quant1 = FloatToInt( alpha1, 15 ); - int quant2 = FloatToInt( alpha2, 15 ); - - // set alpha to zero where masked - int bit1 = 1 << ( 2*i ); - int bit2 = 1 << ( 2*i + 1 ); - if( ( mask & bit1 ) == 0 ) - quant1 = 0; - if( ( mask & bit2 ) == 0 ) - quant2 = 0; - - // pack into the byte - bytes[i] = ( u8 )( quant1 | ( quant2 << 4 ) ); - } -} - -void DecompressAlphaDxt3( u8* rgba, void const* block ) -{ - u8 const* bytes = reinterpret_cast< u8 const* >( block ); - - // unpack the alpha values pairwise - for( int i = 0; i < 8; ++i ) - { - // quantise down to 4 bits - u8 quant = bytes[i]; - - // unpack the values - u8 lo = quant & 0x0f; - u8 hi = quant & 0xf0; - - // convert back up to bytes - rgba[8*i + 3] = lo | ( lo << 4 ); - rgba[8*i + 7] = hi | ( hi >> 4 ); - } -} - -static void FixRange( int& min, int& max, int steps ) -{ - if( max - min < steps ) - max = std::min( min + steps, 255 ); - if( max - min < steps ) - min = std::max( 0, max - steps ); -} - -static int FitCodes( u8 const* rgba, int mask, u8 const* codes, u8* indices ) -{ - // fit each alpha value to the codebook - int err = 0; - for( int i = 0; i < 16; ++i ) - { - // check this pixel is valid - int bit = 1 << i; - if( ( mask & bit ) == 0 ) - { - // use the first code - indices[i] = 0; - continue; - } - - // find the least error and corresponding index - int value = rgba[4*i + 3]; - int least = INT_MAX; - int index = 0; - for( int j = 0; j < 8; ++j ) - { - // get the squared error from this code - int dist = ( int )value - ( int )codes[j]; - dist *= dist; - - // compare with the best so far - if( dist < least ) - { - least = dist; - index = j; - } - } - - // save this index and accumulate the error - indices[i] = ( u8 )index; - err += least; - } - - // return the total error - return err; -} - -static void WriteAlphaBlock( int alpha0, int alpha1, u8 const* indices, void* block ) -{ - u8* bytes = reinterpret_cast< u8* >( block ); - - // write the first two bytes - bytes[0] = ( u8 )alpha0; - bytes[1] = ( u8 )alpha1; - - // pack the indices with 3 bits each - u8* dest = bytes + 2; - u8 const* src = indices; - for( int i = 0; i < 2; ++i ) - { - // pack 8 3-bit values - int value = 0; - for( int j = 0; j < 8; ++j ) - { - int index = *src++; - value |= ( index << 3*j ); - } - - // store in 3 bytes - for( int j = 0; j < 3; ++j ) - { - int byte = ( value >> 8*j ) & 0xff; - *dest++ = ( u8 )byte; - } - } -} - -static void WriteAlphaBlock5( int alpha0, int alpha1, u8 const* indices, void* block ) -{ - // check the relative values of the endpoints - if( alpha0 > alpha1 ) - { - // swap the indices - u8 swapped[16]; - for( int i = 0; i < 16; ++i ) - { - u8 index = indices[i]; - if( index == 0 ) - swapped[i] = 1; - else if( index == 1 ) - swapped[i] = 0; - else if( index <= 5 ) - swapped[i] = 7 - index; - else - swapped[i] = index; - } - - // write the block - WriteAlphaBlock( alpha1, alpha0, swapped, block ); - } - else - { - // write the block - WriteAlphaBlock( alpha0, alpha1, indices, block ); - } -} - -static void WriteAlphaBlock7( int alpha0, int alpha1, u8 const* indices, void* block ) -{ - // check the relative values of the endpoints - if( alpha0 < alpha1 ) - { - // swap the indices - u8 swapped[16]; - for( int i = 0; i < 16; ++i ) - { - u8 index = indices[i]; - if( index == 0 ) - swapped[i] = 1; - else if( index == 1 ) - swapped[i] = 0; - else - swapped[i] = 9 - index; - } - - // write the block - WriteAlphaBlock( alpha1, alpha0, swapped, block ); - } - else - { - // write the block - WriteAlphaBlock( alpha0, alpha1, indices, block ); - } -} - -void CompressAlphaDxt5( u8 const* rgba, int mask, void* block ) -{ - // get the range for 5-alpha and 7-alpha interpolation - int min5 = 255; - int max5 = 0; - int min7 = 255; - int max7 = 0; - for( int i = 0; i < 16; ++i ) - { - // check this pixel is valid - int bit = 1 << i; - if( ( mask & bit ) == 0 ) - continue; - - // incorporate into the min/max - int value = rgba[4*i + 3]; - if( value < min7 ) - min7 = value; - if( value > max7 ) - max7 = value; - if( value != 0 && value < min5 ) - min5 = value; - if( value != 255 && value > max5 ) - max5 = value; - } - - // handle the case that no valid range was found - if( min5 > max5 ) - min5 = max5; - if( min7 > max7 ) - min7 = max7; - - // fix the range to be the minimum in each case - FixRange( min5, max5, 5 ); - FixRange( min7, max7, 7 ); - - // set up the 5-alpha code book - u8 codes5[8]; - codes5[0] = ( u8 )min5; - codes5[1] = ( u8 )max5; - for( int i = 1; i < 5; ++i ) - codes5[1 + i] = ( u8 )( ( ( 5 - i )*min5 + i*max5 )/5 ); - codes5[6] = 0; - codes5[7] = 255; - - // set up the 7-alpha code book - u8 codes7[8]; - codes7[0] = ( u8 )min7; - codes7[1] = ( u8 )max7; - for( int i = 1; i < 7; ++i ) - codes7[1 + i] = ( u8 )( ( ( 7 - i )*min7 + i*max7 )/7 ); - - // fit the data to both code books - u8 indices5[16]; - u8 indices7[16]; - int err5 = FitCodes( rgba, mask, codes5, indices5 ); - int err7 = FitCodes( rgba, mask, codes7, indices7 ); - - // save the block with least error - if( err5 <= err7 ) - WriteAlphaBlock5( min5, max5, indices5, block ); - else - WriteAlphaBlock7( min7, max7, indices7, block ); -} - -void DecompressAlphaDxt5( u8* rgba, void const* block ) -{ - // get the two alpha values - u8 const* bytes = reinterpret_cast< u8 const* >( block ); - int alpha0 = bytes[0]; - int alpha1 = bytes[1]; - - // compare the values to build the codebook - u8 codes[8]; - codes[0] = ( u8 )alpha0; - codes[1] = ( u8 )alpha1; - if( alpha0 <= alpha1 ) - { - // use 5-alpha codebook - for( int i = 1; i < 5; ++i ) - codes[1 + i] = ( u8 )( ( ( 5 - i )*alpha0 + i*alpha1 )/5 ); - codes[6] = 0; - codes[7] = 255; - } - else - { - // use 7-alpha codebook - for( int i = 1; i < 7; ++i ) - codes[1 + i] = ( u8 )( ( ( 7 - i )*alpha0 + i*alpha1 )/7 ); - } - - // decode the indices - u8 indices[16]; - u8 const* src = bytes + 2; - u8* dest = indices; - for( int i = 0; i < 2; ++i ) - { - // grab 3 bytes - int value = 0; - for( int j = 0; j < 3; ++j ) - { - int byte = *src++; - value |= ( byte << 8*j ); - } - - // unpack 8 3-bit values from it - for( int j = 0; j < 8; ++j ) - { - int index = ( value >> 3*j ) & 0x7; - *dest++ = ( u8 )index; - } - } - - // write out the indexed codebook values - for( int i = 0; i < 16; ++i ) - rgba[4*i + 3] = codes[indices[i]]; -} - -} // namespace squish diff --git a/thirdparty/squish/alpha.h b/thirdparty/squish/alpha.h deleted file mode 100644 index a1fffd4049..0000000000 --- a/thirdparty/squish/alpha.h +++ /dev/null @@ -1,41 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_ALPHA_H -#define SQUISH_ALPHA_H - -#include "squish.h" - -namespace squish { - -void CompressAlphaDxt3( u8 const* rgba, int mask, void* block ); -void CompressAlphaDxt5( u8 const* rgba, int mask, void* block ); - -void DecompressAlphaDxt3( u8* rgba, void const* block ); -void DecompressAlphaDxt5( u8* rgba, void const* block ); - -} // namespace squish - -#endif // ndef SQUISH_ALPHA_H diff --git a/thirdparty/squish/clusterfit.cpp b/thirdparty/squish/clusterfit.cpp deleted file mode 100644 index 1610ecb5d8..0000000000 --- a/thirdparty/squish/clusterfit.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - Copyright (c) 2007 Ignacio Castano icastano@nvidia.com - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "clusterfit.h" -#include "colourset.h" -#include "colourblock.h" -#include <cfloat> - -namespace squish { - -ClusterFit::ClusterFit( ColourSet const* colours, int flags, float* metric ) - : ColourFit( colours, flags ) -{ - // set the iteration count - m_iterationCount = ( m_flags & kColourIterativeClusterFit ) ? kMaxIterations : 1; - - // initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f) - if( metric ) - m_metric = Vec4( metric[0], metric[1], metric[2], 1.0f ); - else - m_metric = VEC4_CONST( 1.0f ); - - // initialise the best error - m_besterror = VEC4_CONST( FLT_MAX ); - - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // get the covariance matrix - Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() ); - - // compute the principle component - m_principle = ComputePrincipleComponent( covariance ); -} - -bool ClusterFit::ConstructOrdering( Vec3 const& axis, int iteration ) -{ - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // build the list of dot products - float dps[16]; - u8* order = ( u8* )m_order + 16*iteration; - for( int i = 0; i < count; ++i ) - { - dps[i] = Dot( values[i], axis ); - order[i] = ( u8 )i; - } - - // stable sort using them - for( int i = 0; i < count; ++i ) - { - for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j ) - { - std::swap( dps[j], dps[j - 1] ); - std::swap( order[j], order[j - 1] ); - } - } - - // check this ordering is unique - for( int it = 0; it < iteration; ++it ) - { - u8 const* prev = ( u8* )m_order + 16*it; - bool same = true; - for( int i = 0; i < count; ++i ) - { - if( order[i] != prev[i] ) - { - same = false; - break; - } - } - if( same ) - return false; - } - - // copy the ordering and weight all the points - Vec3 const* unweighted = m_colours->GetPoints(); - float const* weights = m_colours->GetWeights(); - m_xsum_wsum = VEC4_CONST( 0.0f ); - for( int i = 0; i < count; ++i ) - { - int j = order[i]; - Vec4 p( unweighted[j].X(), unweighted[j].Y(), unweighted[j].Z(), 1.0f ); - Vec4 w( weights[j] ); - Vec4 x = p*w; - m_points_weights[i] = x; - m_xsum_wsum += x; - } - return true; -} - -void ClusterFit::Compress3( void* block ) -{ - // declare variables - int const count = m_colours->GetCount(); - Vec4 const two = VEC4_CONST( 2.0 ); - Vec4 const one = VEC4_CONST( 1.0f ); - Vec4 const half_half2( 0.5f, 0.5f, 0.5f, 0.25f ); - Vec4 const zero = VEC4_CONST( 0.0f ); - Vec4 const half = VEC4_CONST( 0.5f ); - Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); - Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); - - // prepare an ordering using the principle axis - ConstructOrdering( m_principle, 0 ); - - // check all possible clusters and iterate on the total order - Vec4 beststart = VEC4_CONST( 0.0f ); - Vec4 bestend = VEC4_CONST( 0.0f ); - Vec4 besterror = m_besterror; - u8 bestindices[16]; - int bestiteration = 0; - int besti = 0, bestj = 0; - - // loop over iterations (we avoid the case that all points in first or last cluster) - for( int iterationIndex = 0;; ) - { - // first cluster [0,i) is at the start - Vec4 part0 = VEC4_CONST( 0.0f ); - for( int i = 0; i < count; ++i ) - { - // second cluster [i,j) is half along - Vec4 part1 = ( i == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f ); - int jmin = ( i == 0 ) ? 1 : i; - for( int j = jmin;; ) - { - // last cluster [j,count) is at the end - Vec4 part2 = m_xsum_wsum - part1 - part0; - - // compute least squares terms directly - Vec4 alphax_sum = MultiplyAdd( part1, half_half2, part0 ); - Vec4 alpha2_sum = alphax_sum.SplatW(); - - Vec4 betax_sum = MultiplyAdd( part1, half_half2, part2 ); - Vec4 beta2_sum = betax_sum.SplatW(); - - Vec4 alphabeta_sum = ( part1*half_half2 ).SplatW(); - - // compute the least-squares optimal points - Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) ); - Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor; - Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor; - - // clamp to the grid - a = Min( one, Max( zero, a ) ); - b = Min( one, Max( zero, b ) ); - a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp; - b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp; - - // compute the error (we skip the constant xxsum) - Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); - Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); - Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); - Vec4 e4 = MultiplyAdd( two, e3, e1 ); - - // apply the metric to the error term - Vec4 e5 = e4*m_metric; - Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ(); - - // keep the solution if it wins - if( CompareAnyLessThan( error, besterror ) ) - { - beststart = a; - bestend = b; - besti = i; - bestj = j; - besterror = error; - bestiteration = iterationIndex; - } - - // advance - if( j == count ) - break; - part1 += m_points_weights[j]; - ++j; - } - - // advance - part0 += m_points_weights[i]; - } - - // stop if we didn't improve in this iteration - if( bestiteration != iterationIndex ) - break; - - // advance if possible - ++iterationIndex; - if( iterationIndex == m_iterationCount ) - break; - - // stop if a new iteration is an ordering that has already been tried - Vec3 axis = ( bestend - beststart ).GetVec3(); - if( !ConstructOrdering( axis, iterationIndex ) ) - break; - } - - // save the block if necessary - if( CompareAnyLessThan( besterror, m_besterror ) ) - { - // remap the indices - u8 const* order = ( u8* )m_order + 16*bestiteration; - - u8 unordered[16]; - for( int m = 0; m < besti; ++m ) - unordered[order[m]] = 0; - for( int m = besti; m < bestj; ++m ) - unordered[order[m]] = 2; - for( int m = bestj; m < count; ++m ) - unordered[order[m]] = 1; - - m_colours->RemapIndices( unordered, bestindices ); - - // save the block - WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); - - // save the error - m_besterror = besterror; - } -} - -void ClusterFit::Compress4( void* block ) -{ - // declare variables - int const count = m_colours->GetCount(); - Vec4 const two = VEC4_CONST( 2.0f ); - Vec4 const one = VEC4_CONST( 1.0f ); - Vec4 const onethird_onethird2( 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/9.0f ); - Vec4 const twothirds_twothirds2( 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 4.0f/9.0f ); - Vec4 const twonineths = VEC4_CONST( 2.0f/9.0f ); - Vec4 const zero = VEC4_CONST( 0.0f ); - Vec4 const half = VEC4_CONST( 0.5f ); - Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); - Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); - - // prepare an ordering using the principle axis - ConstructOrdering( m_principle, 0 ); - - // check all possible clusters and iterate on the total order - Vec4 beststart = VEC4_CONST( 0.0f ); - Vec4 bestend = VEC4_CONST( 0.0f ); - Vec4 besterror = m_besterror; - u8 bestindices[16]; - int bestiteration = 0; - int besti = 0, bestj = 0, bestk = 0; - - // loop over iterations (we avoid the case that all points in first or last cluster) - for( int iterationIndex = 0;; ) - { - // first cluster [0,i) is at the start - Vec4 part0 = VEC4_CONST( 0.0f ); - for( int i = 0; i < count; ++i ) - { - // second cluster [i,j) is one third along - Vec4 part1 = VEC4_CONST( 0.0f ); - for( int j = i;; ) - { - // third cluster [j,k) is two thirds along - Vec4 part2 = ( j == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f ); - int kmin = ( j == 0 ) ? 1 : j; - for( int k = kmin;; ) - { - // last cluster [k,count) is at the end - Vec4 part3 = m_xsum_wsum - part2 - part1 - part0; - - // compute least squares terms directly - Vec4 const alphax_sum = MultiplyAdd( part2, onethird_onethird2, MultiplyAdd( part1, twothirds_twothirds2, part0 ) ); - Vec4 const alpha2_sum = alphax_sum.SplatW(); - - Vec4 const betax_sum = MultiplyAdd( part1, onethird_onethird2, MultiplyAdd( part2, twothirds_twothirds2, part3 ) ); - Vec4 const beta2_sum = betax_sum.SplatW(); - - Vec4 const alphabeta_sum = twonineths*( part1 + part2 ).SplatW(); - - // compute the least-squares optimal points - Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) ); - Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor; - Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor; - - // clamp to the grid - a = Min( one, Max( zero, a ) ); - b = Min( one, Max( zero, b ) ); - a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp; - b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp; - - // compute the error (we skip the constant xxsum) - Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); - Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); - Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); - Vec4 e4 = MultiplyAdd( two, e3, e1 ); - - // apply the metric to the error term - Vec4 e5 = e4*m_metric; - Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ(); - - // keep the solution if it wins - if( CompareAnyLessThan( error, besterror ) ) - { - beststart = a; - bestend = b; - besterror = error; - besti = i; - bestj = j; - bestk = k; - bestiteration = iterationIndex; - } - - // advance - if( k == count ) - break; - part2 += m_points_weights[k]; - ++k; - } - - // advance - if( j == count ) - break; - part1 += m_points_weights[j]; - ++j; - } - - // advance - part0 += m_points_weights[i]; - } - - // stop if we didn't improve in this iteration - if( bestiteration != iterationIndex ) - break; - - // advance if possible - ++iterationIndex; - if( iterationIndex == m_iterationCount ) - break; - - // stop if a new iteration is an ordering that has already been tried - Vec3 axis = ( bestend - beststart ).GetVec3(); - if( !ConstructOrdering( axis, iterationIndex ) ) - break; - } - - // save the block if necessary - if( CompareAnyLessThan( besterror, m_besterror ) ) - { - // remap the indices - u8 const* order = ( u8* )m_order + 16*bestiteration; - - u8 unordered[16]; - for( int m = 0; m < besti; ++m ) - unordered[order[m]] = 0; - for( int m = besti; m < bestj; ++m ) - unordered[order[m]] = 2; - for( int m = bestj; m < bestk; ++m ) - unordered[order[m]] = 3; - for( int m = bestk; m < count; ++m ) - unordered[order[m]] = 1; - - m_colours->RemapIndices( unordered, bestindices ); - - // save the block - WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); - - // save the error - m_besterror = besterror; - } -} - -} // namespace squish diff --git a/thirdparty/squish/clusterfit.h b/thirdparty/squish/clusterfit.h deleted file mode 100644 index 999396b262..0000000000 --- a/thirdparty/squish/clusterfit.h +++ /dev/null @@ -1,61 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - Copyright (c) 2007 Ignacio Castano icastano@nvidia.com - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_CLUSTERFIT_H -#define SQUISH_CLUSTERFIT_H - -#include "squish.h" -#include "maths.h" -#include "simd.h" -#include "colourfit.h" - -namespace squish { - -class ClusterFit : public ColourFit -{ -public: - ClusterFit( ColourSet const* colours, int flags, float* metric ); - -private: - bool ConstructOrdering( Vec3 const& axis, int iteration ); - - virtual void Compress3( void* block ); - virtual void Compress4( void* block ); - - enum { kMaxIterations = 8 }; - - int m_iterationCount; - Vec3 m_principle; - u8 m_order[16*kMaxIterations]; - Vec4 m_points_weights[16]; - Vec4 m_xsum_wsum; - Vec4 m_metric; - Vec4 m_besterror; -}; - -} // namespace squish - -#endif // ndef SQUISH_CLUSTERFIT_H diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp deleted file mode 100644 index f14c9362bd..0000000000 --- a/thirdparty/squish/colourblock.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "colourblock.h" -// -- GODOT start -- -#include "alpha.h" -// -- GODOT end -- - -namespace squish { - -static int FloatToInt( float a, int limit ) -{ - // use ANSI round-to-zero behaviour to get round-to-nearest - int i = ( int )( a + 0.5f ); - - // clamp to the limit - if( i < 0 ) - i = 0; - else if( i > limit ) - i = limit; - - // done - return i; -} - -static int FloatTo565( Vec3::Arg colour ) -{ - // get the components in the correct range - int r = FloatToInt( 31.0f*colour.X(), 31 ); - int g = FloatToInt( 63.0f*colour.Y(), 63 ); - int b = FloatToInt( 31.0f*colour.Z(), 31 ); - - // pack into a single value - return ( r << 11 ) | ( g << 5 ) | b; -} - -static void WriteColourBlock( int a, int b, u8* indices, void* block ) -{ - // get the block as bytes - u8* bytes = ( u8* )block; - - // write the endpoints - bytes[0] = ( u8 )( a & 0xff ); - bytes[1] = ( u8 )( a >> 8 ); - bytes[2] = ( u8 )( b & 0xff ); - bytes[3] = ( u8 )( b >> 8 ); - - // write the indices - for( int i = 0; i < 4; ++i ) - { - u8 const* ind = indices + 4*i; - bytes[4 + i] = ind[0] | ( ind[1] << 2 ) | ( ind[2] << 4 ) | ( ind[3] << 6 ); - } -} - -void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ) -{ - // get the packed values - int a = FloatTo565( start ); - int b = FloatTo565( end ); - - // remap the indices - u8 remapped[16]; - if( a <= b ) - { - // use the indices directly - for( int i = 0; i < 16; ++i ) - remapped[i] = indices[i]; - } - else - { - // swap a and b - std::swap( a, b ); - for( int i = 0; i < 16; ++i ) - { - if( indices[i] == 0 ) - remapped[i] = 1; - else if( indices[i] == 1 ) - remapped[i] = 0; - else - remapped[i] = indices[i]; - } - } - - // write the block - WriteColourBlock( a, b, remapped, block ); -} - -void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ) -{ - // get the packed values - int a = FloatTo565( start ); - int b = FloatTo565( end ); - - // remap the indices - u8 remapped[16]; - if( a < b ) - { - // swap a and b - std::swap( a, b ); - for( int i = 0; i < 16; ++i ) - remapped[i] = ( indices[i] ^ 0x1 ) & 0x3; - } - else if( a == b ) - { - // use index 0 - for( int i = 0; i < 16; ++i ) - remapped[i] = 0; - } - else - { - // use the indices directly - for( int i = 0; i < 16; ++i ) - remapped[i] = indices[i]; - } - - // write the block - WriteColourBlock( a, b, remapped, block ); -} - -static int Unpack565( u8 const* packed, u8* colour ) -{ - // build the packed value - int value = ( int )packed[0] | ( ( int )packed[1] << 8 ); - - // get the components in the stored range - u8 red = ( u8 )( ( value >> 11 ) & 0x1f ); - u8 green = ( u8 )( ( value >> 5 ) & 0x3f ); - u8 blue = ( u8 )( value & 0x1f ); - - // scale up to 8 bits - colour[0] = ( red << 3 ) | ( red >> 2 ); - colour[1] = ( green << 2 ) | ( green >> 4 ); - colour[2] = ( blue << 3 ) | ( blue >> 2 ); - colour[3] = 255; - - // return the value - return value; -} - -void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) -{ - // get the block bytes - u8 const* bytes = reinterpret_cast< u8 const* >( block ); - - // unpack the endpoints - u8 codes[16]; - int a = Unpack565( bytes, codes ); - int b = Unpack565( bytes + 2, codes + 4 ); - - // generate the midpoints - for( int i = 0; i < 3; ++i ) - { - int c = codes[i]; - int d = codes[4 + i]; - - if( isDxt1 && a <= b ) - { - codes[8 + i] = ( u8 )( ( c + d )/2 ); - codes[12 + i] = 0; - } - else - { - codes[8 + i] = ( u8 )( ( 2*c + d )/3 ); - codes[12 + i] = ( u8 )( ( c + 2*d )/3 ); - } - } - - // fill in alpha for the intermediate values - codes[8 + 3] = 255; - codes[12 + 3] = ( isDxt1 && a <= b ) ? 0 : 255; - - // unpack the indices - u8 indices[16]; - for( int i = 0; i < 4; ++i ) - { - u8* ind = indices + 4*i; - u8 packed = bytes[4 + i]; - - ind[0] = packed & 0x3; - ind[1] = ( packed >> 2 ) & 0x3; - ind[2] = ( packed >> 4 ) & 0x3; - ind[3] = ( packed >> 6 ) & 0x3; - } - - // store out the colours - for( int i = 0; i < 16; ++i ) - { - u8 offset = 4*indices[i]; - for( int j = 0; j < 4; ++j ) - rgba[4*i + j] = codes[offset + j]; - } -} - -// -- GODOT start -- -void DecompressColourBc4( u8* rgba, void const* block) -{ - DecompressAlphaDxt5(rgba,block); - for ( int i = 0; i < 16; ++i ) { - rgba[i*4] = rgba[i*4 + 3]; - rgba[i*4 + 1] = 0; - rgba[i*4 + 2] = 0; - rgba[i*4 + 3] = 255; - } -} - -void DecompressColourBc5( u8* rgba, void const* block) -{ - void const* rblock = block; - void const* gblock = reinterpret_cast< u8 const* >( block ) + 8; - DecompressAlphaDxt5(rgba,rblock); - for ( int i = 0; i < 16; ++i ) { - rgba[i*4] = rgba[i*4 + 3]; - } - DecompressAlphaDxt5(rgba,gblock); - for ( int i = 0; i < 16; ++i ) { - rgba[i*4+1] = rgba[i*4 + 3]; - rgba[i*4 + 2] = 0; - rgba[i*4 + 3] = 255; - } -} -// -- GODOT end -- - - -} // namespace squish diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h deleted file mode 100644 index e1eb9e4917..0000000000 --- a/thirdparty/squish/colourblock.h +++ /dev/null @@ -1,45 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_COLOURBLOCK_H -#define SQUISH_COLOURBLOCK_H - -#include "squish.h" -#include "maths.h" - -namespace squish { - -void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); -void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); - -void DecompressColour( u8* rgba, void const* block, bool isDxt1 ); -// -- GODOT start -- -void DecompressColourBc4( u8* rgba, void const* block ); -void DecompressColourBc5( u8* rgba, void const* block ); -// -- GODOT end -- - -} // namespace squish - -#endif // ndef SQUISH_COLOURBLOCK_H diff --git a/thirdparty/squish/colourfit.cpp b/thirdparty/squish/colourfit.cpp deleted file mode 100644 index e45b656557..0000000000 --- a/thirdparty/squish/colourfit.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "colourfit.h" -#include "colourset.h" - -namespace squish { - -ColourFit::ColourFit( ColourSet const* colours, int flags ) - : m_colours( colours ), - m_flags( flags ) -{ -} - -ColourFit::~ColourFit() -{ -} - -void ColourFit::Compress( void* block ) -{ - bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 ); - if( isDxt1 ) - { - Compress3( block ); - if( !m_colours->IsTransparent() ) - Compress4( block ); - } - else - Compress4( block ); -} - -} // namespace squish diff --git a/thirdparty/squish/colourfit.h b/thirdparty/squish/colourfit.h deleted file mode 100644 index e73dceb2eb..0000000000 --- a/thirdparty/squish/colourfit.h +++ /dev/null @@ -1,56 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_COLOURFIT_H -#define SQUISH_COLOURFIT_H - -#include "squish.h" -#include "maths.h" - -#include <climits> - -namespace squish { - -class ColourSet; - -class ColourFit -{ -public: - ColourFit( ColourSet const* colours, int flags ); - virtual ~ColourFit(); - - void Compress( void* block ); - -protected: - virtual void Compress3( void* block ) = 0; - virtual void Compress4( void* block ) = 0; - - ColourSet const* m_colours; - int m_flags; -}; - -} // namespace squish - -#endif // ndef SQUISH_COLOURFIT_H diff --git a/thirdparty/squish/colourset.cpp b/thirdparty/squish/colourset.cpp deleted file mode 100644 index e900556471..0000000000 --- a/thirdparty/squish/colourset.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "colourset.h" - -namespace squish { - -ColourSet::ColourSet( u8 const* rgba, int mask, int flags ) - : m_count( 0 ), - m_transparent( false ) -{ - // check the compression mode for dxt1 - bool isDxt1 = ( ( flags & kDxt1 ) != 0 ); - bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 ); - - // create the minimal set - for( int i = 0; i < 16; ++i ) - { - // check this pixel is enabled - int bit = 1 << i; - if( ( mask & bit ) == 0 ) - { - m_remap[i] = -1; - continue; - } - - // check for transparent pixels when using dxt1 - if( isDxt1 && rgba[4*i + 3] < 128 ) - { - m_remap[i] = -1; - m_transparent = true; - continue; - } - - // loop over previous points for a match - for( int j = 0;; ++j ) - { - // allocate a new point - if( j == i ) - { - // normalise coordinates to [0,1] - float x = ( float )rgba[4*i] / 255.0f; - float y = ( float )rgba[4*i + 1] / 255.0f; - float z = ( float )rgba[4*i + 2] / 255.0f; - - // ensure there is always non-zero weight even for zero alpha - float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f; - - // add the point - m_points[m_count] = Vec3( x, y, z ); - m_weights[m_count] = ( weightByAlpha ? w : 1.0f ); - m_remap[i] = m_count; - - // advance - ++m_count; - break; - } - - // check for a match - int oldbit = 1 << j; - bool match = ( ( mask & oldbit ) != 0 ) - && ( rgba[4*i] == rgba[4*j] ) - && ( rgba[4*i + 1] == rgba[4*j + 1] ) - && ( rgba[4*i + 2] == rgba[4*j + 2] ) - && ( rgba[4*j + 3] >= 128 || !isDxt1 ); - if( match ) - { - // get the index of the match - int index = m_remap[j]; - - // ensure there is always non-zero weight even for zero alpha - float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f; - - // map to this point and increase the weight - m_weights[index] += ( weightByAlpha ? w : 1.0f ); - m_remap[i] = index; - break; - } - } - } - - // square root the weights - for( int i = 0; i < m_count; ++i ) - m_weights[i] = std::sqrt( m_weights[i] ); -} - -void ColourSet::RemapIndices( u8 const* source, u8* target ) const -{ - for( int i = 0; i < 16; ++i ) - { - int j = m_remap[i]; - if( j == -1 ) - target[i] = 3; - else - target[i] = source[j]; - } -} - -} // namespace squish diff --git a/thirdparty/squish/colourset.h b/thirdparty/squish/colourset.h deleted file mode 100644 index e13bb6fc35..0000000000 --- a/thirdparty/squish/colourset.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_COLOURSET_H -#define SQUISH_COLOURSET_H - -#include "squish.h" -#include "maths.h" - -namespace squish { - -/*! @brief Represents a set of block colours -*/ -class ColourSet -{ -public: - ColourSet( u8 const* rgba, int mask, int flags ); - - int GetCount() const { return m_count; } - Vec3 const* GetPoints() const { return m_points; } - float const* GetWeights() const { return m_weights; } - bool IsTransparent() const { return m_transparent; } - - void RemapIndices( u8 const* source, u8* target ) const; - -private: - int m_count; - Vec3 m_points[16]; - float m_weights[16]; - int m_remap[16]; - bool m_transparent; -}; - -} // namespace sqish - -#endif // ndef SQUISH_COLOURSET_H diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h deleted file mode 100644 index 05f8d72598..0000000000 --- a/thirdparty/squish/config.h +++ /dev/null @@ -1,69 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_CONFIG_H -#define SQUISH_CONFIG_H - -// Set to 1 when building squish to use Altivec instructions. -#ifndef SQUISH_USE_ALTIVEC -#define SQUISH_USE_ALTIVEC 0 -#endif - -// Set to 1 or 2 when building squish to use SSE or SSE2 instructions. -// -- GODOT start -- -#ifdef _MSC_VER - #if defined(_M_IX86_FP) - #if _M_IX86_FP >= 2 - #define SQUISH_USE_SSE 2 - #elif _M_IX86_FP >= 1 - #define SQUISH_USE_SSE 1 - #endif - #elif defined(_M_X64) - #define SQUISH_USE_SSE 2 - #endif -#else - #if defined(__SSE2__) - #define SQUISH_USE_SSE 2 - #elif defined(__SSE__) - #define SQUISH_USE_SSE 1 - #endif -#endif -// -- GODOT end -- - -#ifndef SQUISH_USE_SSE -#define SQUISH_USE_SSE 0 -#endif - -// Internally set SQUISH_USE_SIMD when either Altivec or SSE is available. -#if SQUISH_USE_ALTIVEC && SQUISH_USE_SSE -#error "Cannot enable both Altivec and SSE!" -#endif -#if SQUISH_USE_ALTIVEC || SQUISH_USE_SSE -#define SQUISH_USE_SIMD 1 -#else -#define SQUISH_USE_SIMD 0 -#endif - -#endif // ndef SQUISH_CONFIG_H diff --git a/thirdparty/squish/maths.cpp b/thirdparty/squish/maths.cpp deleted file mode 100644 index 4fa0bcfb35..0000000000 --- a/thirdparty/squish/maths.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -/*! @file - - The symmetric eigensystem solver algorithm is from - http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf -*/ - -#include "maths.h" -#include "simd.h" -#include <cfloat> - -namespace squish { - -Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights ) -{ - // compute the centroid - float total = 0.0f; - Vec3 centroid( 0.0f ); - for( int i = 0; i < n; ++i ) - { - total += weights[i]; - centroid += weights[i]*points[i]; - } - if( total > FLT_EPSILON ) - centroid /= total; - - // accumulate the covariance matrix - Sym3x3 covariance( 0.0f ); - for( int i = 0; i < n; ++i ) - { - Vec3 a = points[i] - centroid; - Vec3 b = weights[i]*a; - - covariance[0] += a.X()*b.X(); - covariance[1] += a.X()*b.Y(); - covariance[2] += a.X()*b.Z(); - covariance[3] += a.Y()*b.Y(); - covariance[4] += a.Y()*b.Z(); - covariance[5] += a.Z()*b.Z(); - } - - // return it - return covariance; -} - -#if 0 - -static Vec3 GetMultiplicity1Evector( Sym3x3 const& matrix, float evalue ) -{ - // compute M - Sym3x3 m; - m[0] = matrix[0] - evalue; - m[1] = matrix[1]; - m[2] = matrix[2]; - m[3] = matrix[3] - evalue; - m[4] = matrix[4]; - m[5] = matrix[5] - evalue; - - // compute U - Sym3x3 u; - u[0] = m[3]*m[5] - m[4]*m[4]; - u[1] = m[2]*m[4] - m[1]*m[5]; - u[2] = m[1]*m[4] - m[2]*m[3]; - u[3] = m[0]*m[5] - m[2]*m[2]; - u[4] = m[1]*m[2] - m[4]*m[0]; - u[5] = m[0]*m[3] - m[1]*m[1]; - - // find the largest component - float mc = std::fabs( u[0] ); - int mi = 0; - for( int i = 1; i < 6; ++i ) - { - float c = std::fabs( u[i] ); - if( c > mc ) - { - mc = c; - mi = i; - } - } - - // pick the column with this component - switch( mi ) - { - case 0: - return Vec3( u[0], u[1], u[2] ); - - case 1: - case 3: - return Vec3( u[1], u[3], u[4] ); - - default: - return Vec3( u[2], u[4], u[5] ); - } -} - -static Vec3 GetMultiplicity2Evector( Sym3x3 const& matrix, float evalue ) -{ - // compute M - Sym3x3 m; - m[0] = matrix[0] - evalue; - m[1] = matrix[1]; - m[2] = matrix[2]; - m[3] = matrix[3] - evalue; - m[4] = matrix[4]; - m[5] = matrix[5] - evalue; - - // find the largest component - float mc = std::fabs( m[0] ); - int mi = 0; - for( int i = 1; i < 6; ++i ) - { - float c = std::fabs( m[i] ); - if( c > mc ) - { - mc = c; - mi = i; - } - } - - // pick the first eigenvector based on this index - switch( mi ) - { - case 0: - case 1: - return Vec3( -m[1], m[0], 0.0f ); - - case 2: - return Vec3( m[2], 0.0f, -m[0] ); - - case 3: - case 4: - return Vec3( 0.0f, -m[4], m[3] ); - - default: - return Vec3( 0.0f, -m[5], m[4] ); - } -} - -Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ) -{ - // compute the cubic coefficients - float c0 = matrix[0]*matrix[3]*matrix[5] - + 2.0f*matrix[1]*matrix[2]*matrix[4] - - matrix[0]*matrix[4]*matrix[4] - - matrix[3]*matrix[2]*matrix[2] - - matrix[5]*matrix[1]*matrix[1]; - float c1 = matrix[0]*matrix[3] + matrix[0]*matrix[5] + matrix[3]*matrix[5] - - matrix[1]*matrix[1] - matrix[2]*matrix[2] - matrix[4]*matrix[4]; - float c2 = matrix[0] + matrix[3] + matrix[5]; - - // compute the quadratic coefficients - float a = c1 - ( 1.0f/3.0f )*c2*c2; - float b = ( -2.0f/27.0f )*c2*c2*c2 + ( 1.0f/3.0f )*c1*c2 - c0; - - // compute the root count check - float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a; - - // test the multiplicity - if( FLT_EPSILON < Q ) - { - // only one root, which implies we have a multiple of the identity - return Vec3( 1.0f ); - } - else if( Q < -FLT_EPSILON ) - { - // three distinct roots - float theta = std::atan2( std::sqrt( -Q ), -0.5f*b ); - float rho = std::sqrt( 0.25f*b*b - Q ); - - float rt = std::pow( rho, 1.0f/3.0f ); - float ct = std::cos( theta/3.0f ); - float st = std::sin( theta/3.0f ); - - float l1 = ( 1.0f/3.0f )*c2 + 2.0f*rt*ct; - float l2 = ( 1.0f/3.0f )*c2 - rt*( ct + ( float )sqrt( 3.0f )*st ); - float l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st ); - - // pick the larger - if( std::fabs( l2 ) > std::fabs( l1 ) ) - l1 = l2; - if( std::fabs( l3 ) > std::fabs( l1 ) ) - l1 = l3; - - // get the eigenvector - return GetMultiplicity1Evector( matrix, l1 ); - } - else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON ) - { - // two roots - float rt; - if( b < 0.0f ) - rt = -std::pow( -0.5f*b, 1.0f/3.0f ); - else - rt = std::pow( 0.5f*b, 1.0f/3.0f ); - - float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated - float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt; - - // get the eigenvector - if( std::fabs( l1 ) > std::fabs( l2 ) ) - return GetMultiplicity2Evector( matrix, l1 ); - else - return GetMultiplicity1Evector( matrix, l2 ); - } -} - -#else - -#define POWER_ITERATION_COUNT 8 - -Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ) -{ - Vec4 const row0( matrix[0], matrix[1], matrix[2], 0.0f ); - Vec4 const row1( matrix[1], matrix[3], matrix[4], 0.0f ); - Vec4 const row2( matrix[2], matrix[4], matrix[5], 0.0f ); - Vec4 v = VEC4_CONST( 1.0f ); - for( int i = 0; i < POWER_ITERATION_COUNT; ++i ) - { - // matrix multiply - Vec4 w = row0*v.SplatX(); - w = MultiplyAdd(row1, v.SplatY(), w); - w = MultiplyAdd(row2, v.SplatZ(), w); - - // get max component from xyz in all channels - Vec4 a = Max(w.SplatX(), Max(w.SplatY(), w.SplatZ())); - - // divide through and advance - v = w*Reciprocal(a); - } - return v.GetVec3(); -} - -#endif - -} // namespace squish diff --git a/thirdparty/squish/maths.h b/thirdparty/squish/maths.h deleted file mode 100644 index 59c32196b1..0000000000 --- a/thirdparty/squish/maths.h +++ /dev/null @@ -1,233 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_MATHS_H -#define SQUISH_MATHS_H - -#include <cmath> -#include <algorithm> -#include "config.h" - -namespace squish { - -class Vec3 -{ -public: - typedef Vec3 const& Arg; - - Vec3() - { - } - - explicit Vec3( float s ) - { - m_x = s; - m_y = s; - m_z = s; - } - - Vec3( float x, float y, float z ) - { - m_x = x; - m_y = y; - m_z = z; - } - - float X() const { return m_x; } - float Y() const { return m_y; } - float Z() const { return m_z; } - - Vec3 operator-() const - { - return Vec3( -m_x, -m_y, -m_z ); - } - - Vec3& operator+=( Arg v ) - { - m_x += v.m_x; - m_y += v.m_y; - m_z += v.m_z; - return *this; - } - - Vec3& operator-=( Arg v ) - { - m_x -= v.m_x; - m_y -= v.m_y; - m_z -= v.m_z; - return *this; - } - - Vec3& operator*=( Arg v ) - { - m_x *= v.m_x; - m_y *= v.m_y; - m_z *= v.m_z; - return *this; - } - - Vec3& operator*=( float s ) - { - m_x *= s; - m_y *= s; - m_z *= s; - return *this; - } - - Vec3& operator/=( Arg v ) - { - m_x /= v.m_x; - m_y /= v.m_y; - m_z /= v.m_z; - return *this; - } - - Vec3& operator/=( float s ) - { - float t = 1.0f/s; - m_x *= t; - m_y *= t; - m_z *= t; - return *this; - } - - friend Vec3 operator+( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy += right; - } - - friend Vec3 operator-( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy -= right; - } - - friend Vec3 operator*( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy *= right; - } - - friend Vec3 operator*( Arg left, float right ) - { - Vec3 copy( left ); - return copy *= right; - } - - friend Vec3 operator*( float left, Arg right ) - { - Vec3 copy( right ); - return copy *= left; - } - - friend Vec3 operator/( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy /= right; - } - - friend Vec3 operator/( Arg left, float right ) - { - Vec3 copy( left ); - return copy /= right; - } - - friend float Dot( Arg left, Arg right ) - { - return left.m_x*right.m_x + left.m_y*right.m_y + left.m_z*right.m_z; - } - - friend Vec3 Min( Arg left, Arg right ) - { - return Vec3( - std::min( left.m_x, right.m_x ), - std::min( left.m_y, right.m_y ), - std::min( left.m_z, right.m_z ) - ); - } - - friend Vec3 Max( Arg left, Arg right ) - { - return Vec3( - std::max( left.m_x, right.m_x ), - std::max( left.m_y, right.m_y ), - std::max( left.m_z, right.m_z ) - ); - } - - friend Vec3 Truncate( Arg v ) - { - return Vec3( - v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ), - v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ), - v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ) - ); - } - -private: - float m_x; - float m_y; - float m_z; -}; - -inline float LengthSquared( Vec3::Arg v ) -{ - return Dot( v, v ); -} - -class Sym3x3 -{ -public: - Sym3x3() - { - } - - Sym3x3( float s ) - { - for( int i = 0; i < 6; ++i ) - m_x[i] = s; - } - - float operator[]( int index ) const - { - return m_x[index]; - } - - float& operator[]( int index ) - { - return m_x[index]; - } - -private: - float m_x[6]; -}; - -Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights ); -Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ); - -} // namespace squish - -#endif // ndef SQUISH_MATHS_H diff --git a/thirdparty/squish/patches/config_sse.patch b/thirdparty/squish/patches/config_sse.patch deleted file mode 100644 index 047701ee32..0000000000 --- a/thirdparty/squish/patches/config_sse.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h -index 92edefe966..05f8d72598 100644 ---- a/thirdparty/squish/config.h -+++ b/thirdparty/squish/config.h -@@ -32,6 +32,26 @@ - #endif - - // Set to 1 or 2 when building squish to use SSE or SSE2 instructions. -+// -- GODOT start -- -+#ifdef _MSC_VER -+ #if defined(_M_IX86_FP) -+ #if _M_IX86_FP >= 2 -+ #define SQUISH_USE_SSE 2 -+ #elif _M_IX86_FP >= 1 -+ #define SQUISH_USE_SSE 1 -+ #endif -+ #elif defined(_M_X64) -+ #define SQUISH_USE_SSE 2 -+ #endif -+#else -+ #if defined(__SSE2__) -+ #define SQUISH_USE_SSE 2 -+ #elif defined(__SSE__) -+ #define SQUISH_USE_SSE 1 -+ #endif -+#endif -+// -- GODOT end -- -+ - #ifndef SQUISH_USE_SSE - #define SQUISH_USE_SSE 0 - #endif diff --git a/thirdparty/squish/patches/decompress_bc4_bc5.patch b/thirdparty/squish/patches/decompress_bc4_bc5.patch deleted file mode 100644 index 949375560c..0000000000 --- a/thirdparty/squish/patches/decompress_bc4_bc5.patch +++ /dev/null @@ -1,85 +0,0 @@ -diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp -index af8b980365..f14c9362bd 100644 ---- a/thirdparty/squish/colourblock.cpp -+++ b/thirdparty/squish/colourblock.cpp -@@ -24,6 +24,9 @@ - -------------------------------------------------------------------------- */ - - #include "colourblock.h" -+// -- GODOT start -- -+#include "alpha.h" -+// -- GODOT end -- - - namespace squish { - -@@ -211,4 +214,34 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) - } - } - -+// -- GODOT start -- -+void DecompressColourBc4( u8* rgba, void const* block) -+{ -+ DecompressAlphaDxt5(rgba,block); -+ for ( int i = 0; i < 16; ++i ) { -+ rgba[i*4] = rgba[i*4 + 3]; -+ rgba[i*4 + 1] = 0; -+ rgba[i*4 + 2] = 0; -+ rgba[i*4 + 3] = 255; -+ } -+} -+ -+void DecompressColourBc5( u8* rgba, void const* block) -+{ -+ void const* rblock = block; -+ void const* gblock = reinterpret_cast< u8 const* >( block ) + 8; -+ DecompressAlphaDxt5(rgba,rblock); -+ for ( int i = 0; i < 16; ++i ) { -+ rgba[i*4] = rgba[i*4 + 3]; -+ } -+ DecompressAlphaDxt5(rgba,gblock); -+ for ( int i = 0; i < 16; ++i ) { -+ rgba[i*4+1] = rgba[i*4 + 3]; -+ rgba[i*4 + 2] = 0; -+ rgba[i*4 + 3] = 255; -+ } -+} -+// -- GODOT end -- -+ -+ - } // namespace squish -diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h -index fee2cd7c5d..e1eb9e4917 100644 ---- a/thirdparty/squish/colourblock.h -+++ b/thirdparty/squish/colourblock.h -@@ -35,6 +35,10 @@ void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* - void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); - - void DecompressColour( u8* rgba, void const* block, bool isDxt1 ); -+// -- GODOT start -- -+void DecompressColourBc4( u8* rgba, void const* block ); -+void DecompressColourBc5( u8* rgba, void const* block ); -+// -- GODOT end -- - - } // namespace squish - -diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp -index 1d22a64ad6..086ba11cd0 100644 ---- a/thirdparty/squish/squish.cpp -+++ b/thirdparty/squish/squish.cpp -@@ -135,7 +135,15 @@ void Decompress( u8* rgba, void const* block, int flags ) - colourBlock = reinterpret_cast< u8 const* >( block ) + 8; - - // decompress colour -- DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); -+ // -- GODOT start -- -+ //DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); -+ if(( flags & ( kBc4 ) ) != 0) -+ DecompressColourBc4( rgba, colourBlock); -+ else if(( flags & ( kBc5 ) ) != 0) -+ DecompressColourBc5( rgba, colourBlock); -+ else -+ DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); -+ // -- GODOT end -- - - // decompress alpha separately if necessary - if( ( flags & kDxt3 ) != 0 ) diff --git a/thirdparty/squish/rangefit.cpp b/thirdparty/squish/rangefit.cpp deleted file mode 100644 index adc07ed7d2..0000000000 --- a/thirdparty/squish/rangefit.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "rangefit.h" -#include "colourset.h" -#include "colourblock.h" -#include <cfloat> - -namespace squish { - -RangeFit::RangeFit( ColourSet const* colours, int flags, float* metric ) - : ColourFit( colours, flags ) -{ - // initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f) - if( metric ) - m_metric = Vec3( metric[0], metric[1], metric[2] ); - else - m_metric = Vec3( 1.0f ); - - // initialise the best error - m_besterror = FLT_MAX; - - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - float const* weights = m_colours->GetWeights(); - - // get the covariance matrix - Sym3x3 covariance = ComputeWeightedCovariance( count, values, weights ); - - // compute the principle component - Vec3 principle = ComputePrincipleComponent( covariance ); - - // get the min and max range as the codebook endpoints - Vec3 start( 0.0f ); - Vec3 end( 0.0f ); - if( count > 0 ) - { - float min, max; - - // compute the range - start = end = values[0]; - min = max = Dot( values[0], principle ); - for( int i = 1; i < count; ++i ) - { - float val = Dot( values[i], principle ); - if( val < min ) - { - start = values[i]; - min = val; - } - else if( val > max ) - { - end = values[i]; - max = val; - } - } - } - - // clamp the output to [0, 1] - Vec3 const one( 1.0f ); - Vec3 const zero( 0.0f ); - start = Min( one, Max( zero, start ) ); - end = Min( one, Max( zero, end ) ); - - // clamp to the grid and save - Vec3 const grid( 31.0f, 63.0f, 31.0f ); - Vec3 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f ); - Vec3 const half( 0.5f ); - m_start = Truncate( grid*start + half )*gridrcp; - m_end = Truncate( grid*end + half )*gridrcp; -} - -void RangeFit::Compress3( void* block ) -{ - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // create a codebook - Vec3 codes[3]; - codes[0] = m_start; - codes[1] = m_end; - codes[2] = 0.5f*m_start + 0.5f*m_end; - - // match each point to the closest code - u8 closest[16]; - float error = 0.0f; - for( int i = 0; i < count; ++i ) - { - // find the closest code - float dist = FLT_MAX; - int idx = 0; - for( int j = 0; j < 3; ++j ) - { - float d = LengthSquared( m_metric*( values[i] - codes[j] ) ); - if( d < dist ) - { - dist = d; - idx = j; - } - } - - // save the index - closest[i] = ( u8 )idx; - - // accumulate the error - error += dist; - } - - // save this scheme if it wins - if( error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( closest, indices ); - - // save the block - WriteColourBlock3( m_start, m_end, indices, block ); - - // save the error - m_besterror = error; - } -} - -void RangeFit::Compress4( void* block ) -{ - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // create a codebook - Vec3 codes[4]; - codes[0] = m_start; - codes[1] = m_end; - codes[2] = ( 2.0f/3.0f )*m_start + ( 1.0f/3.0f )*m_end; - codes[3] = ( 1.0f/3.0f )*m_start + ( 2.0f/3.0f )*m_end; - - // match each point to the closest code - u8 closest[16]; - float error = 0.0f; - for( int i = 0; i < count; ++i ) - { - // find the closest code - float dist = FLT_MAX; - int idx = 0; - for( int j = 0; j < 4; ++j ) - { - float d = LengthSquared( m_metric*( values[i] - codes[j] ) ); - if( d < dist ) - { - dist = d; - idx = j; - } - } - - // save the index - closest[i] = ( u8 )idx; - - // accumulate the error - error += dist; - } - - // save this scheme if it wins - if( error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( closest, indices ); - - // save the block - WriteColourBlock4( m_start, m_end, indices, block ); - - // save the error - m_besterror = error; - } -} - -} // namespace squish diff --git a/thirdparty/squish/rangefit.h b/thirdparty/squish/rangefit.h deleted file mode 100644 index bdb21a9007..0000000000 --- a/thirdparty/squish/rangefit.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_RANGEFIT_H -#define SQUISH_RANGEFIT_H - -#include "squish.h" -#include "colourfit.h" -#include "maths.h" - -namespace squish { - -class ColourSet; - -class RangeFit : public ColourFit -{ -public: - RangeFit( ColourSet const* colours, int flags, float* metric ); - -private: - virtual void Compress3( void* block ); - virtual void Compress4( void* block ); - - Vec3 m_metric; - Vec3 m_start; - Vec3 m_end; - float m_besterror; -}; - -} // squish - -#endif // ndef SQUISH_RANGEFIT_H diff --git a/thirdparty/squish/simd.h b/thirdparty/squish/simd.h deleted file mode 100644 index 1e02fa160e..0000000000 --- a/thirdparty/squish/simd.h +++ /dev/null @@ -1,40 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_H -#define SQUISH_SIMD_H - -#include "maths.h" - -#if SQUISH_USE_ALTIVEC -#include "simd_ve.h" -#elif SQUISH_USE_SSE -#include "simd_sse.h" -#else -#include "simd_float.h" -#endif - - -#endif // ndef SQUISH_SIMD_H diff --git a/thirdparty/squish/simd_float.h b/thirdparty/squish/simd_float.h deleted file mode 100644 index 030ea70950..0000000000 --- a/thirdparty/squish/simd_float.h +++ /dev/null @@ -1,183 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_FLOAT_H -#define SQUISH_SIMD_FLOAT_H - -#include <algorithm> - -namespace squish { - -#define VEC4_CONST( X ) Vec4( X ) - -class Vec4 -{ -public: - typedef Vec4 const& Arg; - - Vec4() {} - - explicit Vec4( float s ) - : m_x( s ), - m_y( s ), - m_z( s ), - m_w( s ) - { - } - - Vec4( float x, float y, float z, float w ) - : m_x( x ), - m_y( y ), - m_z( z ), - m_w( w ) - { - } - - Vec3 GetVec3() const - { - return Vec3( m_x, m_y, m_z ); - } - - Vec4 SplatX() const { return Vec4( m_x ); } - Vec4 SplatY() const { return Vec4( m_y ); } - Vec4 SplatZ() const { return Vec4( m_z ); } - Vec4 SplatW() const { return Vec4( m_w ); } - - Vec4& operator+=( Arg v ) - { - m_x += v.m_x; - m_y += v.m_y; - m_z += v.m_z; - m_w += v.m_w; - return *this; - } - - Vec4& operator-=( Arg v ) - { - m_x -= v.m_x; - m_y -= v.m_y; - m_z -= v.m_z; - m_w -= v.m_w; - return *this; - } - - Vec4& operator*=( Arg v ) - { - m_x *= v.m_x; - m_y *= v.m_y; - m_z *= v.m_z; - m_w *= v.m_w; - return *this; - } - - friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) - { - Vec4 copy( left ); - return copy += right; - } - - friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) - { - Vec4 copy( left ); - return copy -= right; - } - - friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) - { - Vec4 copy( left ); - return copy *= right; - } - - //! Returns a*b + c - friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return a*b + c; - } - - //! Returns -( a*b - c ) - friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return c - a*b; - } - - friend Vec4 Reciprocal( Vec4::Arg v ) - { - return Vec4( - 1.0f/v.m_x, - 1.0f/v.m_y, - 1.0f/v.m_z, - 1.0f/v.m_w - ); - } - - friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( - std::min( left.m_x, right.m_x ), - std::min( left.m_y, right.m_y ), - std::min( left.m_z, right.m_z ), - std::min( left.m_w, right.m_w ) - ); - } - - friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( - std::max( left.m_x, right.m_x ), - std::max( left.m_y, right.m_y ), - std::max( left.m_z, right.m_z ), - std::max( left.m_w, right.m_w ) - ); - } - - friend Vec4 Truncate( Vec4::Arg v ) - { - return Vec4( - v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ), - v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ), - v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ), - v.m_w > 0.0f ? std::floor( v.m_w ) : std::ceil( v.m_w ) - ); - } - - friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) - { - return left.m_x < right.m_x - || left.m_y < right.m_y - || left.m_z < right.m_z - || left.m_w < right.m_w; - } - -private: - float m_x; - float m_y; - float m_z; - float m_w; -}; - -} // namespace squish - -#endif // ndef SQUISH_SIMD_FLOAT_H - diff --git a/thirdparty/squish/simd_sse.h b/thirdparty/squish/simd_sse.h deleted file mode 100644 index 2e8be4ca7b..0000000000 --- a/thirdparty/squish/simd_sse.h +++ /dev/null @@ -1,180 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_SSE_H -#define SQUISH_SIMD_SSE_H - -#include <xmmintrin.h> -#if ( SQUISH_USE_SSE > 1 ) -#include <emmintrin.h> -#endif - -#define SQUISH_SSE_SPLAT( a ) \ - ( ( a ) | ( ( a ) << 2 ) | ( ( a ) << 4 ) | ( ( a ) << 6 ) ) - -#define SQUISH_SSE_SHUF( x, y, z, w ) \ - ( ( x ) | ( ( y ) << 2 ) | ( ( z ) << 4 ) | ( ( w ) << 6 ) ) - -namespace squish { - -#define VEC4_CONST( X ) Vec4( X ) - -class Vec4 -{ -public: - typedef Vec4 const& Arg; - - Vec4() {} - - explicit Vec4( __m128 v ) : m_v( v ) {} - - Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {} - - Vec4& operator=( Vec4 const& arg ) - { - m_v = arg.m_v; - return *this; - } - - explicit Vec4( float s ) : m_v( _mm_set1_ps( s ) ) {} - - Vec4( float x, float y, float z, float w ) : m_v( _mm_setr_ps( x, y, z, w ) ) {} - - Vec3 GetVec3() const - { -#ifdef __GNUC__ - __attribute__ ((__aligned__ (16))) float c[4]; -#else - __declspec(align(16)) float c[4]; -#endif - _mm_store_ps( c, m_v ); - return Vec3( c[0], c[1], c[2] ); - } - - Vec4 SplatX() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 0 ) ) ); } - Vec4 SplatY() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 1 ) ) ); } - Vec4 SplatZ() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 2 ) ) ); } - Vec4 SplatW() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 3 ) ) ); } - - Vec4& operator+=( Arg v ) - { - m_v = _mm_add_ps( m_v, v.m_v ); - return *this; - } - - Vec4& operator-=( Arg v ) - { - m_v = _mm_sub_ps( m_v, v.m_v ); - return *this; - } - - Vec4& operator*=( Arg v ) - { - m_v = _mm_mul_ps( m_v, v.m_v ); - return *this; - } - - friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_add_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_sub_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_mul_ps( left.m_v, right.m_v ) ); - } - - //! Returns a*b + c - friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( _mm_add_ps( _mm_mul_ps( a.m_v, b.m_v ), c.m_v ) ); - } - - //! Returns -( a*b - c ) - friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( _mm_sub_ps( c.m_v, _mm_mul_ps( a.m_v, b.m_v ) ) ); - } - - friend Vec4 Reciprocal( Vec4::Arg v ) - { - // get the reciprocal estimate - __m128 estimate = _mm_rcp_ps( v.m_v ); - - // one round of Newton-Rhaphson refinement - __m128 diff = _mm_sub_ps( _mm_set1_ps( 1.0f ), _mm_mul_ps( estimate, v.m_v ) ); - return Vec4( _mm_add_ps( _mm_mul_ps( diff, estimate ), estimate ) ); - } - - friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_min_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_max_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 Truncate( Vec4::Arg v ) - { -#if ( SQUISH_USE_SSE == 1 ) - // convert to ints - __m128 input = v.m_v; - __m64 lo = _mm_cvttps_pi32( input ); - __m64 hi = _mm_cvttps_pi32( _mm_movehl_ps( input, input ) ); - - // convert to floats - __m128 part = _mm_movelh_ps( input, _mm_cvtpi32_ps( input, hi ) ); - __m128 truncated = _mm_cvtpi32_ps( part, lo ); - - // clear out the MMX multimedia state to allow FP calls later - _mm_empty(); - return Vec4( truncated ); -#else - // use SSE2 instructions - return Vec4( _mm_cvtepi32_ps( _mm_cvttps_epi32( v.m_v ) ) ); -#endif - } - - friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) - { - __m128 bits = _mm_cmplt_ps( left.m_v, right.m_v ); - int value = _mm_movemask_ps( bits ); - return value != 0; - } - -private: - __m128 m_v; -}; - -} // namespace squish - -#endif // ndef SQUISH_SIMD_SSE_H diff --git a/thirdparty/squish/simd_ve.h b/thirdparty/squish/simd_ve.h deleted file mode 100644 index 08a1537503..0000000000 --- a/thirdparty/squish/simd_ve.h +++ /dev/null @@ -1,166 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_VE_H -#define SQUISH_SIMD_VE_H - -#include <altivec.h> -#undef bool - -namespace squish { - -#define VEC4_CONST( X ) Vec4( ( vector float ){ X } ) - -class Vec4 -{ -public: - typedef Vec4 Arg; - - Vec4() {} - - explicit Vec4( vector float v ) : m_v( v ) {} - - Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {} - - Vec4& operator=( Vec4 const& arg ) - { - m_v = arg.m_v; - return *this; - } - - explicit Vec4( float s ) - { - union { vector float v; float c[4]; } u; - u.c[0] = s; - u.c[1] = s; - u.c[2] = s; - u.c[3] = s; - m_v = u.v; - } - - Vec4( float x, float y, float z, float w ) - { - union { vector float v; float c[4]; } u; - u.c[0] = x; - u.c[1] = y; - u.c[2] = z; - u.c[3] = w; - m_v = u.v; - } - - Vec3 GetVec3() const - { - union { vector float v; float c[4]; } u; - u.v = m_v; - return Vec3( u.c[0], u.c[1], u.c[2] ); - } - - Vec4 SplatX() const { return Vec4( vec_splat( m_v, 0 ) ); } - Vec4 SplatY() const { return Vec4( vec_splat( m_v, 1 ) ); } - Vec4 SplatZ() const { return Vec4( vec_splat( m_v, 2 ) ); } - Vec4 SplatW() const { return Vec4( vec_splat( m_v, 3 ) ); } - - Vec4& operator+=( Arg v ) - { - m_v = vec_add( m_v, v.m_v ); - return *this; - } - - Vec4& operator-=( Arg v ) - { - m_v = vec_sub( m_v, v.m_v ); - return *this; - } - - Vec4& operator*=( Arg v ) - { - m_v = vec_madd( m_v, v.m_v, ( vector float ){ -0.0f } ); - return *this; - } - - friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_add( left.m_v, right.m_v ) ); - } - - friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_sub( left.m_v, right.m_v ) ); - } - - friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_madd( left.m_v, right.m_v, ( vector float ){ -0.0f } ) ); - } - - //! Returns a*b + c - friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( vec_madd( a.m_v, b.m_v, c.m_v ) ); - } - - //! Returns -( a*b - c ) - friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( vec_nmsub( a.m_v, b.m_v, c.m_v ) ); - } - - friend Vec4 Reciprocal( Vec4::Arg v ) - { - // get the reciprocal estimate - vector float estimate = vec_re( v.m_v ); - - // one round of Newton-Rhaphson refinement - vector float diff = vec_nmsub( estimate, v.m_v, ( vector float ){ 1.0f } ); - return Vec4( vec_madd( diff, estimate, estimate ) ); - } - - friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_min( left.m_v, right.m_v ) ); - } - - friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_max( left.m_v, right.m_v ) ); - } - - friend Vec4 Truncate( Vec4::Arg v ) - { - return Vec4( vec_trunc( v.m_v ) ); - } - - friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) - { - return vec_any_lt( left.m_v, right.m_v ) != 0; - } - -private: - vector float m_v; -}; - -} // namespace squish - -#endif // ndef SQUISH_SIMD_VE_H diff --git a/thirdparty/squish/singlecolourfit.cpp b/thirdparty/squish/singlecolourfit.cpp deleted file mode 100644 index cef0ebc410..0000000000 --- a/thirdparty/squish/singlecolourfit.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "singlecolourfit.h" -#include "colourset.h" -#include "colourblock.h" - -namespace squish { - -struct SourceBlock -{ - u8 start; - u8 end; - u8 error; -}; - -struct SingleColourLookup -{ - SourceBlock sources[2]; -}; - -#include "singlecolourlookup.inl" - -static int FloatToInt( float a, int limit ) -{ - // use ANSI round-to-zero behaviour to get round-to-nearest - int i = ( int )( a + 0.5f ); - - // clamp to the limit - if( i < 0 ) - i = 0; - else if( i > limit ) - i = limit; - - // done - return i; -} - -SingleColourFit::SingleColourFit( ColourSet const* colours, int flags ) - : ColourFit( colours, flags ) -{ - // grab the single colour - Vec3 const* values = m_colours->GetPoints(); - m_colour[0] = ( u8 )FloatToInt( 255.0f*values->X(), 255 ); - m_colour[1] = ( u8 )FloatToInt( 255.0f*values->Y(), 255 ); - m_colour[2] = ( u8 )FloatToInt( 255.0f*values->Z(), 255 ); - - // initialise the best error - m_besterror = INT_MAX; -} - -void SingleColourFit::Compress3( void* block ) -{ - // build the table of lookups - SingleColourLookup const* const lookups[] = - { - lookup_5_3, - lookup_6_3, - lookup_5_3 - }; - - // find the best end-points and index - ComputeEndPoints( lookups ); - - // build the block if we win - if( m_error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( &m_index, indices ); - - // save the block - WriteColourBlock3( m_start, m_end, indices, block ); - - // save the error - m_besterror = m_error; - } -} - -void SingleColourFit::Compress4( void* block ) -{ - // build the table of lookups - SingleColourLookup const* const lookups[] = - { - lookup_5_4, - lookup_6_4, - lookup_5_4 - }; - - // find the best end-points and index - ComputeEndPoints( lookups ); - - // build the block if we win - if( m_error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( &m_index, indices ); - - // save the block - WriteColourBlock4( m_start, m_end, indices, block ); - - // save the error - m_besterror = m_error; - } -} - -void SingleColourFit::ComputeEndPoints( SingleColourLookup const* const* lookups ) -{ - // check each index combination (endpoint or intermediate) - m_error = INT_MAX; - for( int index = 0; index < 2; ++index ) - { - // check the error for this codebook index - SourceBlock const* sources[3]; - int error = 0; - for( int channel = 0; channel < 3; ++channel ) - { - // grab the lookup table and index for this channel - SingleColourLookup const* lookup = lookups[channel]; - int target = m_colour[channel]; - - // store a pointer to the source for this channel - sources[channel] = lookup[target].sources + index; - - // accumulate the error - int diff = sources[channel]->error; - error += diff*diff; - } - - // keep it if the error is lower - if( error < m_error ) - { - m_start = Vec3( - ( float )sources[0]->start/31.0f, - ( float )sources[1]->start/63.0f, - ( float )sources[2]->start/31.0f - ); - m_end = Vec3( - ( float )sources[0]->end/31.0f, - ( float )sources[1]->end/63.0f, - ( float )sources[2]->end/31.0f - ); - m_index = ( u8 )( 2*index ); - m_error = error; - } - } -} - -} // namespace squish diff --git a/thirdparty/squish/singlecolourfit.h b/thirdparty/squish/singlecolourfit.h deleted file mode 100644 index 974ce77256..0000000000 --- a/thirdparty/squish/singlecolourfit.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SINGLECOLOURFIT_H -#define SQUISH_SINGLECOLOURFIT_H - -#include "squish.h" -#include "colourfit.h" - -namespace squish { - -class ColourSet; -struct SingleColourLookup; - -class SingleColourFit : public ColourFit -{ -public: - SingleColourFit( ColourSet const* colours, int flags ); - -private: - virtual void Compress3( void* block ); - virtual void Compress4( void* block ); - - void ComputeEndPoints( SingleColourLookup const* const* lookups ); - - u8 m_colour[3]; - Vec3 m_start; - Vec3 m_end; - u8 m_index; - int m_error; - int m_besterror; -}; - -} // namespace squish - -#endif // ndef SQUISH_SINGLECOLOURFIT_H diff --git a/thirdparty/squish/singlecolourlookup.inl b/thirdparty/squish/singlecolourlookup.inl deleted file mode 100644 index 5b44a1e5e6..0000000000 --- a/thirdparty/squish/singlecolourlookup.inl +++ /dev/null @@ -1,1064 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -static SingleColourLookup const lookup_5_3[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 0, 1 } } }, - { { { 0, 0, 2 }, { 0, 0, 2 } } }, - { { { 0, 0, 3 }, { 0, 1, 1 } } }, - { { { 0, 0, 4 }, { 0, 1, 0 } } }, - { { { 1, 0, 3 }, { 0, 1, 1 } } }, - { { { 1, 0, 2 }, { 0, 1, 2 } } }, - { { { 1, 0, 1 }, { 0, 2, 1 } } }, - { { { 1, 0, 0 }, { 0, 2, 0 } } }, - { { { 1, 0, 1 }, { 0, 2, 1 } } }, - { { { 1, 0, 2 }, { 0, 2, 2 } } }, - { { { 1, 0, 3 }, { 0, 3, 1 } } }, - { { { 1, 0, 4 }, { 0, 3, 0 } } }, - { { { 2, 0, 3 }, { 0, 3, 1 } } }, - { { { 2, 0, 2 }, { 0, 3, 2 } } }, - { { { 2, 0, 1 }, { 0, 4, 1 } } }, - { { { 2, 0, 0 }, { 0, 4, 0 } } }, - { { { 2, 0, 1 }, { 0, 4, 1 } } }, - { { { 2, 0, 2 }, { 0, 4, 2 } } }, - { { { 2, 0, 3 }, { 0, 5, 1 } } }, - { { { 2, 0, 4 }, { 0, 5, 0 } } }, - { { { 3, 0, 3 }, { 0, 5, 1 } } }, - { { { 3, 0, 2 }, { 0, 5, 2 } } }, - { { { 3, 0, 1 }, { 0, 6, 1 } } }, - { { { 3, 0, 0 }, { 0, 6, 0 } } }, - { { { 3, 0, 1 }, { 0, 6, 1 } } }, - { { { 3, 0, 2 }, { 0, 6, 2 } } }, - { { { 3, 0, 3 }, { 0, 7, 1 } } }, - { { { 3, 0, 4 }, { 0, 7, 0 } } }, - { { { 4, 0, 4 }, { 0, 7, 1 } } }, - { { { 4, 0, 3 }, { 0, 7, 2 } } }, - { { { 4, 0, 2 }, { 1, 7, 1 } } }, - { { { 4, 0, 1 }, { 1, 7, 0 } } }, - { { { 4, 0, 0 }, { 0, 8, 0 } } }, - { { { 4, 0, 1 }, { 0, 8, 1 } } }, - { { { 4, 0, 2 }, { 2, 7, 1 } } }, - { { { 4, 0, 3 }, { 2, 7, 0 } } }, - { { { 4, 0, 4 }, { 0, 9, 0 } } }, - { { { 5, 0, 3 }, { 0, 9, 1 } } }, - { { { 5, 0, 2 }, { 3, 7, 1 } } }, - { { { 5, 0, 1 }, { 3, 7, 0 } } }, - { { { 5, 0, 0 }, { 0, 10, 0 } } }, - { { { 5, 0, 1 }, { 0, 10, 1 } } }, - { { { 5, 0, 2 }, { 0, 10, 2 } } }, - { { { 5, 0, 3 }, { 0, 11, 1 } } }, - { { { 5, 0, 4 }, { 0, 11, 0 } } }, - { { { 6, 0, 3 }, { 0, 11, 1 } } }, - { { { 6, 0, 2 }, { 0, 11, 2 } } }, - { { { 6, 0, 1 }, { 0, 12, 1 } } }, - { { { 6, 0, 0 }, { 0, 12, 0 } } }, - { { { 6, 0, 1 }, { 0, 12, 1 } } }, - { { { 6, 0, 2 }, { 0, 12, 2 } } }, - { { { 6, 0, 3 }, { 0, 13, 1 } } }, - { { { 6, 0, 4 }, { 0, 13, 0 } } }, - { { { 7, 0, 3 }, { 0, 13, 1 } } }, - { { { 7, 0, 2 }, { 0, 13, 2 } } }, - { { { 7, 0, 1 }, { 0, 14, 1 } } }, - { { { 7, 0, 0 }, { 0, 14, 0 } } }, - { { { 7, 0, 1 }, { 0, 14, 1 } } }, - { { { 7, 0, 2 }, { 0, 14, 2 } } }, - { { { 7, 0, 3 }, { 0, 15, 1 } } }, - { { { 7, 0, 4 }, { 0, 15, 0 } } }, - { { { 8, 0, 4 }, { 0, 15, 1 } } }, - { { { 8, 0, 3 }, { 0, 15, 2 } } }, - { { { 8, 0, 2 }, { 1, 15, 1 } } }, - { { { 8, 0, 1 }, { 1, 15, 0 } } }, - { { { 8, 0, 0 }, { 0, 16, 0 } } }, - { { { 8, 0, 1 }, { 0, 16, 1 } } }, - { { { 8, 0, 2 }, { 2, 15, 1 } } }, - { { { 8, 0, 3 }, { 2, 15, 0 } } }, - { { { 8, 0, 4 }, { 0, 17, 0 } } }, - { { { 9, 0, 3 }, { 0, 17, 1 } } }, - { { { 9, 0, 2 }, { 3, 15, 1 } } }, - { { { 9, 0, 1 }, { 3, 15, 0 } } }, - { { { 9, 0, 0 }, { 0, 18, 0 } } }, - { { { 9, 0, 1 }, { 0, 18, 1 } } }, - { { { 9, 0, 2 }, { 0, 18, 2 } } }, - { { { 9, 0, 3 }, { 0, 19, 1 } } }, - { { { 9, 0, 4 }, { 0, 19, 0 } } }, - { { { 10, 0, 3 }, { 0, 19, 1 } } }, - { { { 10, 0, 2 }, { 0, 19, 2 } } }, - { { { 10, 0, 1 }, { 0, 20, 1 } } }, - { { { 10, 0, 0 }, { 0, 20, 0 } } }, - { { { 10, 0, 1 }, { 0, 20, 1 } } }, - { { { 10, 0, 2 }, { 0, 20, 2 } } }, - { { { 10, 0, 3 }, { 0, 21, 1 } } }, - { { { 10, 0, 4 }, { 0, 21, 0 } } }, - { { { 11, 0, 3 }, { 0, 21, 1 } } }, - { { { 11, 0, 2 }, { 0, 21, 2 } } }, - { { { 11, 0, 1 }, { 0, 22, 1 } } }, - { { { 11, 0, 0 }, { 0, 22, 0 } } }, - { { { 11, 0, 1 }, { 0, 22, 1 } } }, - { { { 11, 0, 2 }, { 0, 22, 2 } } }, - { { { 11, 0, 3 }, { 0, 23, 1 } } }, - { { { 11, 0, 4 }, { 0, 23, 0 } } }, - { { { 12, 0, 4 }, { 0, 23, 1 } } }, - { { { 12, 0, 3 }, { 0, 23, 2 } } }, - { { { 12, 0, 2 }, { 1, 23, 1 } } }, - { { { 12, 0, 1 }, { 1, 23, 0 } } }, - { { { 12, 0, 0 }, { 0, 24, 0 } } }, - { { { 12, 0, 1 }, { 0, 24, 1 } } }, - { { { 12, 0, 2 }, { 2, 23, 1 } } }, - { { { 12, 0, 3 }, { 2, 23, 0 } } }, - { { { 12, 0, 4 }, { 0, 25, 0 } } }, - { { { 13, 0, 3 }, { 0, 25, 1 } } }, - { { { 13, 0, 2 }, { 3, 23, 1 } } }, - { { { 13, 0, 1 }, { 3, 23, 0 } } }, - { { { 13, 0, 0 }, { 0, 26, 0 } } }, - { { { 13, 0, 1 }, { 0, 26, 1 } } }, - { { { 13, 0, 2 }, { 0, 26, 2 } } }, - { { { 13, 0, 3 }, { 0, 27, 1 } } }, - { { { 13, 0, 4 }, { 0, 27, 0 } } }, - { { { 14, 0, 3 }, { 0, 27, 1 } } }, - { { { 14, 0, 2 }, { 0, 27, 2 } } }, - { { { 14, 0, 1 }, { 0, 28, 1 } } }, - { { { 14, 0, 0 }, { 0, 28, 0 } } }, - { { { 14, 0, 1 }, { 0, 28, 1 } } }, - { { { 14, 0, 2 }, { 0, 28, 2 } } }, - { { { 14, 0, 3 }, { 0, 29, 1 } } }, - { { { 14, 0, 4 }, { 0, 29, 0 } } }, - { { { 15, 0, 3 }, { 0, 29, 1 } } }, - { { { 15, 0, 2 }, { 0, 29, 2 } } }, - { { { 15, 0, 1 }, { 0, 30, 1 } } }, - { { { 15, 0, 0 }, { 0, 30, 0 } } }, - { { { 15, 0, 1 }, { 0, 30, 1 } } }, - { { { 15, 0, 2 }, { 0, 30, 2 } } }, - { { { 15, 0, 3 }, { 0, 31, 1 } } }, - { { { 15, 0, 4 }, { 0, 31, 0 } } }, - { { { 16, 0, 4 }, { 0, 31, 1 } } }, - { { { 16, 0, 3 }, { 0, 31, 2 } } }, - { { { 16, 0, 2 }, { 1, 31, 1 } } }, - { { { 16, 0, 1 }, { 1, 31, 0 } } }, - { { { 16, 0, 0 }, { 4, 28, 0 } } }, - { { { 16, 0, 1 }, { 4, 28, 1 } } }, - { { { 16, 0, 2 }, { 2, 31, 1 } } }, - { { { 16, 0, 3 }, { 2, 31, 0 } } }, - { { { 16, 0, 4 }, { 4, 29, 0 } } }, - { { { 17, 0, 3 }, { 4, 29, 1 } } }, - { { { 17, 0, 2 }, { 3, 31, 1 } } }, - { { { 17, 0, 1 }, { 3, 31, 0 } } }, - { { { 17, 0, 0 }, { 4, 30, 0 } } }, - { { { 17, 0, 1 }, { 4, 30, 1 } } }, - { { { 17, 0, 2 }, { 4, 30, 2 } } }, - { { { 17, 0, 3 }, { 4, 31, 1 } } }, - { { { 17, 0, 4 }, { 4, 31, 0 } } }, - { { { 18, 0, 3 }, { 4, 31, 1 } } }, - { { { 18, 0, 2 }, { 4, 31, 2 } } }, - { { { 18, 0, 1 }, { 5, 31, 1 } } }, - { { { 18, 0, 0 }, { 5, 31, 0 } } }, - { { { 18, 0, 1 }, { 5, 31, 1 } } }, - { { { 18, 0, 2 }, { 5, 31, 2 } } }, - { { { 18, 0, 3 }, { 6, 31, 1 } } }, - { { { 18, 0, 4 }, { 6, 31, 0 } } }, - { { { 19, 0, 3 }, { 6, 31, 1 } } }, - { { { 19, 0, 2 }, { 6, 31, 2 } } }, - { { { 19, 0, 1 }, { 7, 31, 1 } } }, - { { { 19, 0, 0 }, { 7, 31, 0 } } }, - { { { 19, 0, 1 }, { 7, 31, 1 } } }, - { { { 19, 0, 2 }, { 7, 31, 2 } } }, - { { { 19, 0, 3 }, { 8, 31, 1 } } }, - { { { 19, 0, 4 }, { 8, 31, 0 } } }, - { { { 20, 0, 4 }, { 8, 31, 1 } } }, - { { { 20, 0, 3 }, { 8, 31, 2 } } }, - { { { 20, 0, 2 }, { 9, 31, 1 } } }, - { { { 20, 0, 1 }, { 9, 31, 0 } } }, - { { { 20, 0, 0 }, { 12, 28, 0 } } }, - { { { 20, 0, 1 }, { 12, 28, 1 } } }, - { { { 20, 0, 2 }, { 10, 31, 1 } } }, - { { { 20, 0, 3 }, { 10, 31, 0 } } }, - { { { 20, 0, 4 }, { 12, 29, 0 } } }, - { { { 21, 0, 3 }, { 12, 29, 1 } } }, - { { { 21, 0, 2 }, { 11, 31, 1 } } }, - { { { 21, 0, 1 }, { 11, 31, 0 } } }, - { { { 21, 0, 0 }, { 12, 30, 0 } } }, - { { { 21, 0, 1 }, { 12, 30, 1 } } }, - { { { 21, 0, 2 }, { 12, 30, 2 } } }, - { { { 21, 0, 3 }, { 12, 31, 1 } } }, - { { { 21, 0, 4 }, { 12, 31, 0 } } }, - { { { 22, 0, 3 }, { 12, 31, 1 } } }, - { { { 22, 0, 2 }, { 12, 31, 2 } } }, - { { { 22, 0, 1 }, { 13, 31, 1 } } }, - { { { 22, 0, 0 }, { 13, 31, 0 } } }, - { { { 22, 0, 1 }, { 13, 31, 1 } } }, - { { { 22, 0, 2 }, { 13, 31, 2 } } }, - { { { 22, 0, 3 }, { 14, 31, 1 } } }, - { { { 22, 0, 4 }, { 14, 31, 0 } } }, - { { { 23, 0, 3 }, { 14, 31, 1 } } }, - { { { 23, 0, 2 }, { 14, 31, 2 } } }, - { { { 23, 0, 1 }, { 15, 31, 1 } } }, - { { { 23, 0, 0 }, { 15, 31, 0 } } }, - { { { 23, 0, 1 }, { 15, 31, 1 } } }, - { { { 23, 0, 2 }, { 15, 31, 2 } } }, - { { { 23, 0, 3 }, { 16, 31, 1 } } }, - { { { 23, 0, 4 }, { 16, 31, 0 } } }, - { { { 24, 0, 4 }, { 16, 31, 1 } } }, - { { { 24, 0, 3 }, { 16, 31, 2 } } }, - { { { 24, 0, 2 }, { 17, 31, 1 } } }, - { { { 24, 0, 1 }, { 17, 31, 0 } } }, - { { { 24, 0, 0 }, { 20, 28, 0 } } }, - { { { 24, 0, 1 }, { 20, 28, 1 } } }, - { { { 24, 0, 2 }, { 18, 31, 1 } } }, - { { { 24, 0, 3 }, { 18, 31, 0 } } }, - { { { 24, 0, 4 }, { 20, 29, 0 } } }, - { { { 25, 0, 3 }, { 20, 29, 1 } } }, - { { { 25, 0, 2 }, { 19, 31, 1 } } }, - { { { 25, 0, 1 }, { 19, 31, 0 } } }, - { { { 25, 0, 0 }, { 20, 30, 0 } } }, - { { { 25, 0, 1 }, { 20, 30, 1 } } }, - { { { 25, 0, 2 }, { 20, 30, 2 } } }, - { { { 25, 0, 3 }, { 20, 31, 1 } } }, - { { { 25, 0, 4 }, { 20, 31, 0 } } }, - { { { 26, 0, 3 }, { 20, 31, 1 } } }, - { { { 26, 0, 2 }, { 20, 31, 2 } } }, - { { { 26, 0, 1 }, { 21, 31, 1 } } }, - { { { 26, 0, 0 }, { 21, 31, 0 } } }, - { { { 26, 0, 1 }, { 21, 31, 1 } } }, - { { { 26, 0, 2 }, { 21, 31, 2 } } }, - { { { 26, 0, 3 }, { 22, 31, 1 } } }, - { { { 26, 0, 4 }, { 22, 31, 0 } } }, - { { { 27, 0, 3 }, { 22, 31, 1 } } }, - { { { 27, 0, 2 }, { 22, 31, 2 } } }, - { { { 27, 0, 1 }, { 23, 31, 1 } } }, - { { { 27, 0, 0 }, { 23, 31, 0 } } }, - { { { 27, 0, 1 }, { 23, 31, 1 } } }, - { { { 27, 0, 2 }, { 23, 31, 2 } } }, - { { { 27, 0, 3 }, { 24, 31, 1 } } }, - { { { 27, 0, 4 }, { 24, 31, 0 } } }, - { { { 28, 0, 4 }, { 24, 31, 1 } } }, - { { { 28, 0, 3 }, { 24, 31, 2 } } }, - { { { 28, 0, 2 }, { 25, 31, 1 } } }, - { { { 28, 0, 1 }, { 25, 31, 0 } } }, - { { { 28, 0, 0 }, { 28, 28, 0 } } }, - { { { 28, 0, 1 }, { 28, 28, 1 } } }, - { { { 28, 0, 2 }, { 26, 31, 1 } } }, - { { { 28, 0, 3 }, { 26, 31, 0 } } }, - { { { 28, 0, 4 }, { 28, 29, 0 } } }, - { { { 29, 0, 3 }, { 28, 29, 1 } } }, - { { { 29, 0, 2 }, { 27, 31, 1 } } }, - { { { 29, 0, 1 }, { 27, 31, 0 } } }, - { { { 29, 0, 0 }, { 28, 30, 0 } } }, - { { { 29, 0, 1 }, { 28, 30, 1 } } }, - { { { 29, 0, 2 }, { 28, 30, 2 } } }, - { { { 29, 0, 3 }, { 28, 31, 1 } } }, - { { { 29, 0, 4 }, { 28, 31, 0 } } }, - { { { 30, 0, 3 }, { 28, 31, 1 } } }, - { { { 30, 0, 2 }, { 28, 31, 2 } } }, - { { { 30, 0, 1 }, { 29, 31, 1 } } }, - { { { 30, 0, 0 }, { 29, 31, 0 } } }, - { { { 30, 0, 1 }, { 29, 31, 1 } } }, - { { { 30, 0, 2 }, { 29, 31, 2 } } }, - { { { 30, 0, 3 }, { 30, 31, 1 } } }, - { { { 30, 0, 4 }, { 30, 31, 0 } } }, - { { { 31, 0, 3 }, { 30, 31, 1 } } }, - { { { 31, 0, 2 }, { 30, 31, 2 } } }, - { { { 31, 0, 1 }, { 31, 31, 1 } } }, - { { { 31, 0, 0 }, { 31, 31, 0 } } } -}; - -static SingleColourLookup const lookup_6_3[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 1, 1 } } }, - { { { 0, 0, 2 }, { 0, 1, 0 } } }, - { { { 1, 0, 1 }, { 0, 2, 1 } } }, - { { { 1, 0, 0 }, { 0, 2, 0 } } }, - { { { 1, 0, 1 }, { 0, 3, 1 } } }, - { { { 1, 0, 2 }, { 0, 3, 0 } } }, - { { { 2, 0, 1 }, { 0, 4, 1 } } }, - { { { 2, 0, 0 }, { 0, 4, 0 } } }, - { { { 2, 0, 1 }, { 0, 5, 1 } } }, - { { { 2, 0, 2 }, { 0, 5, 0 } } }, - { { { 3, 0, 1 }, { 0, 6, 1 } } }, - { { { 3, 0, 0 }, { 0, 6, 0 } } }, - { { { 3, 0, 1 }, { 0, 7, 1 } } }, - { { { 3, 0, 2 }, { 0, 7, 0 } } }, - { { { 4, 0, 1 }, { 0, 8, 1 } } }, - { { { 4, 0, 0 }, { 0, 8, 0 } } }, - { { { 4, 0, 1 }, { 0, 9, 1 } } }, - { { { 4, 0, 2 }, { 0, 9, 0 } } }, - { { { 5, 0, 1 }, { 0, 10, 1 } } }, - { { { 5, 0, 0 }, { 0, 10, 0 } } }, - { { { 5, 0, 1 }, { 0, 11, 1 } } }, - { { { 5, 0, 2 }, { 0, 11, 0 } } }, - { { { 6, 0, 1 }, { 0, 12, 1 } } }, - { { { 6, 0, 0 }, { 0, 12, 0 } } }, - { { { 6, 0, 1 }, { 0, 13, 1 } } }, - { { { 6, 0, 2 }, { 0, 13, 0 } } }, - { { { 7, 0, 1 }, { 0, 14, 1 } } }, - { { { 7, 0, 0 }, { 0, 14, 0 } } }, - { { { 7, 0, 1 }, { 0, 15, 1 } } }, - { { { 7, 0, 2 }, { 0, 15, 0 } } }, - { { { 8, 0, 1 }, { 0, 16, 1 } } }, - { { { 8, 0, 0 }, { 0, 16, 0 } } }, - { { { 8, 0, 1 }, { 0, 17, 1 } } }, - { { { 8, 0, 2 }, { 0, 17, 0 } } }, - { { { 9, 0, 1 }, { 0, 18, 1 } } }, - { { { 9, 0, 0 }, { 0, 18, 0 } } }, - { { { 9, 0, 1 }, { 0, 19, 1 } } }, - { { { 9, 0, 2 }, { 0, 19, 0 } } }, - { { { 10, 0, 1 }, { 0, 20, 1 } } }, - { { { 10, 0, 0 }, { 0, 20, 0 } } }, - { { { 10, 0, 1 }, { 0, 21, 1 } } }, - { { { 10, 0, 2 }, { 0, 21, 0 } } }, - { { { 11, 0, 1 }, { 0, 22, 1 } } }, - { { { 11, 0, 0 }, { 0, 22, 0 } } }, - { { { 11, 0, 1 }, { 0, 23, 1 } } }, - { { { 11, 0, 2 }, { 0, 23, 0 } } }, - { { { 12, 0, 1 }, { 0, 24, 1 } } }, - { { { 12, 0, 0 }, { 0, 24, 0 } } }, - { { { 12, 0, 1 }, { 0, 25, 1 } } }, - { { { 12, 0, 2 }, { 0, 25, 0 } } }, - { { { 13, 0, 1 }, { 0, 26, 1 } } }, - { { { 13, 0, 0 }, { 0, 26, 0 } } }, - { { { 13, 0, 1 }, { 0, 27, 1 } } }, - { { { 13, 0, 2 }, { 0, 27, 0 } } }, - { { { 14, 0, 1 }, { 0, 28, 1 } } }, - { { { 14, 0, 0 }, { 0, 28, 0 } } }, - { { { 14, 0, 1 }, { 0, 29, 1 } } }, - { { { 14, 0, 2 }, { 0, 29, 0 } } }, - { { { 15, 0, 1 }, { 0, 30, 1 } } }, - { { { 15, 0, 0 }, { 0, 30, 0 } } }, - { { { 15, 0, 1 }, { 0, 31, 1 } } }, - { { { 15, 0, 2 }, { 0, 31, 0 } } }, - { { { 16, 0, 2 }, { 1, 31, 1 } } }, - { { { 16, 0, 1 }, { 1, 31, 0 } } }, - { { { 16, 0, 0 }, { 0, 32, 0 } } }, - { { { 16, 0, 1 }, { 2, 31, 0 } } }, - { { { 16, 0, 2 }, { 0, 33, 0 } } }, - { { { 17, 0, 1 }, { 3, 31, 0 } } }, - { { { 17, 0, 0 }, { 0, 34, 0 } } }, - { { { 17, 0, 1 }, { 4, 31, 0 } } }, - { { { 17, 0, 2 }, { 0, 35, 0 } } }, - { { { 18, 0, 1 }, { 5, 31, 0 } } }, - { { { 18, 0, 0 }, { 0, 36, 0 } } }, - { { { 18, 0, 1 }, { 6, 31, 0 } } }, - { { { 18, 0, 2 }, { 0, 37, 0 } } }, - { { { 19, 0, 1 }, { 7, 31, 0 } } }, - { { { 19, 0, 0 }, { 0, 38, 0 } } }, - { { { 19, 0, 1 }, { 8, 31, 0 } } }, - { { { 19, 0, 2 }, { 0, 39, 0 } } }, - { { { 20, 0, 1 }, { 9, 31, 0 } } }, - { { { 20, 0, 0 }, { 0, 40, 0 } } }, - { { { 20, 0, 1 }, { 10, 31, 0 } } }, - { { { 20, 0, 2 }, { 0, 41, 0 } } }, - { { { 21, 0, 1 }, { 11, 31, 0 } } }, - { { { 21, 0, 0 }, { 0, 42, 0 } } }, - { { { 21, 0, 1 }, { 12, 31, 0 } } }, - { { { 21, 0, 2 }, { 0, 43, 0 } } }, - { { { 22, 0, 1 }, { 13, 31, 0 } } }, - { { { 22, 0, 0 }, { 0, 44, 0 } } }, - { { { 22, 0, 1 }, { 14, 31, 0 } } }, - { { { 22, 0, 2 }, { 0, 45, 0 } } }, - { { { 23, 0, 1 }, { 15, 31, 0 } } }, - { { { 23, 0, 0 }, { 0, 46, 0 } } }, - { { { 23, 0, 1 }, { 0, 47, 1 } } }, - { { { 23, 0, 2 }, { 0, 47, 0 } } }, - { { { 24, 0, 1 }, { 0, 48, 1 } } }, - { { { 24, 0, 0 }, { 0, 48, 0 } } }, - { { { 24, 0, 1 }, { 0, 49, 1 } } }, - { { { 24, 0, 2 }, { 0, 49, 0 } } }, - { { { 25, 0, 1 }, { 0, 50, 1 } } }, - { { { 25, 0, 0 }, { 0, 50, 0 } } }, - { { { 25, 0, 1 }, { 0, 51, 1 } } }, - { { { 25, 0, 2 }, { 0, 51, 0 } } }, - { { { 26, 0, 1 }, { 0, 52, 1 } } }, - { { { 26, 0, 0 }, { 0, 52, 0 } } }, - { { { 26, 0, 1 }, { 0, 53, 1 } } }, - { { { 26, 0, 2 }, { 0, 53, 0 } } }, - { { { 27, 0, 1 }, { 0, 54, 1 } } }, - { { { 27, 0, 0 }, { 0, 54, 0 } } }, - { { { 27, 0, 1 }, { 0, 55, 1 } } }, - { { { 27, 0, 2 }, { 0, 55, 0 } } }, - { { { 28, 0, 1 }, { 0, 56, 1 } } }, - { { { 28, 0, 0 }, { 0, 56, 0 } } }, - { { { 28, 0, 1 }, { 0, 57, 1 } } }, - { { { 28, 0, 2 }, { 0, 57, 0 } } }, - { { { 29, 0, 1 }, { 0, 58, 1 } } }, - { { { 29, 0, 0 }, { 0, 58, 0 } } }, - { { { 29, 0, 1 }, { 0, 59, 1 } } }, - { { { 29, 0, 2 }, { 0, 59, 0 } } }, - { { { 30, 0, 1 }, { 0, 60, 1 } } }, - { { { 30, 0, 0 }, { 0, 60, 0 } } }, - { { { 30, 0, 1 }, { 0, 61, 1 } } }, - { { { 30, 0, 2 }, { 0, 61, 0 } } }, - { { { 31, 0, 1 }, { 0, 62, 1 } } }, - { { { 31, 0, 0 }, { 0, 62, 0 } } }, - { { { 31, 0, 1 }, { 0, 63, 1 } } }, - { { { 31, 0, 2 }, { 0, 63, 0 } } }, - { { { 32, 0, 2 }, { 1, 63, 1 } } }, - { { { 32, 0, 1 }, { 1, 63, 0 } } }, - { { { 32, 0, 0 }, { 16, 48, 0 } } }, - { { { 32, 0, 1 }, { 2, 63, 0 } } }, - { { { 32, 0, 2 }, { 16, 49, 0 } } }, - { { { 33, 0, 1 }, { 3, 63, 0 } } }, - { { { 33, 0, 0 }, { 16, 50, 0 } } }, - { { { 33, 0, 1 }, { 4, 63, 0 } } }, - { { { 33, 0, 2 }, { 16, 51, 0 } } }, - { { { 34, 0, 1 }, { 5, 63, 0 } } }, - { { { 34, 0, 0 }, { 16, 52, 0 } } }, - { { { 34, 0, 1 }, { 6, 63, 0 } } }, - { { { 34, 0, 2 }, { 16, 53, 0 } } }, - { { { 35, 0, 1 }, { 7, 63, 0 } } }, - { { { 35, 0, 0 }, { 16, 54, 0 } } }, - { { { 35, 0, 1 }, { 8, 63, 0 } } }, - { { { 35, 0, 2 }, { 16, 55, 0 } } }, - { { { 36, 0, 1 }, { 9, 63, 0 } } }, - { { { 36, 0, 0 }, { 16, 56, 0 } } }, - { { { 36, 0, 1 }, { 10, 63, 0 } } }, - { { { 36, 0, 2 }, { 16, 57, 0 } } }, - { { { 37, 0, 1 }, { 11, 63, 0 } } }, - { { { 37, 0, 0 }, { 16, 58, 0 } } }, - { { { 37, 0, 1 }, { 12, 63, 0 } } }, - { { { 37, 0, 2 }, { 16, 59, 0 } } }, - { { { 38, 0, 1 }, { 13, 63, 0 } } }, - { { { 38, 0, 0 }, { 16, 60, 0 } } }, - { { { 38, 0, 1 }, { 14, 63, 0 } } }, - { { { 38, 0, 2 }, { 16, 61, 0 } } }, - { { { 39, 0, 1 }, { 15, 63, 0 } } }, - { { { 39, 0, 0 }, { 16, 62, 0 } } }, - { { { 39, 0, 1 }, { 16, 63, 1 } } }, - { { { 39, 0, 2 }, { 16, 63, 0 } } }, - { { { 40, 0, 1 }, { 17, 63, 1 } } }, - { { { 40, 0, 0 }, { 17, 63, 0 } } }, - { { { 40, 0, 1 }, { 18, 63, 1 } } }, - { { { 40, 0, 2 }, { 18, 63, 0 } } }, - { { { 41, 0, 1 }, { 19, 63, 1 } } }, - { { { 41, 0, 0 }, { 19, 63, 0 } } }, - { { { 41, 0, 1 }, { 20, 63, 1 } } }, - { { { 41, 0, 2 }, { 20, 63, 0 } } }, - { { { 42, 0, 1 }, { 21, 63, 1 } } }, - { { { 42, 0, 0 }, { 21, 63, 0 } } }, - { { { 42, 0, 1 }, { 22, 63, 1 } } }, - { { { 42, 0, 2 }, { 22, 63, 0 } } }, - { { { 43, 0, 1 }, { 23, 63, 1 } } }, - { { { 43, 0, 0 }, { 23, 63, 0 } } }, - { { { 43, 0, 1 }, { 24, 63, 1 } } }, - { { { 43, 0, 2 }, { 24, 63, 0 } } }, - { { { 44, 0, 1 }, { 25, 63, 1 } } }, - { { { 44, 0, 0 }, { 25, 63, 0 } } }, - { { { 44, 0, 1 }, { 26, 63, 1 } } }, - { { { 44, 0, 2 }, { 26, 63, 0 } } }, - { { { 45, 0, 1 }, { 27, 63, 1 } } }, - { { { 45, 0, 0 }, { 27, 63, 0 } } }, - { { { 45, 0, 1 }, { 28, 63, 1 } } }, - { { { 45, 0, 2 }, { 28, 63, 0 } } }, - { { { 46, 0, 1 }, { 29, 63, 1 } } }, - { { { 46, 0, 0 }, { 29, 63, 0 } } }, - { { { 46, 0, 1 }, { 30, 63, 1 } } }, - { { { 46, 0, 2 }, { 30, 63, 0 } } }, - { { { 47, 0, 1 }, { 31, 63, 1 } } }, - { { { 47, 0, 0 }, { 31, 63, 0 } } }, - { { { 47, 0, 1 }, { 32, 63, 1 } } }, - { { { 47, 0, 2 }, { 32, 63, 0 } } }, - { { { 48, 0, 2 }, { 33, 63, 1 } } }, - { { { 48, 0, 1 }, { 33, 63, 0 } } }, - { { { 48, 0, 0 }, { 48, 48, 0 } } }, - { { { 48, 0, 1 }, { 34, 63, 0 } } }, - { { { 48, 0, 2 }, { 48, 49, 0 } } }, - { { { 49, 0, 1 }, { 35, 63, 0 } } }, - { { { 49, 0, 0 }, { 48, 50, 0 } } }, - { { { 49, 0, 1 }, { 36, 63, 0 } } }, - { { { 49, 0, 2 }, { 48, 51, 0 } } }, - { { { 50, 0, 1 }, { 37, 63, 0 } } }, - { { { 50, 0, 0 }, { 48, 52, 0 } } }, - { { { 50, 0, 1 }, { 38, 63, 0 } } }, - { { { 50, 0, 2 }, { 48, 53, 0 } } }, - { { { 51, 0, 1 }, { 39, 63, 0 } } }, - { { { 51, 0, 0 }, { 48, 54, 0 } } }, - { { { 51, 0, 1 }, { 40, 63, 0 } } }, - { { { 51, 0, 2 }, { 48, 55, 0 } } }, - { { { 52, 0, 1 }, { 41, 63, 0 } } }, - { { { 52, 0, 0 }, { 48, 56, 0 } } }, - { { { 52, 0, 1 }, { 42, 63, 0 } } }, - { { { 52, 0, 2 }, { 48, 57, 0 } } }, - { { { 53, 0, 1 }, { 43, 63, 0 } } }, - { { { 53, 0, 0 }, { 48, 58, 0 } } }, - { { { 53, 0, 1 }, { 44, 63, 0 } } }, - { { { 53, 0, 2 }, { 48, 59, 0 } } }, - { { { 54, 0, 1 }, { 45, 63, 0 } } }, - { { { 54, 0, 0 }, { 48, 60, 0 } } }, - { { { 54, 0, 1 }, { 46, 63, 0 } } }, - { { { 54, 0, 2 }, { 48, 61, 0 } } }, - { { { 55, 0, 1 }, { 47, 63, 0 } } }, - { { { 55, 0, 0 }, { 48, 62, 0 } } }, - { { { 55, 0, 1 }, { 48, 63, 1 } } }, - { { { 55, 0, 2 }, { 48, 63, 0 } } }, - { { { 56, 0, 1 }, { 49, 63, 1 } } }, - { { { 56, 0, 0 }, { 49, 63, 0 } } }, - { { { 56, 0, 1 }, { 50, 63, 1 } } }, - { { { 56, 0, 2 }, { 50, 63, 0 } } }, - { { { 57, 0, 1 }, { 51, 63, 1 } } }, - { { { 57, 0, 0 }, { 51, 63, 0 } } }, - { { { 57, 0, 1 }, { 52, 63, 1 } } }, - { { { 57, 0, 2 }, { 52, 63, 0 } } }, - { { { 58, 0, 1 }, { 53, 63, 1 } } }, - { { { 58, 0, 0 }, { 53, 63, 0 } } }, - { { { 58, 0, 1 }, { 54, 63, 1 } } }, - { { { 58, 0, 2 }, { 54, 63, 0 } } }, - { { { 59, 0, 1 }, { 55, 63, 1 } } }, - { { { 59, 0, 0 }, { 55, 63, 0 } } }, - { { { 59, 0, 1 }, { 56, 63, 1 } } }, - { { { 59, 0, 2 }, { 56, 63, 0 } } }, - { { { 60, 0, 1 }, { 57, 63, 1 } } }, - { { { 60, 0, 0 }, { 57, 63, 0 } } }, - { { { 60, 0, 1 }, { 58, 63, 1 } } }, - { { { 60, 0, 2 }, { 58, 63, 0 } } }, - { { { 61, 0, 1 }, { 59, 63, 1 } } }, - { { { 61, 0, 0 }, { 59, 63, 0 } } }, - { { { 61, 0, 1 }, { 60, 63, 1 } } }, - { { { 61, 0, 2 }, { 60, 63, 0 } } }, - { { { 62, 0, 1 }, { 61, 63, 1 } } }, - { { { 62, 0, 0 }, { 61, 63, 0 } } }, - { { { 62, 0, 1 }, { 62, 63, 1 } } }, - { { { 62, 0, 2 }, { 62, 63, 0 } } }, - { { { 63, 0, 1 }, { 63, 63, 1 } } }, - { { { 63, 0, 0 }, { 63, 63, 0 } } } -}; - -static SingleColourLookup const lookup_5_4[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 1, 1 } } }, - { { { 0, 0, 2 }, { 0, 1, 0 } } }, - { { { 0, 0, 3 }, { 0, 1, 1 } } }, - { { { 0, 0, 4 }, { 0, 2, 1 } } }, - { { { 1, 0, 3 }, { 0, 2, 0 } } }, - { { { 1, 0, 2 }, { 0, 2, 1 } } }, - { { { 1, 0, 1 }, { 0, 3, 1 } } }, - { { { 1, 0, 0 }, { 0, 3, 0 } } }, - { { { 1, 0, 1 }, { 1, 2, 1 } } }, - { { { 1, 0, 2 }, { 1, 2, 0 } } }, - { { { 1, 0, 3 }, { 0, 4, 0 } } }, - { { { 1, 0, 4 }, { 0, 5, 1 } } }, - { { { 2, 0, 3 }, { 0, 5, 0 } } }, - { { { 2, 0, 2 }, { 0, 5, 1 } } }, - { { { 2, 0, 1 }, { 0, 6, 1 } } }, - { { { 2, 0, 0 }, { 0, 6, 0 } } }, - { { { 2, 0, 1 }, { 2, 3, 1 } } }, - { { { 2, 0, 2 }, { 2, 3, 0 } } }, - { { { 2, 0, 3 }, { 0, 7, 0 } } }, - { { { 2, 0, 4 }, { 1, 6, 1 } } }, - { { { 3, 0, 3 }, { 1, 6, 0 } } }, - { { { 3, 0, 2 }, { 0, 8, 0 } } }, - { { { 3, 0, 1 }, { 0, 9, 1 } } }, - { { { 3, 0, 0 }, { 0, 9, 0 } } }, - { { { 3, 0, 1 }, { 0, 9, 1 } } }, - { { { 3, 0, 2 }, { 0, 10, 1 } } }, - { { { 3, 0, 3 }, { 0, 10, 0 } } }, - { { { 3, 0, 4 }, { 2, 7, 1 } } }, - { { { 4, 0, 4 }, { 2, 7, 0 } } }, - { { { 4, 0, 3 }, { 0, 11, 0 } } }, - { { { 4, 0, 2 }, { 1, 10, 1 } } }, - { { { 4, 0, 1 }, { 1, 10, 0 } } }, - { { { 4, 0, 0 }, { 0, 12, 0 } } }, - { { { 4, 0, 1 }, { 0, 13, 1 } } }, - { { { 4, 0, 2 }, { 0, 13, 0 } } }, - { { { 4, 0, 3 }, { 0, 13, 1 } } }, - { { { 4, 0, 4 }, { 0, 14, 1 } } }, - { { { 5, 0, 3 }, { 0, 14, 0 } } }, - { { { 5, 0, 2 }, { 2, 11, 1 } } }, - { { { 5, 0, 1 }, { 2, 11, 0 } } }, - { { { 5, 0, 0 }, { 0, 15, 0 } } }, - { { { 5, 0, 1 }, { 1, 14, 1 } } }, - { { { 5, 0, 2 }, { 1, 14, 0 } } }, - { { { 5, 0, 3 }, { 0, 16, 0 } } }, - { { { 5, 0, 4 }, { 0, 17, 1 } } }, - { { { 6, 0, 3 }, { 0, 17, 0 } } }, - { { { 6, 0, 2 }, { 0, 17, 1 } } }, - { { { 6, 0, 1 }, { 0, 18, 1 } } }, - { { { 6, 0, 0 }, { 0, 18, 0 } } }, - { { { 6, 0, 1 }, { 2, 15, 1 } } }, - { { { 6, 0, 2 }, { 2, 15, 0 } } }, - { { { 6, 0, 3 }, { 0, 19, 0 } } }, - { { { 6, 0, 4 }, { 1, 18, 1 } } }, - { { { 7, 0, 3 }, { 1, 18, 0 } } }, - { { { 7, 0, 2 }, { 0, 20, 0 } } }, - { { { 7, 0, 1 }, { 0, 21, 1 } } }, - { { { 7, 0, 0 }, { 0, 21, 0 } } }, - { { { 7, 0, 1 }, { 0, 21, 1 } } }, - { { { 7, 0, 2 }, { 0, 22, 1 } } }, - { { { 7, 0, 3 }, { 0, 22, 0 } } }, - { { { 7, 0, 4 }, { 2, 19, 1 } } }, - { { { 8, 0, 4 }, { 2, 19, 0 } } }, - { { { 8, 0, 3 }, { 0, 23, 0 } } }, - { { { 8, 0, 2 }, { 1, 22, 1 } } }, - { { { 8, 0, 1 }, { 1, 22, 0 } } }, - { { { 8, 0, 0 }, { 0, 24, 0 } } }, - { { { 8, 0, 1 }, { 0, 25, 1 } } }, - { { { 8, 0, 2 }, { 0, 25, 0 } } }, - { { { 8, 0, 3 }, { 0, 25, 1 } } }, - { { { 8, 0, 4 }, { 0, 26, 1 } } }, - { { { 9, 0, 3 }, { 0, 26, 0 } } }, - { { { 9, 0, 2 }, { 2, 23, 1 } } }, - { { { 9, 0, 1 }, { 2, 23, 0 } } }, - { { { 9, 0, 0 }, { 0, 27, 0 } } }, - { { { 9, 0, 1 }, { 1, 26, 1 } } }, - { { { 9, 0, 2 }, { 1, 26, 0 } } }, - { { { 9, 0, 3 }, { 0, 28, 0 } } }, - { { { 9, 0, 4 }, { 0, 29, 1 } } }, - { { { 10, 0, 3 }, { 0, 29, 0 } } }, - { { { 10, 0, 2 }, { 0, 29, 1 } } }, - { { { 10, 0, 1 }, { 0, 30, 1 } } }, - { { { 10, 0, 0 }, { 0, 30, 0 } } }, - { { { 10, 0, 1 }, { 2, 27, 1 } } }, - { { { 10, 0, 2 }, { 2, 27, 0 } } }, - { { { 10, 0, 3 }, { 0, 31, 0 } } }, - { { { 10, 0, 4 }, { 1, 30, 1 } } }, - { { { 11, 0, 3 }, { 1, 30, 0 } } }, - { { { 11, 0, 2 }, { 4, 24, 0 } } }, - { { { 11, 0, 1 }, { 1, 31, 1 } } }, - { { { 11, 0, 0 }, { 1, 31, 0 } } }, - { { { 11, 0, 1 }, { 1, 31, 1 } } }, - { { { 11, 0, 2 }, { 2, 30, 1 } } }, - { { { 11, 0, 3 }, { 2, 30, 0 } } }, - { { { 11, 0, 4 }, { 2, 31, 1 } } }, - { { { 12, 0, 4 }, { 2, 31, 0 } } }, - { { { 12, 0, 3 }, { 4, 27, 0 } } }, - { { { 12, 0, 2 }, { 3, 30, 1 } } }, - { { { 12, 0, 1 }, { 3, 30, 0 } } }, - { { { 12, 0, 0 }, { 4, 28, 0 } } }, - { { { 12, 0, 1 }, { 3, 31, 1 } } }, - { { { 12, 0, 2 }, { 3, 31, 0 } } }, - { { { 12, 0, 3 }, { 3, 31, 1 } } }, - { { { 12, 0, 4 }, { 4, 30, 1 } } }, - { { { 13, 0, 3 }, { 4, 30, 0 } } }, - { { { 13, 0, 2 }, { 6, 27, 1 } } }, - { { { 13, 0, 1 }, { 6, 27, 0 } } }, - { { { 13, 0, 0 }, { 4, 31, 0 } } }, - { { { 13, 0, 1 }, { 5, 30, 1 } } }, - { { { 13, 0, 2 }, { 5, 30, 0 } } }, - { { { 13, 0, 3 }, { 8, 24, 0 } } }, - { { { 13, 0, 4 }, { 5, 31, 1 } } }, - { { { 14, 0, 3 }, { 5, 31, 0 } } }, - { { { 14, 0, 2 }, { 5, 31, 1 } } }, - { { { 14, 0, 1 }, { 6, 30, 1 } } }, - { { { 14, 0, 0 }, { 6, 30, 0 } } }, - { { { 14, 0, 1 }, { 6, 31, 1 } } }, - { { { 14, 0, 2 }, { 6, 31, 0 } } }, - { { { 14, 0, 3 }, { 8, 27, 0 } } }, - { { { 14, 0, 4 }, { 7, 30, 1 } } }, - { { { 15, 0, 3 }, { 7, 30, 0 } } }, - { { { 15, 0, 2 }, { 8, 28, 0 } } }, - { { { 15, 0, 1 }, { 7, 31, 1 } } }, - { { { 15, 0, 0 }, { 7, 31, 0 } } }, - { { { 15, 0, 1 }, { 7, 31, 1 } } }, - { { { 15, 0, 2 }, { 8, 30, 1 } } }, - { { { 15, 0, 3 }, { 8, 30, 0 } } }, - { { { 15, 0, 4 }, { 10, 27, 1 } } }, - { { { 16, 0, 4 }, { 10, 27, 0 } } }, - { { { 16, 0, 3 }, { 8, 31, 0 } } }, - { { { 16, 0, 2 }, { 9, 30, 1 } } }, - { { { 16, 0, 1 }, { 9, 30, 0 } } }, - { { { 16, 0, 0 }, { 12, 24, 0 } } }, - { { { 16, 0, 1 }, { 9, 31, 1 } } }, - { { { 16, 0, 2 }, { 9, 31, 0 } } }, - { { { 16, 0, 3 }, { 9, 31, 1 } } }, - { { { 16, 0, 4 }, { 10, 30, 1 } } }, - { { { 17, 0, 3 }, { 10, 30, 0 } } }, - { { { 17, 0, 2 }, { 10, 31, 1 } } }, - { { { 17, 0, 1 }, { 10, 31, 0 } } }, - { { { 17, 0, 0 }, { 12, 27, 0 } } }, - { { { 17, 0, 1 }, { 11, 30, 1 } } }, - { { { 17, 0, 2 }, { 11, 30, 0 } } }, - { { { 17, 0, 3 }, { 12, 28, 0 } } }, - { { { 17, 0, 4 }, { 11, 31, 1 } } }, - { { { 18, 0, 3 }, { 11, 31, 0 } } }, - { { { 18, 0, 2 }, { 11, 31, 1 } } }, - { { { 18, 0, 1 }, { 12, 30, 1 } } }, - { { { 18, 0, 0 }, { 12, 30, 0 } } }, - { { { 18, 0, 1 }, { 14, 27, 1 } } }, - { { { 18, 0, 2 }, { 14, 27, 0 } } }, - { { { 18, 0, 3 }, { 12, 31, 0 } } }, - { { { 18, 0, 4 }, { 13, 30, 1 } } }, - { { { 19, 0, 3 }, { 13, 30, 0 } } }, - { { { 19, 0, 2 }, { 16, 24, 0 } } }, - { { { 19, 0, 1 }, { 13, 31, 1 } } }, - { { { 19, 0, 0 }, { 13, 31, 0 } } }, - { { { 19, 0, 1 }, { 13, 31, 1 } } }, - { { { 19, 0, 2 }, { 14, 30, 1 } } }, - { { { 19, 0, 3 }, { 14, 30, 0 } } }, - { { { 19, 0, 4 }, { 14, 31, 1 } } }, - { { { 20, 0, 4 }, { 14, 31, 0 } } }, - { { { 20, 0, 3 }, { 16, 27, 0 } } }, - { { { 20, 0, 2 }, { 15, 30, 1 } } }, - { { { 20, 0, 1 }, { 15, 30, 0 } } }, - { { { 20, 0, 0 }, { 16, 28, 0 } } }, - { { { 20, 0, 1 }, { 15, 31, 1 } } }, - { { { 20, 0, 2 }, { 15, 31, 0 } } }, - { { { 20, 0, 3 }, { 15, 31, 1 } } }, - { { { 20, 0, 4 }, { 16, 30, 1 } } }, - { { { 21, 0, 3 }, { 16, 30, 0 } } }, - { { { 21, 0, 2 }, { 18, 27, 1 } } }, - { { { 21, 0, 1 }, { 18, 27, 0 } } }, - { { { 21, 0, 0 }, { 16, 31, 0 } } }, - { { { 21, 0, 1 }, { 17, 30, 1 } } }, - { { { 21, 0, 2 }, { 17, 30, 0 } } }, - { { { 21, 0, 3 }, { 20, 24, 0 } } }, - { { { 21, 0, 4 }, { 17, 31, 1 } } }, - { { { 22, 0, 3 }, { 17, 31, 0 } } }, - { { { 22, 0, 2 }, { 17, 31, 1 } } }, - { { { 22, 0, 1 }, { 18, 30, 1 } } }, - { { { 22, 0, 0 }, { 18, 30, 0 } } }, - { { { 22, 0, 1 }, { 18, 31, 1 } } }, - { { { 22, 0, 2 }, { 18, 31, 0 } } }, - { { { 22, 0, 3 }, { 20, 27, 0 } } }, - { { { 22, 0, 4 }, { 19, 30, 1 } } }, - { { { 23, 0, 3 }, { 19, 30, 0 } } }, - { { { 23, 0, 2 }, { 20, 28, 0 } } }, - { { { 23, 0, 1 }, { 19, 31, 1 } } }, - { { { 23, 0, 0 }, { 19, 31, 0 } } }, - { { { 23, 0, 1 }, { 19, 31, 1 } } }, - { { { 23, 0, 2 }, { 20, 30, 1 } } }, - { { { 23, 0, 3 }, { 20, 30, 0 } } }, - { { { 23, 0, 4 }, { 22, 27, 1 } } }, - { { { 24, 0, 4 }, { 22, 27, 0 } } }, - { { { 24, 0, 3 }, { 20, 31, 0 } } }, - { { { 24, 0, 2 }, { 21, 30, 1 } } }, - { { { 24, 0, 1 }, { 21, 30, 0 } } }, - { { { 24, 0, 0 }, { 24, 24, 0 } } }, - { { { 24, 0, 1 }, { 21, 31, 1 } } }, - { { { 24, 0, 2 }, { 21, 31, 0 } } }, - { { { 24, 0, 3 }, { 21, 31, 1 } } }, - { { { 24, 0, 4 }, { 22, 30, 1 } } }, - { { { 25, 0, 3 }, { 22, 30, 0 } } }, - { { { 25, 0, 2 }, { 22, 31, 1 } } }, - { { { 25, 0, 1 }, { 22, 31, 0 } } }, - { { { 25, 0, 0 }, { 24, 27, 0 } } }, - { { { 25, 0, 1 }, { 23, 30, 1 } } }, - { { { 25, 0, 2 }, { 23, 30, 0 } } }, - { { { 25, 0, 3 }, { 24, 28, 0 } } }, - { { { 25, 0, 4 }, { 23, 31, 1 } } }, - { { { 26, 0, 3 }, { 23, 31, 0 } } }, - { { { 26, 0, 2 }, { 23, 31, 1 } } }, - { { { 26, 0, 1 }, { 24, 30, 1 } } }, - { { { 26, 0, 0 }, { 24, 30, 0 } } }, - { { { 26, 0, 1 }, { 26, 27, 1 } } }, - { { { 26, 0, 2 }, { 26, 27, 0 } } }, - { { { 26, 0, 3 }, { 24, 31, 0 } } }, - { { { 26, 0, 4 }, { 25, 30, 1 } } }, - { { { 27, 0, 3 }, { 25, 30, 0 } } }, - { { { 27, 0, 2 }, { 28, 24, 0 } } }, - { { { 27, 0, 1 }, { 25, 31, 1 } } }, - { { { 27, 0, 0 }, { 25, 31, 0 } } }, - { { { 27, 0, 1 }, { 25, 31, 1 } } }, - { { { 27, 0, 2 }, { 26, 30, 1 } } }, - { { { 27, 0, 3 }, { 26, 30, 0 } } }, - { { { 27, 0, 4 }, { 26, 31, 1 } } }, - { { { 28, 0, 4 }, { 26, 31, 0 } } }, - { { { 28, 0, 3 }, { 28, 27, 0 } } }, - { { { 28, 0, 2 }, { 27, 30, 1 } } }, - { { { 28, 0, 1 }, { 27, 30, 0 } } }, - { { { 28, 0, 0 }, { 28, 28, 0 } } }, - { { { 28, 0, 1 }, { 27, 31, 1 } } }, - { { { 28, 0, 2 }, { 27, 31, 0 } } }, - { { { 28, 0, 3 }, { 27, 31, 1 } } }, - { { { 28, 0, 4 }, { 28, 30, 1 } } }, - { { { 29, 0, 3 }, { 28, 30, 0 } } }, - { { { 29, 0, 2 }, { 30, 27, 1 } } }, - { { { 29, 0, 1 }, { 30, 27, 0 } } }, - { { { 29, 0, 0 }, { 28, 31, 0 } } }, - { { { 29, 0, 1 }, { 29, 30, 1 } } }, - { { { 29, 0, 2 }, { 29, 30, 0 } } }, - { { { 29, 0, 3 }, { 29, 30, 1 } } }, - { { { 29, 0, 4 }, { 29, 31, 1 } } }, - { { { 30, 0, 3 }, { 29, 31, 0 } } }, - { { { 30, 0, 2 }, { 29, 31, 1 } } }, - { { { 30, 0, 1 }, { 30, 30, 1 } } }, - { { { 30, 0, 0 }, { 30, 30, 0 } } }, - { { { 30, 0, 1 }, { 30, 31, 1 } } }, - { { { 30, 0, 2 }, { 30, 31, 0 } } }, - { { { 30, 0, 3 }, { 30, 31, 1 } } }, - { { { 30, 0, 4 }, { 31, 30, 1 } } }, - { { { 31, 0, 3 }, { 31, 30, 0 } } }, - { { { 31, 0, 2 }, { 31, 30, 1 } } }, - { { { 31, 0, 1 }, { 31, 31, 1 } } }, - { { { 31, 0, 0 }, { 31, 31, 0 } } } -}; - -static SingleColourLookup const lookup_6_4[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 1, 0 } } }, - { { { 0, 0, 2 }, { 0, 2, 0 } } }, - { { { 1, 0, 1 }, { 0, 3, 1 } } }, - { { { 1, 0, 0 }, { 0, 3, 0 } } }, - { { { 1, 0, 1 }, { 0, 4, 0 } } }, - { { { 1, 0, 2 }, { 0, 5, 0 } } }, - { { { 2, 0, 1 }, { 0, 6, 1 } } }, - { { { 2, 0, 0 }, { 0, 6, 0 } } }, - { { { 2, 0, 1 }, { 0, 7, 0 } } }, - { { { 2, 0, 2 }, { 0, 8, 0 } } }, - { { { 3, 0, 1 }, { 0, 9, 1 } } }, - { { { 3, 0, 0 }, { 0, 9, 0 } } }, - { { { 3, 0, 1 }, { 0, 10, 0 } } }, - { { { 3, 0, 2 }, { 0, 11, 0 } } }, - { { { 4, 0, 1 }, { 0, 12, 1 } } }, - { { { 4, 0, 0 }, { 0, 12, 0 } } }, - { { { 4, 0, 1 }, { 0, 13, 0 } } }, - { { { 4, 0, 2 }, { 0, 14, 0 } } }, - { { { 5, 0, 1 }, { 0, 15, 1 } } }, - { { { 5, 0, 0 }, { 0, 15, 0 } } }, - { { { 5, 0, 1 }, { 0, 16, 0 } } }, - { { { 5, 0, 2 }, { 1, 15, 0 } } }, - { { { 6, 0, 1 }, { 0, 17, 0 } } }, - { { { 6, 0, 0 }, { 0, 18, 0 } } }, - { { { 6, 0, 1 }, { 0, 19, 0 } } }, - { { { 6, 0, 2 }, { 3, 14, 0 } } }, - { { { 7, 0, 1 }, { 0, 20, 0 } } }, - { { { 7, 0, 0 }, { 0, 21, 0 } } }, - { { { 7, 0, 1 }, { 0, 22, 0 } } }, - { { { 7, 0, 2 }, { 4, 15, 0 } } }, - { { { 8, 0, 1 }, { 0, 23, 0 } } }, - { { { 8, 0, 0 }, { 0, 24, 0 } } }, - { { { 8, 0, 1 }, { 0, 25, 0 } } }, - { { { 8, 0, 2 }, { 6, 14, 0 } } }, - { { { 9, 0, 1 }, { 0, 26, 0 } } }, - { { { 9, 0, 0 }, { 0, 27, 0 } } }, - { { { 9, 0, 1 }, { 0, 28, 0 } } }, - { { { 9, 0, 2 }, { 7, 15, 0 } } }, - { { { 10, 0, 1 }, { 0, 29, 0 } } }, - { { { 10, 0, 0 }, { 0, 30, 0 } } }, - { { { 10, 0, 1 }, { 0, 31, 0 } } }, - { { { 10, 0, 2 }, { 9, 14, 0 } } }, - { { { 11, 0, 1 }, { 0, 32, 0 } } }, - { { { 11, 0, 0 }, { 0, 33, 0 } } }, - { { { 11, 0, 1 }, { 2, 30, 0 } } }, - { { { 11, 0, 2 }, { 0, 34, 0 } } }, - { { { 12, 0, 1 }, { 0, 35, 0 } } }, - { { { 12, 0, 0 }, { 0, 36, 0 } } }, - { { { 12, 0, 1 }, { 3, 31, 0 } } }, - { { { 12, 0, 2 }, { 0, 37, 0 } } }, - { { { 13, 0, 1 }, { 0, 38, 0 } } }, - { { { 13, 0, 0 }, { 0, 39, 0 } } }, - { { { 13, 0, 1 }, { 5, 30, 0 } } }, - { { { 13, 0, 2 }, { 0, 40, 0 } } }, - { { { 14, 0, 1 }, { 0, 41, 0 } } }, - { { { 14, 0, 0 }, { 0, 42, 0 } } }, - { { { 14, 0, 1 }, { 6, 31, 0 } } }, - { { { 14, 0, 2 }, { 0, 43, 0 } } }, - { { { 15, 0, 1 }, { 0, 44, 0 } } }, - { { { 15, 0, 0 }, { 0, 45, 0 } } }, - { { { 15, 0, 1 }, { 8, 30, 0 } } }, - { { { 15, 0, 2 }, { 0, 46, 0 } } }, - { { { 16, 0, 2 }, { 0, 47, 0 } } }, - { { { 16, 0, 1 }, { 1, 46, 0 } } }, - { { { 16, 0, 0 }, { 0, 48, 0 } } }, - { { { 16, 0, 1 }, { 0, 49, 0 } } }, - { { { 16, 0, 2 }, { 0, 50, 0 } } }, - { { { 17, 0, 1 }, { 2, 47, 0 } } }, - { { { 17, 0, 0 }, { 0, 51, 0 } } }, - { { { 17, 0, 1 }, { 0, 52, 0 } } }, - { { { 17, 0, 2 }, { 0, 53, 0 } } }, - { { { 18, 0, 1 }, { 4, 46, 0 } } }, - { { { 18, 0, 0 }, { 0, 54, 0 } } }, - { { { 18, 0, 1 }, { 0, 55, 0 } } }, - { { { 18, 0, 2 }, { 0, 56, 0 } } }, - { { { 19, 0, 1 }, { 5, 47, 0 } } }, - { { { 19, 0, 0 }, { 0, 57, 0 } } }, - { { { 19, 0, 1 }, { 0, 58, 0 } } }, - { { { 19, 0, 2 }, { 0, 59, 0 } } }, - { { { 20, 0, 1 }, { 7, 46, 0 } } }, - { { { 20, 0, 0 }, { 0, 60, 0 } } }, - { { { 20, 0, 1 }, { 0, 61, 0 } } }, - { { { 20, 0, 2 }, { 0, 62, 0 } } }, - { { { 21, 0, 1 }, { 8, 47, 0 } } }, - { { { 21, 0, 0 }, { 0, 63, 0 } } }, - { { { 21, 0, 1 }, { 1, 62, 0 } } }, - { { { 21, 0, 2 }, { 1, 63, 0 } } }, - { { { 22, 0, 1 }, { 10, 46, 0 } } }, - { { { 22, 0, 0 }, { 2, 62, 0 } } }, - { { { 22, 0, 1 }, { 2, 63, 0 } } }, - { { { 22, 0, 2 }, { 3, 62, 0 } } }, - { { { 23, 0, 1 }, { 11, 47, 0 } } }, - { { { 23, 0, 0 }, { 3, 63, 0 } } }, - { { { 23, 0, 1 }, { 4, 62, 0 } } }, - { { { 23, 0, 2 }, { 4, 63, 0 } } }, - { { { 24, 0, 1 }, { 13, 46, 0 } } }, - { { { 24, 0, 0 }, { 5, 62, 0 } } }, - { { { 24, 0, 1 }, { 5, 63, 0 } } }, - { { { 24, 0, 2 }, { 6, 62, 0 } } }, - { { { 25, 0, 1 }, { 14, 47, 0 } } }, - { { { 25, 0, 0 }, { 6, 63, 0 } } }, - { { { 25, 0, 1 }, { 7, 62, 0 } } }, - { { { 25, 0, 2 }, { 7, 63, 0 } } }, - { { { 26, 0, 1 }, { 16, 45, 0 } } }, - { { { 26, 0, 0 }, { 8, 62, 0 } } }, - { { { 26, 0, 1 }, { 8, 63, 0 } } }, - { { { 26, 0, 2 }, { 9, 62, 0 } } }, - { { { 27, 0, 1 }, { 16, 48, 0 } } }, - { { { 27, 0, 0 }, { 9, 63, 0 } } }, - { { { 27, 0, 1 }, { 10, 62, 0 } } }, - { { { 27, 0, 2 }, { 10, 63, 0 } } }, - { { { 28, 0, 1 }, { 16, 51, 0 } } }, - { { { 28, 0, 0 }, { 11, 62, 0 } } }, - { { { 28, 0, 1 }, { 11, 63, 0 } } }, - { { { 28, 0, 2 }, { 12, 62, 0 } } }, - { { { 29, 0, 1 }, { 16, 54, 0 } } }, - { { { 29, 0, 0 }, { 12, 63, 0 } } }, - { { { 29, 0, 1 }, { 13, 62, 0 } } }, - { { { 29, 0, 2 }, { 13, 63, 0 } } }, - { { { 30, 0, 1 }, { 16, 57, 0 } } }, - { { { 30, 0, 0 }, { 14, 62, 0 } } }, - { { { 30, 0, 1 }, { 14, 63, 0 } } }, - { { { 30, 0, 2 }, { 15, 62, 0 } } }, - { { { 31, 0, 1 }, { 16, 60, 0 } } }, - { { { 31, 0, 0 }, { 15, 63, 0 } } }, - { { { 31, 0, 1 }, { 24, 46, 0 } } }, - { { { 31, 0, 2 }, { 16, 62, 0 } } }, - { { { 32, 0, 2 }, { 16, 63, 0 } } }, - { { { 32, 0, 1 }, { 17, 62, 0 } } }, - { { { 32, 0, 0 }, { 25, 47, 0 } } }, - { { { 32, 0, 1 }, { 17, 63, 0 } } }, - { { { 32, 0, 2 }, { 18, 62, 0 } } }, - { { { 33, 0, 1 }, { 18, 63, 0 } } }, - { { { 33, 0, 0 }, { 27, 46, 0 } } }, - { { { 33, 0, 1 }, { 19, 62, 0 } } }, - { { { 33, 0, 2 }, { 19, 63, 0 } } }, - { { { 34, 0, 1 }, { 20, 62, 0 } } }, - { { { 34, 0, 0 }, { 28, 47, 0 } } }, - { { { 34, 0, 1 }, { 20, 63, 0 } } }, - { { { 34, 0, 2 }, { 21, 62, 0 } } }, - { { { 35, 0, 1 }, { 21, 63, 0 } } }, - { { { 35, 0, 0 }, { 30, 46, 0 } } }, - { { { 35, 0, 1 }, { 22, 62, 0 } } }, - { { { 35, 0, 2 }, { 22, 63, 0 } } }, - { { { 36, 0, 1 }, { 23, 62, 0 } } }, - { { { 36, 0, 0 }, { 31, 47, 0 } } }, - { { { 36, 0, 1 }, { 23, 63, 0 } } }, - { { { 36, 0, 2 }, { 24, 62, 0 } } }, - { { { 37, 0, 1 }, { 24, 63, 0 } } }, - { { { 37, 0, 0 }, { 32, 47, 0 } } }, - { { { 37, 0, 1 }, { 25, 62, 0 } } }, - { { { 37, 0, 2 }, { 25, 63, 0 } } }, - { { { 38, 0, 1 }, { 26, 62, 0 } } }, - { { { 38, 0, 0 }, { 32, 50, 0 } } }, - { { { 38, 0, 1 }, { 26, 63, 0 } } }, - { { { 38, 0, 2 }, { 27, 62, 0 } } }, - { { { 39, 0, 1 }, { 27, 63, 0 } } }, - { { { 39, 0, 0 }, { 32, 53, 0 } } }, - { { { 39, 0, 1 }, { 28, 62, 0 } } }, - { { { 39, 0, 2 }, { 28, 63, 0 } } }, - { { { 40, 0, 1 }, { 29, 62, 0 } } }, - { { { 40, 0, 0 }, { 32, 56, 0 } } }, - { { { 40, 0, 1 }, { 29, 63, 0 } } }, - { { { 40, 0, 2 }, { 30, 62, 0 } } }, - { { { 41, 0, 1 }, { 30, 63, 0 } } }, - { { { 41, 0, 0 }, { 32, 59, 0 } } }, - { { { 41, 0, 1 }, { 31, 62, 0 } } }, - { { { 41, 0, 2 }, { 31, 63, 0 } } }, - { { { 42, 0, 1 }, { 32, 61, 0 } } }, - { { { 42, 0, 0 }, { 32, 62, 0 } } }, - { { { 42, 0, 1 }, { 32, 63, 0 } } }, - { { { 42, 0, 2 }, { 41, 46, 0 } } }, - { { { 43, 0, 1 }, { 33, 62, 0 } } }, - { { { 43, 0, 0 }, { 33, 63, 0 } } }, - { { { 43, 0, 1 }, { 34, 62, 0 } } }, - { { { 43, 0, 2 }, { 42, 47, 0 } } }, - { { { 44, 0, 1 }, { 34, 63, 0 } } }, - { { { 44, 0, 0 }, { 35, 62, 0 } } }, - { { { 44, 0, 1 }, { 35, 63, 0 } } }, - { { { 44, 0, 2 }, { 44, 46, 0 } } }, - { { { 45, 0, 1 }, { 36, 62, 0 } } }, - { { { 45, 0, 0 }, { 36, 63, 0 } } }, - { { { 45, 0, 1 }, { 37, 62, 0 } } }, - { { { 45, 0, 2 }, { 45, 47, 0 } } }, - { { { 46, 0, 1 }, { 37, 63, 0 } } }, - { { { 46, 0, 0 }, { 38, 62, 0 } } }, - { { { 46, 0, 1 }, { 38, 63, 0 } } }, - { { { 46, 0, 2 }, { 47, 46, 0 } } }, - { { { 47, 0, 1 }, { 39, 62, 0 } } }, - { { { 47, 0, 0 }, { 39, 63, 0 } } }, - { { { 47, 0, 1 }, { 40, 62, 0 } } }, - { { { 47, 0, 2 }, { 48, 46, 0 } } }, - { { { 48, 0, 2 }, { 40, 63, 0 } } }, - { { { 48, 0, 1 }, { 41, 62, 0 } } }, - { { { 48, 0, 0 }, { 41, 63, 0 } } }, - { { { 48, 0, 1 }, { 48, 49, 0 } } }, - { { { 48, 0, 2 }, { 42, 62, 0 } } }, - { { { 49, 0, 1 }, { 42, 63, 0 } } }, - { { { 49, 0, 0 }, { 43, 62, 0 } } }, - { { { 49, 0, 1 }, { 48, 52, 0 } } }, - { { { 49, 0, 2 }, { 43, 63, 0 } } }, - { { { 50, 0, 1 }, { 44, 62, 0 } } }, - { { { 50, 0, 0 }, { 44, 63, 0 } } }, - { { { 50, 0, 1 }, { 48, 55, 0 } } }, - { { { 50, 0, 2 }, { 45, 62, 0 } } }, - { { { 51, 0, 1 }, { 45, 63, 0 } } }, - { { { 51, 0, 0 }, { 46, 62, 0 } } }, - { { { 51, 0, 1 }, { 48, 58, 0 } } }, - { { { 51, 0, 2 }, { 46, 63, 0 } } }, - { { { 52, 0, 1 }, { 47, 62, 0 } } }, - { { { 52, 0, 0 }, { 47, 63, 0 } } }, - { { { 52, 0, 1 }, { 48, 61, 0 } } }, - { { { 52, 0, 2 }, { 48, 62, 0 } } }, - { { { 53, 0, 1 }, { 56, 47, 0 } } }, - { { { 53, 0, 0 }, { 48, 63, 0 } } }, - { { { 53, 0, 1 }, { 49, 62, 0 } } }, - { { { 53, 0, 2 }, { 49, 63, 0 } } }, - { { { 54, 0, 1 }, { 58, 46, 0 } } }, - { { { 54, 0, 0 }, { 50, 62, 0 } } }, - { { { 54, 0, 1 }, { 50, 63, 0 } } }, - { { { 54, 0, 2 }, { 51, 62, 0 } } }, - { { { 55, 0, 1 }, { 59, 47, 0 } } }, - { { { 55, 0, 0 }, { 51, 63, 0 } } }, - { { { 55, 0, 1 }, { 52, 62, 0 } } }, - { { { 55, 0, 2 }, { 52, 63, 0 } } }, - { { { 56, 0, 1 }, { 61, 46, 0 } } }, - { { { 56, 0, 0 }, { 53, 62, 0 } } }, - { { { 56, 0, 1 }, { 53, 63, 0 } } }, - { { { 56, 0, 2 }, { 54, 62, 0 } } }, - { { { 57, 0, 1 }, { 62, 47, 0 } } }, - { { { 57, 0, 0 }, { 54, 63, 0 } } }, - { { { 57, 0, 1 }, { 55, 62, 0 } } }, - { { { 57, 0, 2 }, { 55, 63, 0 } } }, - { { { 58, 0, 1 }, { 56, 62, 1 } } }, - { { { 58, 0, 0 }, { 56, 62, 0 } } }, - { { { 58, 0, 1 }, { 56, 63, 0 } } }, - { { { 58, 0, 2 }, { 57, 62, 0 } } }, - { { { 59, 0, 1 }, { 57, 63, 1 } } }, - { { { 59, 0, 0 }, { 57, 63, 0 } } }, - { { { 59, 0, 1 }, { 58, 62, 0 } } }, - { { { 59, 0, 2 }, { 58, 63, 0 } } }, - { { { 60, 0, 1 }, { 59, 62, 1 } } }, - { { { 60, 0, 0 }, { 59, 62, 0 } } }, - { { { 60, 0, 1 }, { 59, 63, 0 } } }, - { { { 60, 0, 2 }, { 60, 62, 0 } } }, - { { { 61, 0, 1 }, { 60, 63, 1 } } }, - { { { 61, 0, 0 }, { 60, 63, 0 } } }, - { { { 61, 0, 1 }, { 61, 62, 0 } } }, - { { { 61, 0, 2 }, { 61, 63, 0 } } }, - { { { 62, 0, 1 }, { 62, 62, 1 } } }, - { { { 62, 0, 0 }, { 62, 62, 0 } } }, - { { { 62, 0, 1 }, { 62, 63, 0 } } }, - { { { 62, 0, 2 }, { 63, 62, 0 } } }, - { { { 63, 0, 1 }, { 63, 63, 1 } } }, - { { { 63, 0, 0 }, { 63, 63, 0 } } } -}; diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp deleted file mode 100644 index 1de1da3e52..0000000000 --- a/thirdparty/squish/squish.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include <string.h> -#include "squish.h" -#include "colourset.h" -#include "maths.h" -#include "rangefit.h" -#include "clusterfit.h" -#include "colourblock.h" -#include "alpha.h" -#include "singlecolourfit.h" - -namespace squish { - -static int FixFlags( int flags ) -{ - // grab the flag bits - int method = flags & ( kDxt1 | kDxt3 | kDxt5 | kBc4 | kBc5 ); - int fit = flags & ( kColourIterativeClusterFit | kColourClusterFit | kColourRangeFit ); - int extra = flags & kWeightColourByAlpha; - - // set defaults - if ( method != kDxt3 - && method != kDxt5 - && method != kBc4 - && method != kBc5 ) - { - method = kDxt1; - } - if( fit != kColourRangeFit && fit != kColourIterativeClusterFit ) - fit = kColourClusterFit; - - // done - return method | fit | extra; -} - -void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* metric ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - if ( ( flags & ( kBc4 | kBc5 ) ) != 0 ) - { - u8 alpha[16*4]; - for( int i = 0; i < 16; ++i ) - { - alpha[i*4 + 3] = rgba[i*4 + 0]; // copy R to A - } - - u8* rBlock = reinterpret_cast< u8* >( block ); - CompressAlphaDxt5( alpha, mask, rBlock ); - - if ( ( flags & ( kBc5 ) ) != 0 ) - { - for( int i = 0; i < 16; ++i ) - { - alpha[i*4 + 3] = rgba[i*4 + 1]; // copy G to A - } - - u8* gBlock = reinterpret_cast< u8* >( block ) + 8; - CompressAlphaDxt5( alpha, mask, gBlock ); - } - - return; - } - - // get the block locations - void* colourBlock = block; - void* alphaBlock = block; - if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 ) - colourBlock = reinterpret_cast< u8* >( block ) + 8; - - // create the minimal point set - ColourSet colours( rgba, mask, flags ); - - // check the compression type and compress colour - if( colours.GetCount() == 1 ) - { - // always do a single colour fit - SingleColourFit fit( &colours, flags ); - fit.Compress( colourBlock ); - } - else if( ( flags & kColourRangeFit ) != 0 || colours.GetCount() == 0 ) - { - // do a range fit - RangeFit fit( &colours, flags, metric ); - fit.Compress( colourBlock ); - } - else - { - // default to a cluster fit (could be iterative or not) - ClusterFit fit( &colours, flags, metric ); - fit.Compress( colourBlock ); - } - - // compress alpha separately if necessary - if( ( flags & kDxt3 ) != 0 ) - CompressAlphaDxt3( rgba, mask, alphaBlock ); - else if( ( flags & kDxt5 ) != 0 ) - CompressAlphaDxt5( rgba, mask, alphaBlock ); -} - -void Decompress( u8* rgba, void const* block, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // get the block locations - void const* colourBlock = block; - void const* alphaBlock = block; - if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 ) - colourBlock = reinterpret_cast< u8 const* >( block ) + 8; - - // decompress colour - // -- GODOT start -- - //DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); - if(( flags & ( kBc4 ) ) != 0) - DecompressColourBc4( rgba, colourBlock); - else if(( flags & ( kBc5 ) ) != 0) - DecompressColourBc5( rgba, colourBlock); - else - DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); - // -- GODOT end -- - - // decompress alpha separately if necessary - if( ( flags & kDxt3 ) != 0 ) - DecompressAlphaDxt3( rgba, alphaBlock ); - else if( ( flags & kDxt5 ) != 0 ) - DecompressAlphaDxt5( rgba, alphaBlock ); -} - -int GetStorageRequirements( int width, int height, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // compute the storage requirements - int blockcount = ( ( width + 3 )/4 ) * ( ( height + 3 )/4 ); - int blocksize = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16; - return blockcount*blocksize; -} - -void CopyRGBA( u8 const* source, u8* dest, int flags ) -{ - if (flags & kSourceBGRA) - { - // convert from bgra to rgba - dest[0] = source[2]; - dest[1] = source[1]; - dest[2] = source[0]; - dest[3] = source[3]; - } - else - { - for( int i = 0; i < 4; ++i ) - *dest++ = *source++; - } -} - -void CompressImage( u8 const* rgba, int width, int height, int pitch, void* blocks, int flags, float* metric ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // loop over blocks -#ifdef SQUISH_USE_OPENMP -# pragma omp parallel for -#endif - for( int y = 0; y < height; y += 4 ) - { - // initialise the block output - u8* targetBlock = reinterpret_cast< u8* >( blocks ); - int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16; - targetBlock += ( (y / 4) * ( (width + 3) / 4) ) * bytesPerBlock; - - for( int x = 0; x < width; x += 4 ) - { - // build the 4x4 block of pixels - u8 sourceRgba[16*4]; - u8* targetPixel = sourceRgba; - int mask = 0; - for( int py = 0; py < 4; ++py ) - { - for( int px = 0; px < 4; ++px ) - { - // get the source pixel in the image - int sx = x + px; - int sy = y + py; - - // enable if we're in the image - if( sx < width && sy < height ) - { - // copy the rgba value - u8 const* sourcePixel = rgba + pitch*sy + 4*sx; - CopyRGBA(sourcePixel, targetPixel, flags); - // enable this pixel - mask |= ( 1 << ( 4*py + px ) ); - } - - // advance to the next pixel - targetPixel += 4; - } - } - - // compress it into the output - CompressMasked( sourceRgba, mask, targetBlock, flags, metric ); - - // advance - targetBlock += bytesPerBlock; - } - } -} - -void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags, float* metric ) -{ - CompressImage(rgba, width, height, width*4, blocks, flags, metric); -} - -void DecompressImage( u8* rgba, int width, int height, int pitch, void const* blocks, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // loop over blocks -#ifdef SQUISH_USE_OPENMP -# pragma omp parallel for -#endif - for( int y = 0; y < height; y += 4 ) - { - // initialise the block input - u8 const* sourceBlock = reinterpret_cast< u8 const* >( blocks ); - int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16; - sourceBlock += ( (y / 4) * ( (width + 3) / 4) ) * bytesPerBlock; - - for( int x = 0; x < width; x += 4 ) - { - // decompress the block - u8 targetRgba[4*16]; - Decompress( targetRgba, sourceBlock, flags ); - - // write the decompressed pixels to the correct image locations - u8 const* sourcePixel = targetRgba; - for( int py = 0; py < 4; ++py ) - { - for( int px = 0; px < 4; ++px ) - { - // get the target location - int sx = x + px; - int sy = y + py; - - // write if we're in the image - if( sx < width && sy < height ) - { - // copy the rgba value - u8* targetPixel = rgba + pitch*sy + 4*sx; - CopyRGBA(sourcePixel, targetPixel, flags); - } - - // advance to the next pixel - sourcePixel += 4; - } - } - - // advance - sourceBlock += bytesPerBlock; - } - } -} - -void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags ) -{ - DecompressImage( rgba, width, height, width*4, blocks, flags ); -} - -static double ErrorSq(double x, double y) -{ - return (x - y) * (x - y); -} - -static void ComputeBlockWMSE(u8 const *original, u8 const *compressed, unsigned int w, unsigned int h, double &cmse, double &amse) -{ - // Computes the MSE for the block and weights it by the variance of the original block. - // If the variance of the original block is less than 4 (i.e. a standard deviation of 1 per channel) - // then the block is close to being a single colour. Quantisation errors in single colour blocks - // are easier to see than similar errors in blocks that contain more colours, particularly when there - // are many such blocks in a large area (eg a blue sky background) as they cause banding. Given that - // banding is easier to see than small errors in "complex" blocks, we weight the errors by a factor - // of 5. This implies that images with large, single colour areas will have a higher potential WMSE - // than images with lots of detail. - - cmse = amse = 0; - unsigned int sum_p[4]; // per channel sum of pixels - unsigned int sum_p2[4]; // per channel sum of pixels squared - memset(sum_p, 0, sizeof(sum_p)); - memset(sum_p2, 0, sizeof(sum_p2)); - for( unsigned int py = 0; py < 4; ++py ) - { - for( unsigned int px = 0; px < 4; ++px ) - { - if( px < w && py < h ) - { - double pixelCMSE = 0; - for( int i = 0; i < 3; ++i ) - { - pixelCMSE += ErrorSq(original[i], compressed[i]); - sum_p[i] += original[i]; - sum_p2[i] += (unsigned int)original[i]*original[i]; - } - if( original[3] == 0 && compressed[3] == 0 ) - pixelCMSE = 0; // transparent in both, so colour is inconsequential - amse += ErrorSq(original[3], compressed[3]); - cmse += pixelCMSE; - sum_p[3] += original[3]; - sum_p2[3] += (unsigned int)original[3]*original[3]; - } - original += 4; - compressed += 4; - } - } - unsigned int variance = 0; - for( int i = 0; i < 4; ++i ) - variance += w*h*sum_p2[i] - sum_p[i]*sum_p[i]; - if( variance < 4 * w * w * h * h ) - { - amse *= 5; - cmse *= 5; - } -} - -void ComputeMSE( u8 const *rgba, int width, int height, int pitch, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE ) -{ - // fix any bad flags - flags = FixFlags( flags ); - colourMSE = alphaMSE = 0; - - // initialise the block input - squish::u8 const* sourceBlock = dxt; - int bytesPerBlock = ( ( flags & squish::kDxt1 ) != 0 ) ? 8 : 16; - - // loop over blocks - for( int y = 0; y < height; y += 4 ) - { - for( int x = 0; x < width; x += 4 ) - { - // decompress the block - u8 targetRgba[4*16]; - Decompress( targetRgba, sourceBlock, flags ); - u8 const* sourcePixel = targetRgba; - - // copy across to a similar pixel block - u8 originalRgba[4*16]; - u8* originalPixel = originalRgba; - - for( int py = 0; py < 4; ++py ) - { - for( int px = 0; px < 4; ++px ) - { - int sx = x + px; - int sy = y + py; - if( sx < width && sy < height ) - { - u8 const* targetPixel = rgba + pitch*sy + 4*sx; - CopyRGBA(targetPixel, originalPixel, flags); - } - sourcePixel += 4; - originalPixel += 4; - } - } - - // compute the weighted MSE of the block - double blockCMSE, blockAMSE; - ComputeBlockWMSE(originalRgba, targetRgba, std::min(4, width - x), std::min(4, height - y), blockCMSE, blockAMSE); - colourMSE += blockCMSE; - alphaMSE += blockAMSE; - // advance - sourceBlock += bytesPerBlock; - } - } - colourMSE /= (width * height * 3); - alphaMSE /= (width * height); -} - -void ComputeMSE( u8 const *rgba, int width, int height, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE ) -{ - ComputeMSE(rgba, width, height, width*4, dxt, flags, colourMSE, alphaMSE); -} - -} // namespace squish diff --git a/thirdparty/squish/squish.h b/thirdparty/squish/squish.h deleted file mode 100644 index 14c9bb59fb..0000000000 --- a/thirdparty/squish/squish.h +++ /dev/null @@ -1,309 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_H -#define SQUISH_H - -//! All squish API functions live in this namespace. -namespace squish { - -// ----------------------------------------------------------------------------- - -//! Typedef a quantity that is a single unsigned byte. -typedef unsigned char u8; - -// ----------------------------------------------------------------------------- - -enum -{ - //! Use DXT1 compression. - kDxt1 = ( 1 << 0 ), - - //! Use DXT3 compression. - kDxt3 = ( 1 << 1 ), - - //! Use DXT5 compression. - kDxt5 = ( 1 << 2 ), - - //! Use BC4 compression. - kBc4 = ( 1 << 3 ), - - //! Use BC5 compression. - kBc5 = ( 1 << 4 ), - - //! Use a slow but high quality colour compressor (the default). - kColourClusterFit = ( 1 << 5 ), - - //! Use a fast but low quality colour compressor. - kColourRangeFit = ( 1 << 6 ), - - //! Weight the colour by alpha during cluster fit (disabled by default). - kWeightColourByAlpha = ( 1 << 7 ), - - //! Use a very slow but very high quality colour compressor. - kColourIterativeClusterFit = ( 1 << 8 ), - - //! Source is BGRA rather than RGBA - kSourceBGRA = ( 1 << 9 ) -}; - -// ----------------------------------------------------------------------------- - -/*! @brief Compresses a 4x4 block of pixels. - - @param rgba The rgba values of the 16 source pixels. - @param mask The valid pixel mask. - @param block Storage for the compressed DXT block. - @param flags Compression flags. - @param metric An optional perceptual metric. - - The source pixels should be presented as a contiguous array of 16 rgba - values, with each component as 1 byte each. In memory this should be: - - { r1, g1, b1, a1, .... , r16, g16, b16, a16 } - - The mask parameter enables only certain pixels within the block. The lowest - bit enables the first pixel and so on up to the 16th bit. Bits beyond the - 16th bit are ignored. Pixels that are not enabled are allowed to take - arbitrary colours in the output block. An example of how this can be used - is in the CompressImage function to disable pixels outside the bounds of - the image when the width or height is not divisible by 4. - - The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, - however, DXT1 will be used by default if none is specified. When using DXT1 - compression, 8 bytes of storage are required for the compressed DXT block. - DXT3 and DXT5 compression require 16 bytes of storage per block. - - The flags parameter can also specify a preferred colour compressor to use - when fitting the RGB components of the data. Possible colour compressors - are: kColourClusterFit (the default), kColourRangeFit (very fast, low - quality) or kColourIterativeClusterFit (slowest, best quality). - - When using kColourClusterFit or kColourIterativeClusterFit, an additional - flag can be specified to weight the importance of each pixel by its alpha - value. For images that are rendered using alpha blending, this can - significantly increase the perceived quality. - - The metric parameter can be used to weight the relative importance of each - colour channel, or pass NULL to use the default uniform weight of - { 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that - allowed either uniform or "perceptual" weights with the fixed values - { 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a - contiguous array of 3 floats. -*/ -void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* metric = 0 ); - -// ----------------------------------------------------------------------------- - -/*! @brief Compresses a 4x4 block of pixels. - - @param rgba The rgba values of the 16 source pixels. - @param block Storage for the compressed DXT block. - @param flags Compression flags. - @param metric An optional perceptual metric. - - The source pixels should be presented as a contiguous array of 16 rgba - values, with each component as 1 byte each. In memory this should be: - - { r1, g1, b1, a1, .... , r16, g16, b16, a16 } - - The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, - however, DXT1 will be used by default if none is specified. When using DXT1 - compression, 8 bytes of storage are required for the compressed DXT block. - DXT3 and DXT5 compression require 16 bytes of storage per block. - - The flags parameter can also specify a preferred colour compressor to use - when fitting the RGB components of the data. Possible colour compressors - are: kColourClusterFit (the default), kColourRangeFit (very fast, low - quality) or kColourIterativeClusterFit (slowest, best quality). - - When using kColourClusterFit or kColourIterativeClusterFit, an additional - flag can be specified to weight the importance of each pixel by its alpha - value. For images that are rendered using alpha blending, this can - significantly increase the perceived quality. - - The metric parameter can be used to weight the relative importance of each - colour channel, or pass NULL to use the default uniform weight of - { 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that - allowed either uniform or "perceptual" weights with the fixed values - { 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a - contiguous array of 3 floats. - - This method is an inline that calls CompressMasked with a mask of 0xffff, - provided for compatibility with older versions of squish. -*/ -inline void Compress( u8 const* rgba, void* block, int flags, float* metric = 0 ) -{ - CompressMasked( rgba, 0xffff, block, flags, metric ); -} - -// ----------------------------------------------------------------------------- - -/*! @brief Decompresses a 4x4 block of pixels. - - @param rgba Storage for the 16 decompressed pixels. - @param block The compressed DXT block. - @param flags Compression flags. - - The decompressed pixels will be written as a contiguous array of 16 rgba - values, with each component as 1 byte each. In memory this is: - - { r1, g1, b1, a1, .... , r16, g16, b16, a16 } - - The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, - however, DXT1 will be used by default if none is specified. All other flags - are ignored. -*/ -void Decompress( u8* rgba, void const* block, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Computes the amount of compressed storage required. - - @param width The width of the image. - @param height The height of the image. - @param flags Compression flags. - - The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, - however, DXT1 will be used by default if none is specified. All other flags - are ignored. - - Most DXT images will be a multiple of 4 in each dimension, but this - function supports arbitrary size images by allowing the outer blocks to - be only partially used. -*/ -int GetStorageRequirements( int width, int height, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Compresses an image in memory. - - @param rgba The pixels of the source. - @param width The width of the source image. - @param height The height of the source image. - @param pitch The pitch of the source image. - @param blocks Storage for the compressed output. - @param flags Compression flags. - @param metric An optional perceptual metric. - - The source pixels should be presented as a contiguous array of width*height - rgba values, with each component as 1 byte each. In memory this should be: - - { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height - - The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, - however, DXT1 will be used by default if none is specified. When using DXT1 - compression, 8 bytes of storage are required for each compressed DXT block. - DXT3 and DXT5 compression require 16 bytes of storage per block. - - The flags parameter can also specify a preferred colour compressor to use - when fitting the RGB components of the data. Possible colour compressors - are: kColourClusterFit (the default), kColourRangeFit (very fast, low - quality) or kColourIterativeClusterFit (slowest, best quality). - - When using kColourClusterFit or kColourIterativeClusterFit, an additional - flag can be specified to weight the importance of each pixel by its alpha - value. For images that are rendered using alpha blending, this can - significantly increase the perceived quality. - - The metric parameter can be used to weight the relative importance of each - colour channel, or pass NULL to use the default uniform weight of - { 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that - allowed either uniform or "perceptual" weights with the fixed values - { 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a - contiguous array of 3 floats. - - Internally this function calls squish::CompressMasked for each block, which - allows for pixels outside the image to take arbitrary values. The function - squish::GetStorageRequirements can be called to compute the amount of memory - to allocate for the compressed output. - - Note on compression quality: When compressing textures with - libsquish it is recommended to apply a gamma-correction - beforehand. This will reduce the blockiness in dark areas. The - level of necessary gamma-correction is platform dependent. For - example, a gamma correction with gamma = 0.5 before compression - and gamma = 2.0 after decompression yields good results on the - Windows platform but for other platforms like MacOS X a different - gamma value may be more suitable. -*/ -void CompressImage( u8 const* rgba, int width, int height, int pitch, void* blocks, int flags, float* metric = 0 ); -void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags, float* metric = 0 ); - -// ----------------------------------------------------------------------------- - -/*! @brief Decompresses an image in memory. - - @param rgba Storage for the decompressed pixels. - @param width The width of the source image. - @param height The height of the source image. - @param pitch The pitch of the decompressed pixels. - @param blocks The compressed DXT blocks. - @param flags Compression flags. - - The decompressed pixels will be written as a contiguous array of width*height - 16 rgba values, with each component as 1 byte each. In memory this is: - - { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height - - The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, - however, DXT1 will be used by default if none is specified. All other flags - are ignored. - - Internally this function calls squish::Decompress for each block. -*/ -void DecompressImage( u8* rgba, int width, int height, int pitch, void const* blocks, int flags ); -void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Computes MSE of an compressed image in memory. - - @param rgba The original image pixels. - @param width The width of the source image. - @param height The height of the source image. - @param pitch The pitch of the source image. - @param dxt The compressed dxt blocks - @param flags Compression flags. - @param colourMSE The MSE of the colour values. - @param alphaMSE The MSE of the alpha values. - - The colour MSE and alpha MSE are computed across all pixels. The colour MSE is - averaged across all rgb values (i.e. colourMSE = sum sum_k ||dxt.k - rgba.k||/3) - - The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, - however, DXT1 will be used by default if none is specified. All other flags - are ignored. - - Internally this function calls squish::Decompress for each block. -*/ -void ComputeMSE(u8 const *rgba, int width, int height, int pitch, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE); -void ComputeMSE(u8 const *rgba, int width, int height, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE); - -// ----------------------------------------------------------------------------- - -} // namespace squish - -#endif // ndef SQUISH_H diff --git a/thirdparty/vulkan/patches/VKEnumStringHelper-use-volk.patch b/thirdparty/vulkan/patches/VKEnumStringHelper-use-godot-vulkan.patch index 8517b277d0..6b56d60181 100644 --- a/thirdparty/vulkan/patches/VKEnumStringHelper-use-volk.patch +++ b/thirdparty/vulkan/patches/VKEnumStringHelper-use-godot-vulkan.patch @@ -1,17 +1,13 @@ diff --git a/thirdparty/vulkan/vk_enum_string_helper.h b/thirdparty/vulkan/vk_enum_string_helper.h -index 9d2af46344..d61dbb1290 100644 +index 8026787ad4..7a54b12a38 100644 --- a/thirdparty/vulkan/vk_enum_string_helper.h +++ b/thirdparty/vulkan/vk_enum_string_helper.h -@@ -13,7 +13,11 @@ +@@ -13,7 +13,7 @@ #ifdef __cplusplus #include <string> #endif -#include <vulkan/vulkan.h> -+#ifdef USE_VOLK -+ #include <volk.h> -+#else -+ #include <vulkan/vulkan.h> -+#endif ++#include "drivers/vulkan/godot_vulkan.h" static inline const char* string_VkResult(VkResult input_value) { switch (input_value) { case VK_SUCCESS: diff --git a/thirdparty/vulkan/patches/VMA-use-volk.patch b/thirdparty/vulkan/patches/VMA-use-godot-vulkan.patch index e2e5ea5ad4..a6c546e3d8 100644 --- a/thirdparty/vulkan/patches/VMA-use-volk.patch +++ b/thirdparty/vulkan/patches/VMA-use-godot-vulkan.patch @@ -1,17 +1,18 @@ diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h -index 711f486571..e5eaa80e74 100644 +index 2307325d4e..ecb84094b9 100644 --- a/thirdparty/vulkan/vk_mem_alloc.h +++ b/thirdparty/vulkan/vk_mem_alloc.h -@@ -127,7 +127,11 @@ See documentation chapter: \ref statistics. +@@ -122,12 +122,12 @@ for user-defined purpose without allocating any real GPU memory. + See documentation chapter: \ref statistics. + */ + ++#include "drivers/vulkan/godot_vulkan.h" + + #ifdef __cplusplus extern "C" { #endif -#include <vulkan/vulkan.h> -+#ifdef USE_VOLK -+ #include <volk.h> -+#else -+ #include <vulkan/vulkan.h> -+#endif #if !defined(VMA_VULKAN_VERSION) #if defined(VK_VERSION_1_3) diff --git a/thirdparty/vulkan/vk_enum_string_helper.h b/thirdparty/vulkan/vk_enum_string_helper.h index 598453e745..7a54b12a38 100644 --- a/thirdparty/vulkan/vk_enum_string_helper.h +++ b/thirdparty/vulkan/vk_enum_string_helper.h @@ -13,11 +13,7 @@ #ifdef __cplusplus #include <string> #endif -#ifdef USE_VOLK - #include <volk.h> -#else - #include <vulkan/vulkan.h> -#endif +#include "drivers/vulkan/godot_vulkan.h" static inline const char* string_VkResult(VkResult input_value) { switch (input_value) { case VK_SUCCESS: diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h index b39b73b17d..ecb84094b9 100644 --- a/thirdparty/vulkan/vk_mem_alloc.h +++ b/thirdparty/vulkan/vk_mem_alloc.h @@ -122,16 +122,12 @@ for user-defined purpose without allocating any real GPU memory. See documentation chapter: \ref statistics. */ +#include "drivers/vulkan/godot_vulkan.h" #ifdef __cplusplus extern "C" { #endif -#ifdef USE_VOLK - #include <volk.h> -#else - #include <vulkan/vulkan.h> -#endif #if !defined(VMA_VULKAN_VERSION) #if defined(VK_VERSION_1_3) |