VARC.hh (6307B)
1 #ifndef OT_VAR_VARC_VARC_HH 2 #define OT_VAR_VARC_VARC_HH 3 4 #include "../../../hb-decycler.hh" 5 #include "../../../hb-geometry.hh" 6 #include "../../../hb-ot-layout-common.hh" 7 #include "../../../hb-ot-glyf-table.hh" 8 #include "../../../hb-ot-cff2-table.hh" 9 #include "../../../hb-ot-cff1-table.hh" 10 11 #include "coord-setter.hh" 12 13 namespace OT { 14 15 //namespace Var { 16 17 /* 18 * VARC -- Variable Composites 19 * https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md 20 */ 21 22 #ifndef HB_NO_VAR_COMPOSITES 23 24 struct hb_varc_scratch_t 25 { 26 hb_vector_t<unsigned> axisIndices; 27 hb_vector_t<float> axisValues; 28 hb_glyf_scratch_t glyf_scratch; 29 }; 30 31 struct hb_varc_context_t 32 { 33 hb_font_t *font; 34 hb_draw_session_t *draw_session; 35 hb_extents_t<> *extents; 36 mutable hb_decycler_t decycler; 37 mutable signed edges_left; 38 mutable signed depth_left; 39 hb_varc_scratch_t &scratch; 40 }; 41 42 struct VarComponent 43 { 44 enum class flags_t : uint32_t 45 { 46 RESET_UNSPECIFIED_AXES = 1u << 0, 47 HAVE_AXES = 1u << 1, 48 AXIS_VALUES_HAVE_VARIATION = 1u << 2, 49 TRANSFORM_HAS_VARIATION = 1u << 3, 50 HAVE_TRANSLATE_X = 1u << 4, 51 HAVE_TRANSLATE_Y = 1u << 5, 52 HAVE_ROTATION = 1u << 6, 53 HAVE_CONDITION = 1u << 7, 54 HAVE_SCALE_X = 1u << 8, 55 HAVE_SCALE_Y = 1u << 9, 56 HAVE_TCENTER_X = 1u << 10, 57 HAVE_TCENTER_Y = 1u << 11, 58 GID_IS_24BIT = 1u << 12, 59 HAVE_SKEW_X = 1u << 13, 60 HAVE_SKEW_Y = 1u << 14, 61 RESERVED_MASK = ~((1u << 15) - 1), 62 }; 63 64 HB_INTERNAL hb_ubytes_t 65 get_path_at (const hb_varc_context_t &c, 66 hb_codepoint_t parent_gid, 67 hb_array_t<const int> coords, 68 hb_transform_t<> transform, 69 hb_ubytes_t record, 70 hb_scalar_cache_t *cache = nullptr) const; 71 }; 72 73 struct VarCompositeGlyph 74 { 75 static void 76 get_path_at (const hb_varc_context_t &c, 77 hb_codepoint_t gid, 78 hb_array_t<const int> coords, 79 hb_transform_t<> transform, 80 hb_ubytes_t record, 81 hb_scalar_cache_t *cache) 82 { 83 while (record) 84 { 85 const VarComponent &comp = * (const VarComponent *) (record.arrayZ); 86 record = comp.get_path_at (c, 87 gid, 88 coords, transform, 89 record, 90 cache); 91 } 92 } 93 }; 94 95 HB_MARK_AS_FLAG_T (VarComponent::flags_t); 96 97 struct VARC 98 { 99 friend struct VarComponent; 100 101 static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); 102 103 HB_INTERNAL bool 104 get_path_at (const hb_varc_context_t &c, 105 hb_codepoint_t gid, 106 hb_array_t<const int> coords, 107 hb_transform_t<> transform = HB_TRANSFORM_IDENTITY, 108 hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID, 109 hb_scalar_cache_t *parent_cache = nullptr) const; 110 111 bool 112 get_path (hb_font_t *font, 113 hb_codepoint_t gid, 114 hb_draw_session_t &draw_session, 115 hb_varc_scratch_t &scratch) const 116 { 117 hb_varc_context_t c {font, 118 &draw_session, 119 nullptr, 120 hb_decycler_t {}, 121 HB_MAX_GRAPH_EDGE_COUNT, 122 HB_MAX_NESTING_LEVEL, 123 scratch}; 124 125 return get_path_at (c, gid, 126 hb_array (font->coords, font->num_coords)); 127 } 128 129 bool 130 get_extents (hb_font_t *font, 131 hb_codepoint_t gid, 132 hb_extents_t<> *extents, 133 hb_varc_scratch_t &scratch) const 134 { 135 hb_varc_context_t c {font, 136 nullptr, 137 extents, 138 hb_decycler_t {}, 139 HB_MAX_GRAPH_EDGE_COUNT, 140 HB_MAX_NESTING_LEVEL, 141 scratch}; 142 143 return get_path_at (c, gid, 144 hb_array (font->coords, font->num_coords)); 145 } 146 147 bool sanitize (hb_sanitize_context_t *c) const 148 { 149 TRACE_SANITIZE (this); 150 return_trace (version.sanitize (c) && 151 hb_barrier () && 152 version.major == 1 && 153 coverage.sanitize (c, this) && 154 varStore.sanitize (c, this) && 155 conditionList.sanitize (c, this) && 156 axisIndicesList.sanitize (c, this) && 157 glyphRecords.sanitize (c, this)); 158 } 159 160 struct accelerator_t 161 { 162 friend struct VarComponent; 163 164 accelerator_t (hb_face_t *face) 165 { 166 table = hb_sanitize_context_t ().reference_table<VARC> (face); 167 } 168 ~accelerator_t () 169 { 170 auto *scratch = cached_scratch.get_relaxed (); 171 if (scratch) 172 { 173 scratch->~hb_varc_scratch_t (); 174 hb_free (scratch); 175 } 176 177 table.destroy (); 178 } 179 180 bool 181 get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const 182 { 183 if (!table->has_data ()) return false; 184 185 auto *scratch = acquire_scratch (); 186 if (unlikely (!scratch)) return true; 187 bool ret = table->get_path (font, gid, draw_session, *scratch); 188 release_scratch (scratch); 189 return ret; 190 } 191 192 bool 193 get_extents (hb_font_t *font, 194 hb_codepoint_t gid, 195 hb_glyph_extents_t *extents) const 196 { 197 #ifndef HB_NO_DRAW 198 if (!table->has_data ()) return false; 199 200 hb_extents_t<> f_extents; 201 202 auto *scratch = acquire_scratch (); 203 if (unlikely (!scratch)) return true; 204 bool ret = table->get_extents (font, gid, &f_extents, *scratch); 205 release_scratch (scratch); 206 207 if (ret) 208 *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0); 209 210 return ret; 211 #else 212 return false; 213 #endif 214 } 215 216 private: 217 218 hb_varc_scratch_t *acquire_scratch () const 219 { 220 hb_varc_scratch_t *scratch = cached_scratch.get_acquire (); 221 222 if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) 223 { 224 scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t)); 225 if (unlikely (!scratch)) 226 return nullptr; 227 } 228 229 return scratch; 230 } 231 void release_scratch (hb_varc_scratch_t *scratch) const 232 { 233 if (!cached_scratch.cmpexch (nullptr, scratch)) 234 { 235 scratch->~hb_varc_scratch_t (); 236 hb_free (scratch); 237 } 238 } 239 240 private: 241 hb_blob_ptr_t<VARC> table; 242 mutable hb_atomic_t<hb_varc_scratch_t *> cached_scratch; 243 }; 244 245 bool has_data () const { return version.major != 0; } 246 247 protected: 248 FixedVersion<> version; /* Version identifier */ 249 Offset32To<Coverage> coverage; 250 Offset32To<MultiItemVariationStore> varStore; 251 Offset32To<ConditionList> conditionList; 252 Offset32To<TupleList> axisIndicesList; 253 Offset32To<CFF2Index/*Of<VarCompositeGlyph>*/> glyphRecords; 254 public: 255 DEFINE_SIZE_STATIC (24); 256 }; 257 258 struct VARC_accelerator_t : VARC::accelerator_t { 259 VARC_accelerator_t (hb_face_t *face) : VARC::accelerator_t (face) {} 260 }; 261 262 #endif 263 264 //} 265 266 } 267 268 #endif /* OT_VAR_VARC_VARC_HH */