#ifndef OT_VAR_VARC_VARC_HH #define OT_VAR_VARC_VARC_HH #include "../../../hb-ot-layout-common.hh" #include "../../../hb-ot-glyf-table.hh" #include "../../../hb-ot-cff2-table.hh" #include "../../../hb-ot-cff1-table.hh" #include "coord-setter.hh" namespace OT { //namespace Var { /* * VARC -- Variable Composites * https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md */ #ifndef HB_NO_VAR_COMPOSITES struct VarComponent { enum class flags_t : uint32_t { RESET_UNSPECIFIED_AXES = 1u << 0, HAVE_AXES = 1u << 1, AXIS_VALUES_HAVE_VARIATION = 1u << 2, TRANSFORM_HAS_VARIATION = 1u << 3, HAVE_TRANSLATE_X = 1u << 4, HAVE_TRANSLATE_Y = 1u << 5, HAVE_ROTATION = 1u << 6, HAVE_CONDITION = 1u << 7, HAVE_SCALE_X = 1u << 8, HAVE_SCALE_Y = 1u << 9, HAVE_TCENTER_X = 1u << 10, HAVE_TCENTER_Y = 1u << 11, GID_IS_24BIT = 1u << 12, HAVE_SKEW_X = 1u << 13, HAVE_SKEW_Y = 1u << 14, RESERVED_MASK = ~((1u << 15) - 1), }; HB_INTERNAL hb_ubytes_t get_path_at (hb_font_t *font, hb_codepoint_t parent_gid, hb_draw_session_t &draw_session, hb_array_t coords, hb_ubytes_t record, hb_set_t *visited, signed *edges_left, signed depth_left, VarRegionList::cache_t *cache = nullptr) const; }; struct VarCompositeGlyph { static void get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords, hb_ubytes_t record, hb_set_t *visited, signed *edges_left, signed depth_left, VarRegionList::cache_t *cache = nullptr) { while (record) { const VarComponent &comp = * (const VarComponent *) (record.arrayZ); record = comp.get_path_at (font, glyph, draw_session, coords, record, visited, edges_left, depth_left, cache); } } }; HB_MARK_AS_FLAG_T (VarComponent::flags_t); struct VARC { friend struct VarComponent; static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords, hb_codepoint_t parent_glyph = HB_CODEPOINT_INVALID, hb_set_t *visited = nullptr, signed *edges_left = nullptr, signed depth_left = HB_MAX_NESTING_LEVEL) const { hb_set_t stack_set; if (visited == nullptr) visited = &stack_set; signed stack_edges = HB_MAX_GRAPH_EDGE_COUNT; if (edges_left == nullptr) edges_left = &stack_edges; // Don't recurse on the same glyph. unsigned idx = glyph == parent_glyph ? NOT_COVERED : (this+coverage).get_coverage (glyph); if (idx == NOT_COVERED) { if (!font->face->table.glyf->get_path_at (font, glyph, draw_session, coords)) #ifndef HB_NO_CFF if (!font->face->table.cff2->get_path_at (font, glyph, draw_session, coords)) if (!font->face->table.cff1->get_path (font, glyph, draw_session)) // Doesn't have variations #endif return false; return true; } if (depth_left <= 0) return true; if (*edges_left <= 0) return true; (*edges_left)--; if (visited->has (glyph) || visited->in_error ()) return true; visited->add (glyph); hb_ubytes_t record = (this+glyphRecords)[idx]; VarRegionList::cache_t *cache = record.length >= 64 ? // Heuristic (this+varStore).create_cache () : nullptr; VarCompositeGlyph::get_path_at (font, glyph, draw_session, coords, record, visited, edges_left, depth_left, cache); (this+varStore).destroy_cache (cache); visited->del (glyph); return true; } bool get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const { return get_path_at (font, gid, draw_session, hb_array (font->coords, font->num_coords)); } bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const { funcs->push_clip_glyph (data, gid, font); funcs->color (data, true, foreground); funcs->pop_clip (data); return true; } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && hb_barrier () && version.major == 1 && coverage.sanitize (c, this) && varStore.sanitize (c, this) && conditionList.sanitize (c, this) && axisIndicesList.sanitize (c, this) && glyphRecords.sanitize (c, this)); } protected: FixedVersion<> version; /* Version identifier */ Offset32To coverage; Offset32To varStore; Offset32To conditionList; Offset32To axisIndicesList; Offset32To*/> glyphRecords; public: DEFINE_SIZE_STATIC (24); }; #endif //} } #endif /* OT_VAR_VARC_VARC_HH */