| /* | |
| * 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 ItemVariationStore 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) && | |
| hb_barrier () && | |
| likely (version.major == 1) && | |
| c->check_struct (this) && | |
| hb_barrier () && | |
| 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 ItemVariationStore& src_var_store = this+varStore; | |
| if (!item_vars.instantiate (src_var_store, c->plan)) | |
| 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<ItemVariationStore> | |
| 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 */ |