| /* |
| * Copyright © 2017 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_MVAR_TABLE_HH |
| #define HB_OT_VAR_MVAR_TABLE_HH |
| |
| #include "hb-ot-var-common.hh" |
| |
| |
| namespace OT { |
| |
| |
| struct VariationValueRecord |
| { |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (c->check_struct (this)); |
| } |
| |
| bool subset (hb_subset_context_t *c, |
| const hb_map_t& varidx_map) const |
| { |
| TRACE_SUBSET (this); |
| auto *out = c->serializer->embed (*this); |
| if (unlikely (!out)) return_trace (false); |
| |
| hb_codepoint_t *new_idx; |
| return_trace (c->serializer->check_assign (out->varIdx, |
| (varidx_map.has (varIdx, &new_idx)) ? *new_idx : HB_OT_LAYOUT_NO_VARIATIONS_INDEX, |
| HB_SERIALIZE_ERROR_INT_OVERFLOW)); |
| } |
| |
| public: |
| Tag valueTag; /* Four-byte tag identifying a font-wide measure. */ |
| VarIdx varIdx; /* Outer/inner index into VariationStore item. */ |
| |
| public: |
| DEFINE_SIZE_STATIC (8); |
| }; |
| |
| |
| /* |
| * MVAR -- Metrics Variations |
| * https://docs.microsoft.com/en-us/typography/opentype/spec/mvar |
| */ |
| #define HB_OT_TAG_MVAR HB_TAG('M','V','A','R') |
| |
| struct MVAR |
| { |
| static constexpr hb_tag_t tableTag = HB_OT_TAG_MVAR; |
| |
| bool sanitize (hb_sanitize_context_t *c) const |
| { |
| TRACE_SANITIZE (this); |
| return_trace (version.sanitize (c) && |
| likely (version.major == 1) && |
| c->check_struct (this) && |
| valueRecordSize >= VariationValueRecord::static_size && |
| varStore.sanitize (c, this) && |
| c->check_range (valuesZ.arrayZ, |
| valueRecordCount, |
| valueRecordSize)); |
| } |
| |
| bool subset (hb_subset_context_t *c) const |
| { |
| TRACE_SUBSET (this); |
| #ifdef HB_NO_VAR |
| return_trace (false); |
| #endif |
| |
| if (c->plan->all_axes_pinned) |
| return_trace (false); |
| |
| MVAR *out = c->serializer->start_embed (*this); |
| if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| out->version = version; |
| out->reserved = reserved; |
| out->valueRecordSize = valueRecordSize; |
| out->valueRecordCount = valueRecordCount; |
| |
| item_variations_t item_vars; |
| const VariationStore& src_var_store = this+varStore; |
| if (!item_vars.create_from_item_varstore (src_var_store, c->plan->axes_old_index_tag_map)) |
| return_trace (false); |
| |
| if (!item_vars.instantiate (c->plan->axes_location, c->plan->axes_triple_distances)) |
| return_trace (false); |
| |
| if (!item_vars.optimize ()) |
| return_trace (false); |
| |
| /* serialize varstore */ |
| if (!out->varStore.serialize_serialize (c->serializer, item_vars.has_long_word (), |
| c->plan->axis_tags, |
| item_vars.get_region_list (), |
| item_vars.get_vardata_encodings ())) |
| return_trace (false); |
| |
| /* serialize value records array */ |
| unsigned value_rec_count = valueRecordCount; |
| const VariationValueRecord *record = reinterpret_cast<const VariationValueRecord*> (valuesZ.arrayZ); |
| for (unsigned i = 0; i < value_rec_count; i++) |
| { |
| if (!record->subset (c, item_vars.get_varidx_map ())) return_trace (false); |
| record++; |
| } |
| return_trace (true); |
| } |
| |
| float get_var (hb_tag_t tag, |
| const int *coords, unsigned int coord_count) const |
| { |
| const VariationValueRecord *record; |
| record = (VariationValueRecord *) hb_bsearch (tag, |
| (const VariationValueRecord *) |
| (const HBUINT8 *) valuesZ, |
| valueRecordCount, valueRecordSize, |
| tag_compare); |
| if (!record) |
| return 0.; |
| |
| return (this+varStore).get_delta (record->varIdx, coords, coord_count); |
| } |
| |
| protected: |
| static int tag_compare (const void *pa, const void *pb) |
| { |
| const hb_tag_t *a = (const hb_tag_t *) pa; |
| const Tag *b = (const Tag *) pb; |
| return b->cmp (*a); |
| } |
| |
| protected: |
| FixedVersion<>version; /* Version of the metrics variation table |
| * initially set to 0x00010000u */ |
| HBUINT16 reserved; /* Not used; set to 0. */ |
| HBUINT16 valueRecordSize;/* The size in bytes of each value record — |
| * must be greater than zero. */ |
| HBUINT16 valueRecordCount;/* The number of value records — may be zero. */ |
| Offset16To<VariationStore> |
| varStore; /* Offset to item variation store table. */ |
| UnsizedArrayOf<HBUINT8> |
| valuesZ; /* Array of value records. The records must be |
| * in binary order of their valueTag field. */ |
| |
| public: |
| DEFINE_SIZE_ARRAY (12, valuesZ); |
| }; |
| |
| } /* namespace OT */ |
| |
| |
| #define HB_ADD_MVAR_VAR(tag, field) \ |
| c->serializer->check_assign (table->field, \ |
| roundf (table->field + \ |
| MVAR.get_var (tag, \ |
| c->plan->normalized_coords.arrayZ, \ |
| c->plan->normalized_coords.length)), \ |
| HB_SERIALIZE_ERROR_INT_OVERFLOW) |
| |
| |
| #endif /* HB_OT_VAR_MVAR_TABLE_HH */ |