diff --git a/src/OT/Var/VARC/VARC.cc b/src/OT/Var/VARC/VARC.cc index d9b54b983..dacad44cf 100644 --- a/src/OT/Var/VARC/VARC.cc +++ b/src/OT/Var/VARC/VARC.cc @@ -130,7 +130,8 @@ hb_transforming_pen_get_funcs () hb_ubytes_t VarComponent::get_path_at (hb_font_t *font, hb_codepoint_t parent_gid, - hb_draw_session_t &draw_session, + hb_draw_session_t *draw_session, + hb_extents_t *extents, hb_array_t coords, hb_transform_t total_transform, hb_ubytes_t total_record, @@ -323,7 +324,8 @@ VarComponent::get_path_at (hb_font_t *font, component_coords.arrayZ == coords.arrayZ; VARC.get_path_at (font, gid, - draw_session, component_coords, total_transform, + draw_session, extents, + component_coords, total_transform, parent_gid, decycler, edges_left, depth_left - 1, scratch, @@ -339,7 +341,8 @@ VarComponent::get_path_at (hb_font_t *font, bool VARC::get_path_at (hb_font_t *font, hb_codepoint_t glyph, - hb_draw_session_t &draw_session, + hb_draw_session_t *draw_session, + hb_extents_t *extents, hb_array_t coords, hb_transform_t transform, hb_codepoint_t parent_glyph, @@ -355,21 +358,38 @@ VARC::get_path_at (hb_font_t *font, (this+coverage).get_coverage (glyph); if (idx == NOT_COVERED) { - // Build a transforming pen to apply the transform. - hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs (); - hb_transforming_pen_context_t context {transform, - draw_session.funcs, - draw_session.draw_data, - &draw_session.st}; - hb_draw_session_t transformer_session {transformer_funcs, &context}; - hb_draw_session_t &shape_draw_session = transform.is_identity () ? draw_session : transformer_session; + if (draw_session) + { + // Build a transforming pen to apply the transform. + hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs (); + hb_transforming_pen_context_t context {transform, + draw_session->funcs, + draw_session->draw_data, + &draw_session->st}; + hb_draw_session_t transformer_session {transformer_funcs, &context}; + hb_draw_session_t &shape_draw_session = transform.is_identity () ? *draw_session : transformer_session; - if (!font->face->table.glyf->get_path_at (font, glyph, shape_draw_session, coords, scratch)) + if (!font->face->table.glyf->get_path_at (font, glyph, shape_draw_session, coords, scratch)) #ifndef HB_NO_CFF - if (!font->face->table.cff2->get_path_at (font, glyph, shape_draw_session, coords)) - if (!font->face->table.cff1->get_path (font, glyph, shape_draw_session)) // Doesn't have variations + if (!font->face->table.cff2->get_path_at (font, glyph, shape_draw_session, coords)) + if (!font->face->table.cff1->get_path (font, glyph, shape_draw_session)) // Doesn't have variations #endif - return false; + return false; + } + if (extents) + { + hb_glyph_extents_t glyph_extents; + if (!font->face->table.glyf->get_extents_at (font, glyph, &glyph_extents, coords)) +#ifndef HB_NO_CFF + if (!font->face->table.cff2->get_extents_at (font, glyph, &glyph_extents, coords)) + if (!font->face->table.cff1->get_extents (font, glyph, &glyph_extents)) // Doesn't have variations +#endif + return false; + + hb_extents_t comp_extents (glyph_extents); + transform.transform_extents (comp_extents); + extents->union_ (comp_extents); + } return true; } @@ -394,7 +414,8 @@ VARC::get_path_at (hb_font_t *font, transform.scale (font->x_multf, font->y_multf); VarCompositeGlyph::get_path_at (font, glyph, - draw_session, coords, transform, + draw_session, extents, + coords, transform, record, decycler, edges_left, depth_left, scratch, diff --git a/src/OT/Var/VARC/VARC.hh b/src/OT/Var/VARC/VARC.hh index e3756bb09..8678195cd 100644 --- a/src/OT/Var/VARC/VARC.hh +++ b/src/OT/Var/VARC/VARC.hh @@ -46,7 +46,8 @@ struct VarComponent HB_INTERNAL hb_ubytes_t get_path_at (hb_font_t *font, hb_codepoint_t parent_gid, - hb_draw_session_t &draw_session, + hb_draw_session_t *draw_session, + hb_extents_t *extents, hb_array_t coords, hb_transform_t transform, hb_ubytes_t record, @@ -62,7 +63,8 @@ struct VarCompositeGlyph static void get_path_at (hb_font_t *font, hb_codepoint_t glyph, - hb_draw_session_t &draw_session, + hb_draw_session_t *draw_session, + hb_extents_t *extents, hb_array_t coords, hb_transform_t transform, hb_ubytes_t record, @@ -76,7 +78,8 @@ struct VarCompositeGlyph { const VarComponent &comp = * (const VarComponent *) (record.arrayZ); record = comp.get_path_at (font, glyph, - draw_session, coords, transform, + draw_session, extents, + coords, transform, record, decycler, edges_left, depth_left, scratch, cache); } @@ -94,7 +97,8 @@ struct VARC HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, - hb_draw_session_t &draw_session, + hb_draw_session_t *draw_session, + hb_extents_t *extents, hb_array_t coords, hb_transform_t transform, hb_codepoint_t parent_glyph, @@ -115,7 +119,30 @@ struct VARC return get_path_at (font, gid, - draw_session, + &draw_session, + nullptr, + hb_array (font->coords, font->num_coords), + HB_TRANSFORM_IDENTITY, + HB_CODEPOINT_INVALID, + &decycler, + &edges, + HB_MAX_NESTING_LEVEL, + scratch); + } + + bool + get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_extents_t *extents, + hb_glyf_scratch_t &scratch) const + { + hb_decycler_t decycler; + signed edges = HB_MAX_GRAPH_EDGE_COUNT; + + return get_path_at (font, + gid, + nullptr, + extents, hb_array (font->coords, font->num_coords), HB_TRANSFORM_IDENTITY, HB_CODEPOINT_INVALID, @@ -163,31 +190,57 @@ struct VARC { if (!table->has_data ()) return false; - hb_glyf_scratch_t *scratch; - - // Borrow the cached strach buffer. - { - scratch = cached_scratch.get_acquire (); - if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) - { - scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t)); - if (unlikely (!scratch)) - return true; - } - } - + auto *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; bool ret = table->get_path (font, gid, draw_session, *scratch); + release_scratch (scratch); + return ret; + } - // Put it back. - if (!cached_scratch.cmpexch (nullptr, scratch)) - { - scratch->~hb_glyf_scratch_t (); - hb_free (scratch); - } + bool + get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents) const + { + if (!table->has_data ()) return false; + + hb_extents_t f_extents; + + auto *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = table->get_extents (font, gid, &f_extents, *scratch); + release_scratch (scratch); + + if (ret) + *extents = f_extents.to_glyph_extents (); return ret; } + private: + + hb_glyf_scratch_t *acquire_scratch () const + { + hb_glyf_scratch_t *scratch = cached_scratch.get_acquire (); + + if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) + { + scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t)); + if (unlikely (!scratch)) + return nullptr; + } + + return scratch; + } + void release_scratch (hb_glyf_scratch_t *scratch) const + { + if (!cached_scratch.cmpexch (scratch, nullptr)) + { + scratch->~hb_glyf_scratch_t (); + hb_free (scratch); + } + } + private: hb_blob_ptr_t table; hb_atomic_ptr_t cached_scratch; diff --git a/src/OT/glyf/glyf.hh b/src/OT/glyf/glyf.hh index fe4ae7b8c..c1847b275 100644 --- a/src/OT/glyf/glyf.hh +++ b/src/OT/glyf/glyf.hh @@ -429,16 +429,27 @@ struct glyf_accelerator_t } public: - bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const + + bool get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents) const + { return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); } + + bool get_extents_at (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents, + hb_array_t coords) const { if (unlikely (gid >= num_glyphs)) return false; #ifndef HB_NO_VAR - if (font->num_coords) + if (coords) { hb_glyf_scratch_t scratch; - return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true), - hb_array (font->coords, font->num_coords), + return get_points (font, + gid, + points_aggregator_t (font, extents, nullptr, true), + coords, scratch); } #endif diff --git a/src/hb-geometry.hh b/src/hb-geometry.hh index 2f7fcb328..11bce0cf7 100644 --- a/src/hb-geometry.hh +++ b/src/hb-geometry.hh @@ -30,6 +30,11 @@ struct hb_extents_t { hb_extents_t () {} + hb_extents_t (const hb_glyph_extents_t &extents) : + xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)), + ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)), + xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)), + ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {} hb_extents_t (float xmin, float ymin, float xmax, float ymax) : xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {} @@ -38,6 +43,12 @@ struct hb_extents_t void union_ (const hb_extents_t &o) { + if (o.is_empty ()) return; + if (is_empty ()) + { + *this = o; + return; + } xmin = hb_min (xmin, o.xmin); ymin = hb_min (ymin, o.ymin); xmax = hb_max (xmax, o.xmax); @@ -46,6 +57,11 @@ struct hb_extents_t void intersect (const hb_extents_t &o) { + if (o.is_empty () || is_empty ()) + { + *this = hb_extents_t {}; + return; + } xmin = hb_max (xmin, o.xmin); ymin = hb_max (ymin, o.ymin); xmax = hb_min (xmax, o.xmax); @@ -69,6 +85,15 @@ struct hb_extents_t } } + hb_glyph_extents_t to_glyph_extents () const + { + hb_position_t x0 = (hb_position_t) roundf (xmin); + hb_position_t y0 = (hb_position_t) roundf (ymin); + hb_position_t x1 = (hb_position_t) roundf (xmax); + hb_position_t y1 = (hb_position_t) roundf (ymax); + return hb_glyph_extents_t {x0, y0, x1 - x0, y1 - y0}; + } + float xmin = 0.f; float ymin = 0.f; float xmax = -1.f; diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc index 57023cb91..4157bd3b5 100644 --- a/src/hb-ot-cff2-table.cc +++ b/src/hb-ot-cff2-table.cc @@ -102,6 +102,14 @@ struct cff2_cs_opset_extents_t : cff2_cs_opset_tcoords, font->num_coords)); +} + +bool OT::cff2::accelerator_t::get_extents_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_array_t coords) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ @@ -112,7 +120,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, unsigned int fd = fdSelect->get_fd (glyph); const hb_ubytes_t str = (*charStrings)[glyph]; - cff2_cs_interp_env_t env (str, *this, fd, font->coords, font->num_coords); + cff2_cs_interp_env_t env (str, *this, fd, coords.arrayZ, coords.length); cff2_cs_interpreter_t interp (env); cff2_extents_param_t param; if (unlikely (!interp.interpret (param))) return false; diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh index 0074d5bd8..83b1e2b81 100644 --- a/src/hb-ot-cff2-table.hh +++ b/src/hb-ot-cff2-table.hh @@ -518,6 +518,10 @@ struct cff2 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; + HB_INTERNAL bool get_extents_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_array_t coords) const; HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords) const; }; diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index edfece170..005248741 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -471,6 +471,9 @@ hb_ot_get_glyph_extents (hb_font_t *font, const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; +#ifndef HB_NO_VAR_COMPOSITES + if (ot_face->VARC->get_extents (font, glyph, extents)) return true; +#endif #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) if (ot_face->sbix->get_extents (font, glyph, extents)) return true; if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;