1 #ifndef OT_VAR_VARC_VARC_HH 2 #define OT_VAR_VARC_VARC_HH 3 4 #include "../../../hb-ot-layout-common.hh" 5 #include "../../../hb-ot-glyf-table.hh" 6 #include "../../../hb-ot-cff2-table.hh" 7 #include "../../../hb-ot-cff1-table.hh" 8 9 #include "coord-setter.hh" 10 11 namespace OT { 12 13 //namespace Var { 14 15 /* 16 * VARC -- Variable Composites 17 * https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md 18 */ 19 20 #ifndef HB_NO_VAR_COMPOSITES 21 22 struct VarComponent 23 { 24 enum class flags_t : uint32_t 25 { 26 RESET_UNSPECIFIED_AXES = 1u << 0, 27 HAVE_AXES = 1u << 1, 28 AXIS_VALUES_HAVE_VARIATION = 1u << 2, 29 TRANSFORM_HAS_VARIATION = 1u << 3, 30 HAVE_TRANSLATE_X = 1u << 4, 31 HAVE_TRANSLATE_Y = 1u << 5, 32 HAVE_ROTATION = 1u << 6, 33 HAVE_CONDITION = 1u << 7, 34 HAVE_SCALE_X = 1u << 8, 35 HAVE_SCALE_Y = 1u << 9, 36 HAVE_TCENTER_X = 1u << 10, 37 HAVE_TCENTER_Y = 1u << 11, 38 GID_IS_24BIT = 1u << 12, 39 HAVE_SKEW_X = 1u << 13, 40 HAVE_SKEW_Y = 1u << 14, 41 RESERVED_MASK = ~((1u << 15) - 1), 42 }; 43 44 HB_INTERNAL hb_ubytes_t 45 get_path_at (hb_font_t *font, 46 hb_codepoint_t parent_gid, 47 hb_draw_session_t &draw_session, 48 hb_array_t<const int> coords, 49 hb_ubytes_t record, 50 hb_set_t *visited, 51 signed *edges_left, 52 signed depth_left, 53 VarRegionList::cache_t *cache = nullptr) const; 54 }; 55 56 struct VarCompositeGlyph 57 { 58 static void get_path_atOT::VarCompositeGlyph59 get_path_at (hb_font_t *font, 60 hb_codepoint_t glyph, 61 hb_draw_session_t &draw_session, 62 hb_array_t<const int> coords, 63 hb_ubytes_t record, 64 hb_set_t *visited, 65 signed *edges_left, 66 signed depth_left, 67 VarRegionList::cache_t *cache = nullptr) 68 { 69 while (record) 70 { 71 const VarComponent &comp = * (const VarComponent *) (record.arrayZ); 72 record = comp.get_path_at (font, glyph, 73 draw_session, coords, 74 record, 75 visited, edges_left, depth_left, cache); 76 } 77 } 78 }; 79 80 HB_MARK_AS_FLAG_T (VarComponent::flags_t); 81 82 struct VARC 83 { 84 friend struct VarComponent; 85 86 static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); 87 88 bool get_path_atOT::VARC89 get_path_at (hb_font_t *font, 90 hb_codepoint_t glyph, 91 hb_draw_session_t &draw_session, 92 hb_array_t<const int> coords, 93 hb_codepoint_t parent_glyph = HB_CODEPOINT_INVALID, 94 hb_set_t *visited = nullptr, 95 signed *edges_left = nullptr, 96 signed depth_left = HB_MAX_NESTING_LEVEL) const 97 { 98 hb_set_t stack_set; 99 if (visited == nullptr) 100 visited = &stack_set; 101 signed stack_edges = HB_MAX_GRAPH_EDGE_COUNT; 102 if (edges_left == nullptr) 103 edges_left = &stack_edges; 104 105 // Don't recurse on the same glyph. 106 unsigned idx = glyph == parent_glyph ? 107 NOT_COVERED : 108 (this+coverage).get_coverage (glyph); 109 if (idx == NOT_COVERED) 110 { 111 if (!font->face->table.glyf->get_path_at (font, glyph, draw_session, coords)) 112 #ifndef HB_NO_CFF 113 if (!font->face->table.cff2->get_path_at (font, glyph, draw_session, coords)) 114 if (!font->face->table.cff1->get_path (font, glyph, draw_session)) // Doesn't have variations 115 #endif 116 return false; 117 return true; 118 } 119 120 if (depth_left <= 0) 121 return true; 122 123 if (*edges_left <= 0) 124 return true; 125 (*edges_left)--; 126 127 if (visited->has (glyph) || visited->in_error ()) 128 return true; 129 visited->add (glyph); 130 131 hb_ubytes_t record = (this+glyphRecords)[idx]; 132 133 VarRegionList::cache_t *cache = record.length >= 64 ? // Heuristic 134 (this+varStore).create_cache () 135 : nullptr; 136 137 VarCompositeGlyph::get_path_at (font, glyph, 138 draw_session, coords, 139 record, 140 visited, edges_left, depth_left, 141 cache); 142 143 (this+varStore).destroy_cache (cache); 144 145 visited->del (glyph); 146 147 return true; 148 } 149 150 bool get_pathOT::VARC151 get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const 152 { return get_path_at (font, gid, draw_session, hb_array (font->coords, font->num_coords)); } 153 paint_glyphOT::VARC154 bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const 155 { 156 funcs->push_clip_glyph (data, gid, font); 157 funcs->color (data, true, foreground); 158 funcs->pop_clip (data); 159 160 return true; 161 } 162 sanitizeOT::VARC163 bool sanitize (hb_sanitize_context_t *c) const 164 { 165 TRACE_SANITIZE (this); 166 return_trace (version.sanitize (c) && 167 hb_barrier () && 168 version.major == 1 && 169 coverage.sanitize (c, this) && 170 varStore.sanitize (c, this) && 171 conditionList.sanitize (c, this) && 172 axisIndicesList.sanitize (c, this) && 173 glyphRecords.sanitize (c, this)); 174 } 175 176 protected: 177 FixedVersion<> version; /* Version identifier */ 178 Offset32To<Coverage> coverage; 179 Offset32To<MultiItemVariationStore> varStore; 180 Offset32To<ConditionList> conditionList; 181 Offset32To<TupleList> axisIndicesList; 182 Offset32To<CFF2Index/*Of<VarCompositeGlyph>*/> glyphRecords; 183 public: 184 DEFINE_SIZE_STATIC (24); 185 }; 186 187 #endif 188 189 //} 190 191 } 192 193 #endif /* OT_VAR_VARC_VARC_HH */ 194