1 #ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH 2 #define OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH 3 4 #include "Common.hh" 5 #include "ValueFormat.hh" 6 7 namespace OT { 8 namespace Layout { 9 namespace GPOS_impl { 10 11 struct SinglePosFormat1 : ValueBase 12 { 13 protected: 14 HBUINT16 format; /* Format identifier--format = 1 */ 15 Offset16To<Coverage> 16 coverage; /* Offset to Coverage table--from 17 * beginning of subtable */ 18 ValueFormat valueFormat; /* Defines the types of data in the 19 * ValueRecord */ 20 ValueRecord values; /* Defines positioning 21 * value(s)--applied to all glyphs in 22 * the Coverage table */ 23 public: 24 DEFINE_SIZE_ARRAY (6, values); 25 sanitizeOT::Layout::GPOS_impl::SinglePosFormat126 bool sanitize (hb_sanitize_context_t *c) const 27 { 28 TRACE_SANITIZE (this); 29 return_trace (c->check_struct (this) && 30 coverage.sanitize (c, this) && 31 hb_barrier () && 32 /* The coverage table may use a range to represent a set 33 * of glyphs, which means a small number of bytes can 34 * generate a large glyph set. Manually modify the 35 * sanitizer max ops to take this into account. 36 * 37 * Note: This check *must* be right after coverage sanitize. */ 38 c->check_ops ((this + coverage).get_population () >> 1) && 39 valueFormat.sanitize_value (c, this, values)); 40 41 } 42 intersectsOT::Layout::GPOS_impl::SinglePosFormat143 bool intersects (const hb_set_t *glyphs) const 44 { return (this+coverage).intersects (glyphs); } 45 closure_lookupsOT::Layout::GPOS_impl::SinglePosFormat146 void closure_lookups (hb_closure_lookups_context_t *c) const {} collect_variation_indicesOT::Layout::GPOS_impl::SinglePosFormat147 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 48 { 49 if (!valueFormat.has_device ()) return; 50 51 hb_set_t intersection; 52 (this+coverage).intersect_set (*c->glyph_set, intersection); 53 if (!intersection) return; 54 55 valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ())); 56 } 57 collect_glyphsOT::Layout::GPOS_impl::SinglePosFormat158 void collect_glyphs (hb_collect_glyphs_context_t *c) const 59 { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; } 60 get_coverageOT::Layout::GPOS_impl::SinglePosFormat161 const Coverage &get_coverage () const { return this+coverage; } 62 get_value_formatOT::Layout::GPOS_impl::SinglePosFormat163 ValueFormat get_value_format () const { return valueFormat; } 64 applyOT::Layout::GPOS_impl::SinglePosFormat165 bool apply (hb_ot_apply_context_t *c) const 66 { 67 TRACE_APPLY (this); 68 hb_buffer_t *buffer = c->buffer; 69 unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); 70 if (likely (index == NOT_COVERED)) return_trace (false); 71 72 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) 73 { 74 c->buffer->message (c->font, 75 "positioning glyph at %u", 76 c->buffer->idx); 77 } 78 79 valueFormat.apply_value (c, this, values, buffer->cur_pos()); 80 81 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) 82 { 83 c->buffer->message (c->font, 84 "positioned glyph at %u", 85 c->buffer->idx); 86 } 87 88 buffer->idx++; 89 return_trace (true); 90 } 91 92 bool position_singleOT::Layout::GPOS_impl::SinglePosFormat193 position_single (hb_font_t *font, 94 hb_blob_t *table_blob, 95 hb_direction_t direction, 96 hb_codepoint_t gid, 97 hb_glyph_position_t &pos) const 98 { 99 unsigned int index = (this+coverage).get_coverage (gid); 100 if (likely (index == NOT_COVERED)) return false; 101 102 /* This is ugly... */ 103 hb_buffer_t buffer; 104 buffer.props.direction = direction; 105 OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob); 106 107 valueFormat.apply_value (&c, this, values, pos); 108 return true; 109 } 110 111 template<typename Iterator, 112 typename SrcLookup, 113 hb_requires (hb_is_iterator (Iterator))> serializeOT::Layout::GPOS_impl::SinglePosFormat1114 void serialize (hb_serialize_context_t *c, 115 const SrcLookup *src, 116 Iterator it, 117 ValueFormat newFormat, 118 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) 119 { 120 if (unlikely (!c->extend_min (this))) return; 121 if (unlikely (!c->check_assign (valueFormat, 122 newFormat, 123 HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; 124 125 for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second)) 126 { 127 src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); 128 // Only serialize the first entry in the iterator, the rest are assumed to 129 // be the same. 130 break; 131 } 132 133 auto glyphs = 134 + it 135 | hb_map_retains_sorting (hb_first) 136 ; 137 138 coverage.serialize_serialize (c, glyphs); 139 } 140 subsetOT::Layout::GPOS_impl::SinglePosFormat1141 bool subset (hb_subset_context_t *c) const 142 { 143 TRACE_SUBSET (this); 144 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); 145 const hb_map_t &glyph_map = *c->plan->glyph_map; 146 147 hb_set_t intersection; 148 (this+coverage).intersect_set (glyphset, intersection); 149 150 unsigned new_format = valueFormat; 151 152 if (c->plan->normalized_coords) 153 { 154 new_format = valueFormat.get_effective_format (values.arrayZ, false, false, this, &c->plan->layout_variation_idx_delta_map); 155 } 156 /* do not strip hints for VF */ 157 else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING) 158 { 159 hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r')); 160 bool has_fvar = (blob != hb_blob_get_empty ()); 161 hb_blob_destroy (blob); 162 163 bool strip = !has_fvar; 164 /* special case: strip hints when a VF has no GDEF varstore after 165 * subsetting*/ 166 if (has_fvar && !c->plan->has_gdef_varstore) 167 strip = true; 168 new_format = valueFormat.get_effective_format (values.arrayZ, 169 strip, /* strip hints */ 170 true, /* strip empty */ 171 this, nullptr); 172 } 173 174 auto it = 175 + hb_iter (intersection) 176 | hb_map_retains_sorting (glyph_map) 177 | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ()))) 178 ; 179 180 bool ret = bool (it); 181 SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format); 182 return_trace (ret); 183 } 184 }; 185 186 } 187 } 188 } 189 190 #endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH */ 191