Upgrade Harfbuzz to 11.2.1

[ChangeLog][Third-Party Code] Upgraded Harfbuzz to version
11.2.1.

Task-number: QTBUG-136745
Pick-to: 5.15 6.5 6.8 6.9
Change-Id: Ie3f67e84447f30579933d92677908f3606e557a4
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2025-05-13 11:43:10 +02:00
parent e34db561cf
commit f17a8ac6fb
54 changed files with 1853 additions and 871 deletions

View File

@ -44,6 +44,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
src/hb-open-type.hh src/hb-open-type.hh
src/hb-outline.cc src/hb-outline.hh src/hb-outline.cc src/hb-outline.hh
src/hb-paint.cc src/hb-paint.h src/hb-paint.hh src/hb-paint.cc src/hb-paint.h src/hb-paint.hh
src/hb-paint-bounded.cc src/hb-paint-bounded.hh
src/hb-paint-extents.cc src/hb-paint-extents.hh src/hb-paint-extents.cc src/hb-paint-extents.hh
src/hb-priority-queue.hh src/hb-priority-queue.hh
src/hb-repacker.hh src/hb-repacker.hh

View File

@ -7,8 +7,8 @@
"Description": "HarfBuzz is an OpenType text shaping engine.", "Description": "HarfBuzz is an OpenType text shaping engine.",
"Homepage": "http://harfbuzz.org", "Homepage": "http://harfbuzz.org",
"Version": "11.1.0", "Version": "11.2.1",
"DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/11.1.0", "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/11.2.1",
"PURL": "pkg:github/harfbuzz/harfbuzz@$<VERSION>", "PURL": "pkg:github/harfbuzz/harfbuzz@$<VERSION>",
"CPE": "cpe:2.3:a:harfbuzz_project:harfbuzz:$<VERSION>:*:*:*:*:*:*:*", "CPE": "cpe:2.3:a:harfbuzz_project:harfbuzz:$<VERSION>:*:*:*:*:*:*:*",
"License": "MIT License", "License": "MIT License",

View File

@ -949,25 +949,25 @@ struct CBDT
hb_glyph_extents_t extents; hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents; hb_glyph_extents_t pixel_extents;
hb_blob_t *blob = reference_png (font, glyph); if (unlikely (!font->get_glyph_extents (glyph, &extents, false)))
if (unlikely (blob == hb_blob_get_empty ()))
return false;
if (unlikely (!hb_font_get_glyph_extents (font, glyph, &extents)))
return false; return false;
if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
return false; return false;
hb_blob_t *blob = reference_png (font, glyph);
if (unlikely (hb_blob_is_immutable (blob)))
return false;
bool ret = funcs->image (data, bool ret = funcs->image (data,
blob, blob,
pixel_extents.width, -pixel_extents.height, pixel_extents.width, -pixel_extents.height,
HB_PAINT_IMAGE_FORMAT_PNG, HB_PAINT_IMAGE_FORMAT_PNG,
font->slant_xy, 0.f,
&extents); &extents);
hb_blob_destroy (blob); hb_blob_destroy (blob);
return ret; return ret;
} }

View File

@ -33,6 +33,7 @@
#include "../../../hb-open-type.hh" #include "../../../hb-open-type.hh"
#include "../../../hb-ot-var-common.hh" #include "../../../hb-ot-var-common.hh"
#include "../../../hb-paint.hh" #include "../../../hb-paint.hh"
#include "../../../hb-paint-bounded.hh"
#include "../../../hb-paint-extents.hh" #include "../../../hb-paint-extents.hh"
#include "../CPAL/CPAL.hh" #include "../CPAL/CPAL.hh"
@ -49,6 +50,7 @@ struct hb_paint_context_t;
struct hb_colr_scratch_t struct hb_colr_scratch_t
{ {
hb_paint_bounded_context_t paint_bounded;
hb_paint_extents_context_t paint_extents; hb_paint_extents_context_t paint_extents;
}; };
@ -101,7 +103,21 @@ public:
), ),
foreground (foreground_), foreground (foreground_),
instancer (instancer_) instancer (instancer_)
{ } {
if (font->is_synthetic ())
{
font = hb_font_create_sub_font (font);
hb_font_set_synthetic_bold (font, 0, 0, true);
hb_font_set_synthetic_slant (font, 0);
}
else
hb_font_reference (font);
}
~hb_paint_context_t ()
{
hb_font_destroy (font);
}
hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground) hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground)
{ {
@ -1620,7 +1636,7 @@ struct ClipBox
void closurev1 (hb_colrv1_closure_context_t* c) const void closurev1 (hb_colrv1_closure_context_t* c) const
{ {
switch (u.format) { switch (u.format) {
case 2: u.format2.closurev1 (c); case 2: u.format2.closurev1 (c); return;
default:return; default:return;
} }
} }
@ -2230,7 +2246,7 @@ struct COLR
public: public:
hb_blob_ptr_t<COLR> colr; hb_blob_ptr_t<COLR> colr;
private: private:
hb_atomic_t<hb_colr_scratch_t *> cached_scratch; mutable hb_atomic_t<hb_colr_scratch_t *> cached_scratch;
}; };
void closure_glyphs (hb_codepoint_t glyph, void closure_glyphs (hb_codepoint_t glyph,
@ -2632,7 +2648,6 @@ struct COLR
} }
else else
{ {
// Ugh. We need to undo the synthetic slant here. Leave it for now. :-(.
extents->x_bearing = e.xmin; extents->x_bearing = e.xmin;
extents->y_bearing = e.ymax; extents->y_bearing = e.ymax;
extents->width = e.xmax - e.xmin; extents->width = e.xmax - e.xmin;
@ -2700,7 +2715,6 @@ struct COLR
if (get_clip (glyph, &extents, instancer)) if (get_clip (glyph, &extents, instancer))
{ {
font->scale_glyph_extents (&extents); font->scale_glyph_extents (&extents);
font->synthetic_glyph_extents (&extents);
c.funcs->push_clip_rectangle (c.data, c.funcs->push_clip_rectangle (c.data,
extents.x_bearing, extents.x_bearing,
extents.y_bearing + extents.height, extents.y_bearing + extents.height,
@ -2709,23 +2723,22 @@ struct COLR
} }
else else
{ {
auto *extents_funcs = hb_paint_extents_get_funcs (); clip = false;
scratch.paint_extents.clear (); is_bounded = false;
}
if (!is_bounded)
{
auto *bounded_funcs = hb_paint_bounded_get_funcs ();
scratch.paint_bounded.clear ();
paint_glyph (font, glyph, paint_glyph (font, glyph,
extents_funcs, &scratch.paint_extents, bounded_funcs, &scratch.paint_bounded,
palette_index, foreground, palette_index, foreground,
false, false,
scratch); scratch);
auto extents = scratch.paint_extents.get_extents (); is_bounded = scratch.paint_bounded.is_bounded ();
is_bounded = scratch.paint_extents.is_bounded ();
c.funcs->push_clip_rectangle (c.data,
extents.xmin,
extents.ymin,
extents.xmax,
extents.ymax);
} }
} }

View File

@ -237,27 +237,28 @@ struct sbix
int x_offset = 0, y_offset = 0; int x_offset = 0, y_offset = 0;
unsigned int strike_ppem = 0; unsigned int strike_ppem = 0;
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
hb_glyph_extents_t extents; hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents; hb_glyph_extents_t pixel_extents;
if (blob == hb_blob_get_empty ()) if (!font->get_glyph_extents (glyph, &extents, false))
return false;
if (!hb_font_get_glyph_extents (font, glyph, &extents))
return false; return false;
if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
return false; return false;
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
if (hb_blob_is_immutable (blob))
return false;
bool ret = funcs->image (data, bool ret = funcs->image (data,
blob, blob,
pixel_extents.width, -pixel_extents.height, pixel_extents.width, -pixel_extents.height,
HB_PAINT_IMAGE_FORMAT_PNG, HB_PAINT_IMAGE_FORMAT_PNG,
font->slant_xy, 0.f,
&extents); &extents);
hb_blob_destroy (blob); hb_blob_destroy (blob);
return ret; return ret;
} }

View File

@ -104,15 +104,16 @@ struct SVG
if (blob == hb_blob_get_empty ()) if (blob == hb_blob_get_empty ())
return false; return false;
funcs->image (data, bool ret = funcs->image (data,
blob, blob,
0, 0, 0, 0,
HB_PAINT_IMAGE_FORMAT_SVG, HB_PAINT_IMAGE_FORMAT_SVG,
font->slant_xy, 0.f,
nullptr); nullptr);
hb_blob_destroy (blob); hb_blob_destroy (blob);
return true;
return ret;
} }
private: private:

View File

@ -130,7 +130,7 @@ struct CursivePosFormat1
unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false); unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false);
hb_barrier (); hb_barrier ();
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx); skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_from; unsigned unsafe_from;
if (unlikely (!skippy_iter.prev (&unsafe_from))) if (unlikely (!skippy_iter.prev (&unsafe_from)))

View File

@ -152,8 +152,11 @@ GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
for (unsigned i = 0; i < len; i++) for (unsigned i = 0; i < len; i++)
propagate_attachment_offsets (pos, len, i, direction); propagate_attachment_offsets (pos, len, i, direction);
if (unlikely (font->slant)) if (unlikely (font->slant_xy) &&
HB_DIRECTION_IS_HORIZONTAL (direction))
{ {
/* Slanting shaping results is only supported for horizontal text,
* as it gets weird otherwise. */
for (unsigned i = 0; i < len; i++) for (unsigned i = 0; i < len; i++)
if (unlikely (pos[i].y_offset)) if (unlikely (pos[i].y_offset))
pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset); pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset);

View File

@ -119,7 +119,7 @@ struct MarkBasePosFormat1_2
/* Now we search backwards for a non-mark glyph. /* Now we search backwards for a non-mark glyph.
* We don't use skippy_iter.prev() to avoid O(n^2) behavior. */ * We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
if (c->last_base_until > buffer->idx) if (c->last_base_until > buffer->idx)

View File

@ -101,7 +101,7 @@ struct MarkLigPosFormat1_2
/* Now we search backwards for a non-mark glyph */ /* Now we search backwards for a non-mark glyph */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
if (c->last_base_until > buffer->idx) if (c->last_base_until > buffer->idx)

View File

@ -100,7 +100,7 @@ struct MarkMarkPosFormat1_2
if (likely (mark1_index == NOT_COVERED)) return_trace (false); if (likely (mark1_index == NOT_COVERED)) return_trace (false);
/* now we search backwards for a suitable mark glyph until a non-mark glyph */ /* now we search backwards for a suitable mark glyph until a non-mark glyph */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx); skippy_iter.reset_fast (buffer->idx);
skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags); skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
unsigned unsafe_from; unsigned unsafe_from;

View File

@ -148,7 +148,7 @@ struct PairPosFormat1_3
#endif #endif
if (index == NOT_COVERED) return_trace (false); if (index == NOT_COVERED) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx); skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_to; unsigned unsafe_to;
if (unlikely (!skippy_iter.next (&unsafe_to))) if (unlikely (!skippy_iter.next (&unsafe_to)))

View File

@ -179,7 +179,7 @@ struct PairPosFormat2_4 : ValueBase
#endif #endif
if (index == NOT_COVERED) return_trace (false); if (index == NOT_COVERED) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx); skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_to; unsigned unsafe_to;
if (unlikely (!skippy_iter.next (&unsafe_to))) if (unlikely (!skippy_iter.next (&unsafe_to)))

View File

@ -96,7 +96,7 @@ struct LigatureSet
* *
* This is replicated in ChainRuleSet and RuleSet. */ * This is replicated in ChainRuleSet and RuleSet. */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset (c->buffer->idx); skippy_iter.reset (c->buffer->idx);
skippy_iter.set_match_func (match_always, nullptr); skippy_iter.set_match_func (match_always, nullptr);
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr); skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);

View File

@ -355,12 +355,12 @@ VARC::get_path_at (const hb_varc_context_t &c,
hb_draw_session_t transformer_session {transformer_funcs, &context}; hb_draw_session_t transformer_session {transformer_funcs, &context};
hb_draw_session_t &shape_draw_session = transform.is_identity () ? *c.draw_session : transformer_session; hb_draw_session_t &shape_draw_session = transform.is_identity () ? *c.draw_session : transformer_session;
if (!c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_scratch)) if (c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_scratch)) return true;
#ifndef HB_NO_CFF #ifndef HB_NO_CFF
if (!c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords)) if (c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords)) return true;
if (!c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) // Doesn't have variations if (c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) return true; // Doesn't have variations
#endif #endif
return false; return false;
} }
else if (c.extents) else if (c.extents)
{ {

View File

@ -235,7 +235,7 @@ struct VARC
private: private:
hb_blob_ptr_t<VARC> table; hb_blob_ptr_t<VARC> table;
hb_atomic_t<hb_varc_scratch_t *> cached_scratch; mutable hb_atomic_t<hb_varc_scratch_t *> cached_scratch;
}; };
bool has_data () const { return version.major != 0; } bool has_data () const { return version.major != 0; }

View File

@ -543,7 +543,7 @@ struct glyf_accelerator_t
unsigned int num_glyphs; unsigned int num_glyphs;
hb_blob_ptr_t<loca> loca_table; hb_blob_ptr_t<loca> loca_table;
hb_blob_ptr_t<glyf> glyf_table; hb_blob_ptr_t<glyf> glyf_table;
hb_atomic_t<hb_glyf_scratch_t *> cached_scratch; mutable hb_atomic_t<hb_glyf_scratch_t *> cached_scratch;
}; };

View File

@ -43,6 +43,7 @@
#include "hb-ot-tag.cc" #include "hb-ot-tag.cc"
#include "hb-ot-var.cc" #include "hb-ot-var.cc"
#include "hb-outline.cc" #include "hb-outline.cc"
#include "hb-paint-bounded.cc"
#include "hb-paint-extents.cc" #include "hb-paint-extents.cc"
#include "hb-paint.cc" #include "hb-paint.cc"
#include "hb-set.cc" #include "hb-set.cc"

View File

@ -52,6 +52,7 @@
#include "hb-ot-tag.cc" #include "hb-ot-tag.cc"
#include "hb-ot-var.cc" #include "hb-ot-var.cc"
#include "hb-outline.cc" #include "hb-outline.cc"
#include "hb-paint-bounded.cc"
#include "hb-paint-extents.cc" #include "hb-paint-extents.cc"
#include "hb-paint.cc" #include "hb-paint.cc"
#include "hb-set.cc" #include "hb-set.cc"

View File

@ -194,7 +194,7 @@ struct hb_atomic_t<T*>
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); } T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); } T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); } bool cmpexch (const T *old, T *new_) { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
operator bool () const { return get_acquire () != nullptr; } operator bool () const { return get_acquire () != nullptr; }
T * operator -> () const { return get_acquire (); } T * operator -> () const { return get_acquire (); }

View File

@ -410,6 +410,9 @@ struct hb_buffer_t
bool interior = false, bool interior = false,
bool from_out_buffer = false) bool from_out_buffer = false)
{ {
if (unlikely (end != (unsigned) -1 && end - start > 255))
return;
end = hb_min (end, len); end = hb_min (end, len);
if (interior && !from_out_buffer && end - start < 2) if (interior && !from_out_buffer && end - start < 2)

View File

@ -31,8 +31,6 @@
#include "hb-cairo-utils.hh" #include "hb-cairo-utils.hh"
#include <cairo.h>
/* Some routines in this file were ported from BlackRenderer by Black Foundry. /* Some routines in this file were ported from BlackRenderer by Black Foundry.
* Used by permission to relicense to HarfBuzz license. * Used by permission to relicense to HarfBuzz license.
* *
@ -101,7 +99,7 @@ _hb_cairo_paint_glyph_image (hb_cairo_context_t *c,
unsigned width, unsigned width,
unsigned height, unsigned height,
hb_tag_t format, hb_tag_t format,
float slant, HB_UNUSED float slant_deprecated,
hb_glyph_extents_t *extents) hb_glyph_extents_t *extents)
{ {
cairo_t *cr = c->cr; cairo_t *cr = c->cr;
@ -186,12 +184,6 @@ _hb_cairo_paint_glyph_image (hb_cairo_context_t *c,
cairo_matrix_t matrix = {(double) width, 0, 0, (double) height, 0, 0}; cairo_matrix_t matrix = {(double) width, 0, 0, (double) height, 0, 0};
cairo_pattern_set_matrix (pattern, &matrix); cairo_pattern_set_matrix (pattern, &matrix);
/* Undo slant in the extents and apply it in the context. */
extents->width -= extents->height * slant;
extents->x_bearing -= extents->y_bearing * slant;
cairo_matrix_t cairo_matrix = {1., 0., (double) slant, 1., 0., 0.};
cairo_transform (cr, &cairo_matrix);
cairo_translate (cr, extents->x_bearing, extents->y_bearing); cairo_translate (cr, extents->x_bearing, extents->y_bearing);
cairo_scale (cr, extents->width, extents->height); cairo_scale (cr, extents->width, extents->height);
cairo_set_source (cr, pattern); cairo_set_source (cr, pattern);

View File

@ -204,7 +204,9 @@ hb_cairo_push_clip_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED,
cairo_save (cr); cairo_save (cr);
cairo_new_path (cr); cairo_new_path (cr);
hb_font_draw_glyph (font, glyph, hb_cairo_draw_get_funcs (), cr); hb_font_draw_glyph (font, glyph, hb_cairo_draw_get_funcs (), cr);
cairo_close_path (cr); cairo_close_path (cr);
cairo_clip (cr); cairo_clip (cr);
} }
@ -572,9 +574,12 @@ hb_cairo_text_to_glyphs (cairo_scaled_font_t *scaled_font,
hb_buffer_guess_segment_properties (buffer); hb_buffer_guess_segment_properties (buffer);
hb_shape (font, buffer, nullptr, 0); hb_shape (font, buffer, nullptr, 0);
int x_scale, y_scale;
hb_font_get_scale (font, &x_scale, &y_scale);
hb_cairo_glyphs_from_buffer (buffer, hb_cairo_glyphs_from_buffer (buffer,
true, true,
font->x_scale, font->y_scale, x_scale, y_scale,
0., 0., 0., 0.,
utf8, utf8_len, utf8, utf8_len,
glyphs, (unsigned *) num_glyphs, glyphs, (unsigned *) num_glyphs,
@ -601,10 +606,11 @@ hb_cairo_render_glyph (cairo_scaled_font_t *scaled_font,
+1. / (x_scale ? x_scale : 1), +1. / (x_scale ? x_scale : 1),
-1. / (y_scale ? y_scale : 1)); -1. / (y_scale ? y_scale : 1));
hb_font_draw_glyph (font, glyph, hb_cairo_draw_get_funcs (), cr); if (hb_font_draw_glyph_or_fail (font, glyph, hb_cairo_draw_get_funcs (), cr))
cairo_fill (cr);
cairo_fill (cr);
// If draw fails, we still return SUCCESS, as we want empty drawing, not
// setting the cairo object into error.
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }
@ -639,8 +645,8 @@ hb_cairo_render_color_glyph (cairo_scaled_font_t *scaled_font,
c.cr = cr; c.cr = cr;
c.color_cache = (hb_map_t *) cairo_scaled_font_get_user_data (scaled_font, &color_cache_key); c.color_cache = (hb_map_t *) cairo_scaled_font_get_user_data (scaled_font, &color_cache_key);
hb_font_paint_glyph (font, glyph, hb_cairo_paint_get_funcs (), &c, palette, color); if (!hb_font_paint_glyph_or_fail (font, glyph, hb_cairo_paint_get_funcs (), &c, palette, color))
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }
@ -657,8 +663,7 @@ user_font_face_create (hb_face_t *face)
cairo_user_font_face_set_text_to_glyphs_func (cairo_face, hb_cairo_text_to_glyphs); cairo_user_font_face_set_text_to_glyphs_func (cairo_face, hb_cairo_text_to_glyphs);
cairo_user_font_face_set_render_glyph_func (cairo_face, hb_cairo_render_glyph); cairo_user_font_face_set_render_glyph_func (cairo_face, hb_cairo_render_glyph);
#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC #ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
if (hb_ot_color_has_png (face) || hb_ot_color_has_layers (face) || hb_ot_color_has_paint (face)) cairo_user_font_face_set_render_color_glyph_func (cairo_face, hb_cairo_render_color_glyph);
cairo_user_font_face_set_render_color_glyph_func (cairo_face, hb_cairo_render_color_glyph);
#endif #endif
if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face, if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face,
@ -689,7 +694,8 @@ hb_cairo_font_face_create_for_font (hb_font_t *font)
{ {
hb_font_make_immutable (font); hb_font_make_immutable (font);
auto *cairo_face = user_font_face_create (font->face); auto *hb_face = hb_font_get_face (font);
auto *cairo_face = user_font_face_create (hb_face);
if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face, if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face,
&hb_cairo_font_user_data_key, &hb_cairo_font_user_data_key,

View File

@ -365,12 +365,12 @@ ct_apply_func (void *info, const CGPathElement *element)
} }
} }
static void static hb_bool_t
hb_coretext_draw_glyph (hb_font_t *font, hb_coretext_draw_glyph_or_fail (hb_font_t *font,
void *font_data HB_UNUSED, void *font_data HB_UNUSED,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data, hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data) void *user_data)
{ {
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext; CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
@ -383,13 +383,15 @@ hb_coretext_draw_glyph (hb_font_t *font,
CGPathRef path = CTFontCreatePathForGlyph (ct_font, glyph, &transform); CGPathRef path = CTFontCreatePathForGlyph (ct_font, glyph, &transform);
if (!path) if (!path)
return; return false;
hb_draw_session_t drawing = {draw_funcs, draw_data, font->slant}; hb_draw_session_t drawing {draw_funcs, draw_data};
CGPathApply (path, &drawing, ct_apply_func); CGPathApply (path, &drawing, ct_apply_func);
CFRelease (path); CFRelease (path);
return true;
} }
#endif #endif
@ -469,7 +471,7 @@ static struct hb_coretext_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t
#endif #endif
#ifndef HB_NO_DRAW #ifndef HB_NO_DRAW
hb_font_funcs_set_draw_glyph_func (funcs, hb_coretext_draw_glyph, nullptr, nullptr); hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_coretext_draw_glyph_or_fail, nullptr, nullptr);
#endif #endif
hb_font_funcs_set_glyph_extents_func (funcs, hb_coretext_get_glyph_extents, nullptr, nullptr); hb_font_funcs_set_glyph_extents_func (funcs, hb_coretext_get_glyph_extents, nullptr, nullptr);

View File

@ -205,10 +205,18 @@ create_cg_font (hb_blob_t *blob, unsigned int index)
if (unlikely (named_instance_index != 0)) if (unlikely (named_instance_index != 0))
{ {
// https://github.com/harfbuzz/harfbuzz/issues/5300
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || \
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || \
(defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED >= 110000) || \
(defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED >= 40000) || \
(defined(__MACCATALYST_VERSION_MIN_REQUIRED) && __MACCATALYST_VERSION_MIN_REQUIRED >= 130100) || \
(defined(__VISION_OS_VERSION_MIN_REQUIRED) && __VISION_OS_VERSION_MIN_REQUIRED >= 10000)
auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromData (CFDataCreate (kCFAllocatorDefault, (const UInt8 *) blob_data, blob_length)); auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromData (CFDataCreate (kCFAllocatorDefault, (const UInt8 *) blob_data, blob_length));
if (unlikely (!ct_font_desc_array)) if (likely (ct_font_desc_array))
return nullptr; return create_cg_font (ct_font_desc_array, named_instance_index);
return create_cg_font (ct_font_desc_array, named_instance_index); #endif
return nullptr;
} }
hb_blob_reference (blob); hb_blob_reference (blob);

View File

@ -275,6 +275,48 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
hb_draw_funcs_t *draw_funcs, void *draw_data, hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data); void *user_data);
/**
* hb_font_draw_glyph_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @draw_funcs: The draw functions to send the shape data to
* @draw_data: The data accompanying the draw functions
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* Since: 7.0.0
* XDeprecated: REPLACEME: Use hb_font_draw_glyph_func_or_fail_t instead.
**/
typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data);
/**
* hb_font_paint_glyph_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @paint_funcs: The paint functions to use
* @paint_data: The data accompanying the paint functions
* @palette_index: The color palette to use
* @foreground: The foreground color
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* Since: 7.0.0
* XDeprecated: REPLACEME: Use hb_font_paint_glyph_or_fail_func_t instead.
*/
typedef hb_bool_t (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs, void *paint_data,
unsigned int palette_index,
hb_color_t foreground,
void *user_data);
/** /**
* hb_font_funcs_set_glyph_shape_func: * hb_font_funcs_set_glyph_shape_func:
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
@ -288,13 +330,49 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
* Since: 4.0.0 * Since: 4.0.0
* Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
**/ **/
HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func) HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func)
HB_EXTERN void HB_EXTERN void
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_shape_func_t func, hb_font_get_glyph_shape_func_t func,
void *user_data, hb_destroy_func_t destroy); void *user_data, hb_destroy_func_t destroy);
HB_DEPRECATED_FOR (hb_font_draw_glyph) /**
* hb_font_funcs_set_draw_glyph_func:
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_draw_glyph_func_t.
*
* Since: 7.0.0
* XDeprecated: REPLACEME: Use hb_font_funcs_set_draw_glyph_or_fail_func instead.
**/
HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func)
HB_EXTERN void
hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_draw_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_paint_glyph_func:
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is no longer needed
*
* Sets the implementation function for #hb_font_paint_glyph_func_t.
*
* Since: 7.0.0
* XDeprecated: REPLACEME: Use hb_font_funcs_set_paint_glyph_or_fail_func() instead.
*/
HB_DEPRECATED_FOR (hb_font_funcs_set_paint_glyph_or_fail_func)
HB_EXTERN void
hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_paint_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy);
HB_DEPRECATED_FOR (hb_font_draw_glyph_or_fail)
HB_EXTERN void HB_EXTERN void
hb_font_get_glyph_shape (hb_font_t *font, hb_font_get_glyph_shape (hb_font_t *font,
hb_codepoint_t glyph, hb_codepoint_t glyph,

View File

@ -114,6 +114,8 @@ hb_directwrite_get_glyph_h_advances (hb_font_t* font,
dw_face->QueryInterface (__uuidof(IDWriteFontFace1), (void**)&dw_face1); dw_face->QueryInterface (__uuidof(IDWriteFontFace1), (void**)&dw_face1);
assert (dw_face1); assert (dw_face1);
unsigned int num_glyphs = font->face->get_num_glyphs ();
for (unsigned i = 0; i < count;) for (unsigned i = 0; i < count;)
{ {
UINT16 gids[MAX_GLYPHS]; UINT16 gids[MAX_GLYPHS];
@ -130,7 +132,9 @@ hb_directwrite_get_glyph_h_advances (hb_font_t* font,
dw_face1->GetDesignGlyphAdvances (n, gids, advances, false); dw_face1->GetDesignGlyphAdvances (n, gids, advances, false);
for (unsigned j = 0; j < n; j++) for (unsigned j = 0; j < n; j++)
{ {
*first_advance = font->em_scale_x (advances[j]); // https://github.com/harfbuzz/harfbuzz/issues/5319
auto advance = gids[j] < num_glyphs ? advances[j] : 0;
*first_advance = font->em_scale_x (advance);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride); first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
} }
@ -238,7 +242,7 @@ public:
GeometrySink(hb_font_t *font, GeometrySink(hb_font_t *font,
hb_draw_funcs_t *draw_funcs, hb_draw_funcs_t *draw_funcs,
void *draw_data) void *draw_data)
: font (font), drawing ({draw_funcs, draw_data, font->slant}) {} : font (font), drawing ({draw_funcs, draw_data}) {}
virtual ~GeometrySink() {} virtual ~GeometrySink() {}
@ -275,12 +279,12 @@ public:
} }
}; };
static void static hb_bool_t
hb_directwrite_draw_glyph (hb_font_t *font, hb_directwrite_draw_glyph_or_fail (hb_font_t *font,
void *font_data HB_UNUSED, void *font_data HB_UNUSED,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data, hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data) void *user_data)
{ {
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite; IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
@ -288,11 +292,11 @@ hb_directwrite_draw_glyph (hb_font_t *font,
UINT16 gid = static_cast<UINT16>(glyph); UINT16 gid = static_cast<UINT16>(glyph);
unsigned upem = font->face->get_upem(); unsigned upem = font->face->get_upem();
(void) dw_face->GetGlyphRunOutline (upem, return S_OK == dw_face->GetGlyphRunOutline (upem,
&gid, nullptr, nullptr, &gid, nullptr, nullptr,
1, 1,
false, false, false, false,
&sink); &sink);
} }
#endif #endif
@ -317,7 +321,7 @@ static struct hb_directwrite_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loade
#endif #endif
#ifndef HB_NO_DRAW #ifndef HB_NO_DRAW
hb_font_funcs_set_draw_glyph_func (funcs, hb_directwrite_draw_glyph, nullptr, nullptr); hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_directwrite_draw_glyph_or_fail, nullptr, nullptr);
#endif #endif
hb_font_funcs_set_glyph_extents_func (funcs, hb_directwrite_get_glyph_extents, nullptr, nullptr); hb_font_funcs_set_glyph_extents_func (funcs, hb_directwrite_get_glyph_extents, nullptr, nullptr);

View File

@ -28,6 +28,11 @@
#include "hb-draw.hh" #include "hb-draw.hh"
#include "hb-geometry.hh"
#include "hb-machinery.hh"
/** /**
* SECTION:hb-draw * SECTION:hb-draw
* @title: hb-draw * @title: hb-draw
@ -455,4 +460,92 @@ hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
} }
static void
hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (to_x, to_y);
}
static void
hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (to_x, to_y);
}
static void
hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (control_x, control_y);
extents->add_point (to_x, to_y);
}
static void
hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (control1_x, control1_y);
extents->add_point (control2_x, control2_y);
extents->add_point (to_x, to_y);
}
static inline void free_static_draw_extents_funcs ();
static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_draw_extents_funcs_lazy_loader_t>
{
static hb_draw_funcs_t *create ()
{
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
hb_draw_funcs_make_immutable (funcs);
hb_atexit (free_static_draw_extents_funcs);
return funcs;
}
} static_draw_extents_funcs;
static inline
void free_static_draw_extents_funcs ()
{
static_draw_extents_funcs.free_instance ();
}
hb_draw_funcs_t *
hb_draw_extents_get_funcs ()
{
return static_draw_extents_funcs.get_unconst ();
}
#endif #endif

View File

@ -41,16 +41,9 @@ HB_BEGIN_DECLS
* @path_start_y: Y component of the start of current path * @path_start_y: Y component of the start of current path
* @current_x: X component of current point * @current_x: X component of current point
* @current_y: Y component of current point * @current_y: Y component of current point
* @slant_xy: Slanting factor for synthetic oblique, Since: 11.0.0
* *
* Current drawing state. * Current drawing state.
* *
* The @slant_xy is a slanting factor for synthetic oblique. If the font's
* oblique angle is not 0, this factor is used to slant the drawing. For
* fonts with uniform x and y scales, this factor is calculated as
* tan(oblique_angle). For fonts with non-uniform scales, this factor is
* calculated as tan(oblique_angle) * x_scale / y_scale, or 0 if y_scale is 0.
*
* Since: 4.0.0 * Since: 4.0.0
**/ **/
typedef struct hb_draw_state_t { typedef struct hb_draw_state_t {
@ -62,8 +55,6 @@ typedef struct hb_draw_state_t {
float current_x; float current_x;
float current_y; float current_y;
float slant_xy;
/*< private >*/ /*< private >*/
hb_var_num_t reserved1; hb_var_num_t reserved1;
hb_var_num_t reserved2; hb_var_num_t reserved2;
@ -71,6 +62,7 @@ typedef struct hb_draw_state_t {
hb_var_num_t reserved4; hb_var_num_t reserved4;
hb_var_num_t reserved5; hb_var_num_t reserved5;
hb_var_num_t reserved6; hb_var_num_t reserved6;
hb_var_num_t reserved7;
} hb_draw_state_t; } hb_draw_state_t;
/** /**
@ -78,7 +70,7 @@ typedef struct hb_draw_state_t {
* *
* The default #hb_draw_state_t at the start of glyph drawing. * The default #hb_draw_state_t at the start of glyph drawing.
*/ */
#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}} #define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0}, {0}, {0}, {0}, {0}, {0}, {0}}
/** /**

View File

@ -100,9 +100,6 @@ struct hb_draw_funcs_t
{ {
if (unlikely (st.path_open)) close_path (draw_data, st); if (unlikely (st.path_open)) close_path (draw_data, st);
if (st.slant_xy)
to_x += to_y * st.slant_xy;
st.current_x = to_x; st.current_x = to_x;
st.current_y = to_y; st.current_y = to_y;
} }
@ -114,9 +111,6 @@ struct hb_draw_funcs_t
{ {
if (unlikely (!st.path_open)) start_path (draw_data, st); if (unlikely (!st.path_open)) start_path (draw_data, st);
if (st.slant_xy)
to_x += to_y * st.slant_xy;
emit_line_to (draw_data, st, to_x, to_y); emit_line_to (draw_data, st, to_x, to_y);
st.current_x = to_x; st.current_x = to_x;
@ -131,12 +125,6 @@ struct hb_draw_funcs_t
{ {
if (unlikely (!st.path_open)) start_path (draw_data, st); if (unlikely (!st.path_open)) start_path (draw_data, st);
if (st.slant_xy)
{
control_x += control_y * st.slant_xy;
to_x += to_y * st.slant_xy;
}
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
st.current_x = to_x; st.current_x = to_x;
@ -152,13 +140,6 @@ struct hb_draw_funcs_t
{ {
if (unlikely (!st.path_open)) start_path (draw_data, st); if (unlikely (!st.path_open)) start_path (draw_data, st);
if (st.slant_xy)
{
control1_x += control1_y * st.slant_xy;
control2_x += control2_y * st.slant_xy;
to_x += to_y * st.slant_xy;
}
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
st.current_x = to_x; st.current_x = to_x;
@ -194,9 +175,9 @@ DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
struct hb_draw_session_t struct hb_draw_session_t
{ {
hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_xy = 0.f) hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_)
: funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
{ st.slant_xy = slant_xy; } {}
~hb_draw_session_t () { close_path (); } ~hb_draw_session_t () { close_path (); }
@ -244,4 +225,9 @@ struct hb_draw_session_t
hb_draw_state_t st; hb_draw_state_t st;
}; };
HB_INTERNAL hb_draw_funcs_t *
hb_draw_extents_get_funcs ();
#endif /* HB_DRAW_HH */ #endif /* HB_DRAW_HH */

View File

@ -103,7 +103,7 @@ hb_font_get_font_h_extents_default (hb_font_t *font,
hb_font_extents_t *extents, hb_font_extents_t *extents,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
hb_bool_t ret = font->parent->get_font_h_extents (extents); hb_bool_t ret = font->parent->get_font_h_extents (extents, false);
if (ret) { if (ret) {
extents->ascender = font->parent_scale_y_distance (extents->ascender); extents->ascender = font->parent_scale_y_distance (extents->ascender);
extents->descender = font->parent_scale_y_distance (extents->descender); extents->descender = font->parent_scale_y_distance (extents->descender);
@ -128,7 +128,7 @@ hb_font_get_font_v_extents_default (hb_font_t *font,
hb_font_extents_t *extents, hb_font_extents_t *extents,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
hb_bool_t ret = font->parent->get_font_v_extents (extents); hb_bool_t ret = font->parent->get_font_v_extents (extents, false);
if (ret) { if (ret) {
extents->ascender = font->parent_scale_x_distance (extents->ascender); extents->ascender = font->parent_scale_x_distance (extents->ascender);
extents->descender = font->parent_scale_x_distance (extents->descender); extents->descender = font->parent_scale_x_distance (extents->descender);
@ -234,10 +234,10 @@ hb_font_get_glyph_h_advance_default (hb_font_t *font,
if (font->has_glyph_h_advances_func_set ()) if (font->has_glyph_h_advances_func_set ())
{ {
hb_position_t ret; hb_position_t ret;
font->get_glyph_h_advances (1, &glyph, 0, &ret, 0); font->get_glyph_h_advances (1, &glyph, 0, &ret, 0, false);
return ret; return ret;
} }
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph, false));
} }
static hb_position_t static hb_position_t
@ -259,10 +259,10 @@ hb_font_get_glyph_v_advance_default (hb_font_t *font,
if (font->has_glyph_v_advances_func_set ()) if (font->has_glyph_v_advances_func_set ())
{ {
hb_position_t ret; hb_position_t ret;
font->get_glyph_v_advances (1, &glyph, 0, &ret, 0); font->get_glyph_v_advances (1, &glyph, 0, &ret, 0, false);
return ret; return ret;
} }
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph, false));
} }
#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default #define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
@ -281,7 +281,7 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
{ {
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
*first_advance = font->get_glyph_h_advance (*first_glyph); *first_advance = font->get_glyph_h_advance (*first_glyph, false);
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
} }
@ -290,7 +290,8 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
font->parent->get_glyph_h_advances (count, font->parent->get_glyph_h_advances (count,
first_glyph, glyph_stride, first_glyph, glyph_stride,
first_advance, advance_stride); first_advance, advance_stride,
false);
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
*first_advance = font->parent_scale_x_distance (*first_advance); *first_advance = font->parent_scale_x_distance (*first_advance);
@ -313,7 +314,7 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
{ {
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
*first_advance = font->get_glyph_v_advance (*first_glyph); *first_advance = font->get_glyph_v_advance (*first_glyph, false);
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
} }
@ -322,7 +323,8 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
font->parent->get_glyph_v_advances (count, font->parent->get_glyph_v_advances (count,
first_glyph, glyph_stride, first_glyph, glyph_stride,
first_advance, advance_stride); first_advance, advance_stride,
false);
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
*first_advance = font->parent_scale_y_distance (*first_advance); *first_advance = font->parent_scale_y_distance (*first_advance);
@ -442,7 +444,7 @@ hb_font_get_glyph_extents_default (hb_font_t *font,
hb_glyph_extents_t *extents, hb_glyph_extents_t *extents,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents, false);
if (ret) { if (ret) {
font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
font->parent_scale_distance (&extents->width, &extents->height); font->parent_scale_distance (&extents->width, &extents->height);
@ -472,7 +474,7 @@ hb_font_get_glyph_contour_point_default (hb_font_t *font,
hb_position_t *y, hb_position_t *y,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y, false);
if (ret) if (ret)
font->parent_scale_position (x, y); font->parent_scale_position (x, y);
return ret; return ret;
@ -524,26 +526,28 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
return font->parent->get_glyph_from_name (name, len, glyph); return font->parent->get_glyph_from_name (name, len, glyph);
} }
static void static hb_bool_t
hb_font_draw_glyph_nil (hb_font_t *font HB_UNUSED, hb_font_draw_glyph_or_fail_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED, void *font_data HB_UNUSED,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, hb_draw_funcs_t *draw_funcs,
void *draw_data, void *draw_data,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
return false;
} }
static void static hb_bool_t
hb_font_paint_glyph_nil (hb_font_t *font HB_UNUSED, hb_font_paint_glyph_or_fail_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED, void *font_data HB_UNUSED,
hb_codepoint_t glyph HB_UNUSED, hb_codepoint_t glyph HB_UNUSED,
hb_paint_funcs_t *paint_funcs HB_UNUSED, hb_paint_funcs_t *paint_funcs HB_UNUSED,
void *paint_data HB_UNUSED, void *paint_data HB_UNUSED,
unsigned int palette HB_UNUSED, unsigned int palette HB_UNUSED,
hb_color_t foreground HB_UNUSED, hb_color_t foreground HB_UNUSED,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
return false;
} }
typedef struct hb_font_draw_glyph_default_adaptor_t { typedef struct hb_font_draw_glyph_default_adaptor_t {
@ -551,7 +555,6 @@ typedef struct hb_font_draw_glyph_default_adaptor_t {
void *draw_data; void *draw_data;
float x_scale; float x_scale;
float y_scale; float y_scale;
float slant;
} hb_font_draw_glyph_default_adaptor_t; } hb_font_draw_glyph_default_adaptor_t;
static void static void
@ -564,10 +567,9 @@ hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale; float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale; float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st, adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
x_scale * to_x + slant * to_y, y_scale * to_y); x_scale * to_x, y_scale * to_y);
} }
static void static void
@ -579,13 +581,12 @@ hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale; float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale; float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
st->current_x = st->current_x * x_scale + st->current_y * slant; st->current_x = st->current_x * x_scale;
st->current_y = st->current_y * y_scale; st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st, adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
x_scale * to_x + slant * to_y, y_scale * to_y); x_scale * to_x, y_scale * to_y);
} }
static void static void
@ -598,14 +599,13 @@ hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale; float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale; float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
st->current_x = st->current_x * x_scale + st->current_y * slant; st->current_x = st->current_x * x_scale;
st->current_y = st->current_y * y_scale; st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st, adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
x_scale * control_x + slant * control_y, y_scale * control_y, x_scale * control_x, y_scale * control_y,
x_scale * to_x + slant * to_y, y_scale * to_y); x_scale * to_x, y_scale * to_y);
} }
static void static void
@ -619,15 +619,14 @@ hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale; float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale; float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
st->current_x = st->current_x * x_scale + st->current_y * slant; st->current_x = st->current_x * x_scale;
st->current_y = st->current_y * y_scale; st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st, adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
x_scale * control1_x + slant * control1_y, y_scale * control1_y, x_scale * control1_x, y_scale * control1_y,
x_scale * control2_x + slant * control2_y, y_scale * control2_y, x_scale * control2_x, y_scale * control2_y,
x_scale * to_x + slant * to_y, y_scale * to_y); x_scale * to_x, y_scale * to_y);
} }
static void static void
@ -650,49 +649,47 @@ static const hb_draw_funcs_t _hb_draw_funcs_default = {
} }
}; };
static void static hb_bool_t
hb_font_draw_glyph_default (hb_font_t *font, hb_font_draw_glyph_or_fail_default (hb_font_t *font,
void *font_data HB_UNUSED, void *font_data HB_UNUSED,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, hb_draw_funcs_t *draw_funcs,
void *draw_data, void *draw_data,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
hb_font_draw_glyph_default_adaptor_t adaptor = { hb_font_draw_glyph_default_adaptor_t adaptor = {
draw_funcs, draw_funcs,
draw_data, draw_data,
font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f, font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f, font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f
font->parent->y_scale ? (font->slant - font->parent->slant) *
(float) font->x_scale / (float) font->parent->y_scale : 0.f
}; };
font->parent->draw_glyph (glyph, return font->parent->draw_glyph_or_fail (glyph,
const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default), const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
&adaptor); &adaptor,
false);
} }
static void static hb_bool_t
hb_font_paint_glyph_default (hb_font_t *font, hb_font_paint_glyph_or_fail_default (hb_font_t *font,
void *font_data, void *font_data,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs, hb_paint_funcs_t *paint_funcs,
void *paint_data, void *paint_data,
unsigned int palette, unsigned int palette,
hb_color_t foreground, hb_color_t foreground,
void *user_data) void *user_data)
{ {
paint_funcs->push_transform (paint_data, paint_funcs->push_transform (paint_data,
font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f, font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0, 0,
font->parent->y_scale ? (font->slant - font->parent->slant) * 0, font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0,
(float) font->x_scale / (float) font->parent->y_scale : 0.f, 0, 0);
0.f,
font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
0.f, 0.f);
font->parent->paint_glyph (glyph, paint_funcs, paint_data, palette, foreground); bool ret = font->parent->paint_glyph_or_fail (glyph, paint_funcs, paint_data, palette, foreground);
paint_funcs->pop_transform (paint_data); paint_funcs->pop_transform (paint_data);
return ret;
} }
DEFINE_NULL_INSTANCE (hb_font_funcs_t) = DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
@ -1429,6 +1426,92 @@ hb_font_get_glyph_shape (hb_font_t *font,
} }
#endif #endif
/**
* hb_font_draw_glyph_or_fail:
* @font: #hb_font_t to work upon
* @glyph: The glyph ID
* @dfuncs: #hb_draw_funcs_t to draw to
* @draw_data: User data to pass to draw callbacks
*
* Draws the outline that corresponds to a glyph in the specified @font.
*
* This is a newer name for hb_font_draw_glyph(), that returns `false`
* if the font has no outlines for the glyph.
*
* The outline is returned by way of calls to the callbacks of the @dfuncs
* objects, with @draw_data passed to them.
*
* Return value: `true` if glyph was drawn, `false` otherwise
*
* XSince: REPLACEME
**/
hb_bool_t
hb_font_draw_glyph_or_fail (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data)
{
return font->draw_glyph_or_fail (glyph, dfuncs, draw_data);
}
/**
* hb_font_paint_glyph_or_fail:
* @font: #hb_font_t to work upon
* @glyph: The glyph ID
* @pfuncs: #hb_paint_funcs_t to paint with
* @paint_data: User data to pass to paint callbacks
* @palette_index: The index of the font's color palette to use
* @foreground: The foreground color, unpremultipled
*
* Paints a color glyph.
*
* This function is similar to, but lower-level than,
* hb_font_paint_glyph(). It is suitable for clients that
* need more control. If there are no color glyphs available,
* it will return `false`. The client can then fall back to
* hb_font_draw_glyph_or_fail() for the monochrome outline glyph.
*
* The painting instructions are returned by way of calls to
* the callbacks of the @funcs object, with @paint_data passed
* to them.
*
* If the font has color palettes (see hb_ot_color_has_palettes()),
* then @palette_index selects the palette to use. If the font only
* has one palette, this will be 0.
*
* Return value: `true` if glyph was painted, `false` otherwise
*
* XSince: REPLACEME
*/
hb_bool_t
hb_font_paint_glyph_or_fail (hb_font_t *font,
hb_codepoint_t glyph,
hb_paint_funcs_t *pfuncs, void *paint_data,
unsigned int palette_index,
hb_color_t foreground)
{
return font->paint_glyph_or_fail (glyph, pfuncs, paint_data, palette_index, foreground);
}
/* A bit higher-level, and with fallback */
void
hb_font_t::paint_glyph (hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs, void *paint_data,
unsigned int palette,
hb_color_t foreground)
{
if (paint_glyph_or_fail (glyph,
paint_funcs, paint_data,
palette, foreground))
return;
/* Fallback for outline glyph. */
paint_funcs->push_clip_glyph (paint_data, glyph, this);
paint_funcs->color (paint_data, true, foreground);
paint_funcs->pop_clip (paint_data);
}
/** /**
* hb_font_draw_glyph: * hb_font_draw_glyph:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
@ -1438,6 +1521,9 @@ hb_font_get_glyph_shape (hb_font_t *font,
* *
* Draws the outline that corresponds to a glyph in the specified @font. * Draws the outline that corresponds to a glyph in the specified @font.
* *
* This is an older name for hb_font_draw_glyph_or_fail(), with no
* return value.
*
* The outline is returned by way of calls to the callbacks of the @dfuncs * The outline is returned by way of calls to the callbacks of the @dfuncs
* objects, with @draw_data passed to them. * objects, with @draw_data passed to them.
* *
@ -1445,10 +1531,10 @@ hb_font_get_glyph_shape (hb_font_t *font,
**/ **/
void void
hb_font_draw_glyph (hb_font_t *font, hb_font_draw_glyph (hb_font_t *font,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data) hb_draw_funcs_t *dfuncs, void *draw_data)
{ {
font->draw_glyph (glyph, dfuncs, draw_data); (void) hb_font_draw_glyph_or_fail (font, glyph, dfuncs, draw_data);
} }
/** /**
@ -1460,7 +1546,10 @@ hb_font_draw_glyph (hb_font_t *font,
* @palette_index: The index of the font's color palette to use * @palette_index: The index of the font's color palette to use
* @foreground: The foreground color, unpremultipled * @foreground: The foreground color, unpremultipled
* *
* Paints the glyph. * Paints the glyph. This function is similar to
* hb_font_paint_glyph_or_fail(), but if painting a color glyph
* failed, it will fall back to painting an outline monochrome
* glyph.
* *
* The painting instructions are returned by way of calls to * The painting instructions are returned by way of calls to
* the callbacks of the @funcs object, with @paint_data passed * the callbacks of the @funcs object, with @paint_data passed
@ -1482,8 +1571,6 @@ hb_font_paint_glyph (hb_font_t *font,
font->paint_glyph (glyph, pfuncs, paint_data, palette_index, foreground); font->paint_glyph (glyph, pfuncs, paint_data, palette_index, foreground);
} }
/* A bit higher-level, and with fallback */
/** /**
* hb_font_get_extents_for_direction: * hb_font_get_extents_for_direction:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
@ -2608,6 +2695,23 @@ hb_font_get_ptem (hb_font_t *font)
return font->ptem; return font->ptem;
} }
/**
* hb_font_is_synthetic:
* @font: #hb_font_t to work upon
*
* Tests whether a font is synthetic. A synthetic font is one
* that has either synthetic slant or synthetic bold set on it.
*
* Return value: `true` if the font is synthetic, `false` otherwise.
*
* XSince: REPLACEME
*/
hb_bool_t
hb_font_is_synthetic (hb_font_t *font)
{
return font->is_synthetic ();
}
/** /**
* hb_font_set_synthetic_bold: * hb_font_set_synthetic_bold:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
@ -2625,7 +2729,7 @@ hb_font_get_ptem (hb_font_t *font)
* points of the glyph shape. * points of the glyph shape.
* *
* Synthetic boldness is applied when rendering a glyph via * Synthetic boldness is applied when rendering a glyph via
* hb_font_draw_glyph(). * hb_font_draw_glyph_or_fail().
* *
* If @in_place is `false`, then glyph advance-widths are also * If @in_place is `false`, then glyph advance-widths are also
* adjusted, otherwise they are not. The in-place mode is * adjusted, otherwise they are not. The in-place mode is
@ -2689,7 +2793,7 @@ hb_font_get_synthetic_bold (hb_font_t *font,
* HarfBuzz needs to know this value to adjust shaping results, * HarfBuzz needs to know this value to adjust shaping results,
* metrics, and style values to match the slanted rendering. * metrics, and style values to match the slanted rendering.
* *
* <note>Note: The glyph shape fetched via the hb_font_draw_glyph() * <note>Note: The glyph shape fetched via the hb_font_draw_glyph_or_fail()
* function is slanted to reflect this value as well.</note> * function is slanted to reflect this value as well.</note>
* *
* <note>Note: The slant value is a ratio. For example, a * <note>Note: The slant value is a ratio. For example, a
@ -3195,12 +3299,134 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
#ifndef HB_DISABLE_DEPRECATED #ifndef HB_DISABLE_DEPRECATED
struct hb_draw_glyph_closure_t
{
hb_font_draw_glyph_func_t func;
void *user_data;
hb_destroy_func_t destroy;
};
static hb_bool_t
hb_font_draw_glyph_trampoline (hb_font_t *font,
void *font_data,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs,
void *draw_data,
void *user_data)
{
hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data;
closure->func (font, font_data, glyph, draw_funcs, draw_data, closure->user_data);
return true;
}
static void
hb_font_draw_glyph_closure_destroy (void *user_data)
{
hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data;
if (closure->destroy)
closure->destroy (closure->user_data);
hb_free (closure);
}
static void
_hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_draw_glyph_func_t func,
void *user_data,
hb_destroy_func_t destroy /* May be NULL. */)
{
if (hb_object_is_immutable (ffuncs))
{
if (destroy)
destroy (user_data);
return;
}
hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) hb_calloc (1, sizeof (hb_draw_glyph_closure_t));
if (unlikely (!closure))
{
if (destroy)
destroy (user_data);
return;
}
closure->func = func;
closure->user_data = user_data;
closure->destroy = destroy;
hb_font_funcs_set_draw_glyph_or_fail_func (ffuncs,
hb_font_draw_glyph_trampoline,
closure,
hb_font_draw_glyph_closure_destroy);
}
void
hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_draw_glyph_func_t func,
void *user_data,
hb_destroy_func_t destroy /* May be NULL. */)
{
_hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
}
void void
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_shape_func_t func, hb_font_get_glyph_shape_func_t func,
void *user_data, void *user_data,
hb_destroy_func_t destroy /* May be NULL. */) hb_destroy_func_t destroy /* May be NULL. */)
{ {
hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); _hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
}
struct hb_paint_glyph_closure_t
{
hb_font_paint_glyph_func_t func;
void *user_data;
hb_destroy_func_t destroy;
};
static hb_bool_t
hb_font_paint_glyph_trampoline (hb_font_t *font,
void *font_data,
hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs,
void *paint_data,
unsigned int palette,
hb_color_t foreground,
void *user_data)
{
hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data;
closure->func (font, font_data, glyph, paint_funcs, paint_data, palette, foreground, closure->user_data);
return true;
}
static void
hb_font_paint_glyph_closure_destroy (void *user_data)
{
hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data;
if (closure->destroy)
closure->destroy (closure->user_data);
hb_free (closure);
}
void
hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_paint_glyph_func_t func,
void *user_data,
hb_destroy_func_t destroy /* May be NULL. */)
{
if (hb_object_is_immutable (ffuncs))
{
if (destroy)
destroy (user_data);
return;
}
hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) hb_calloc (1, sizeof (hb_paint_glyph_closure_t));
if (unlikely (!closure))
{
if (destroy)
destroy (user_data);
return;
}
closure->func = func;
closure->user_data = user_data;
closure->destroy = destroy;
hb_font_funcs_set_paint_glyph_or_fail_func (ffuncs,
hb_font_paint_glyph_trampoline,
closure,
hb_font_paint_glyph_closure_destroy);
} }
#endif #endif

View File

@ -486,7 +486,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
void *user_data); void *user_data);
/** /**
* hb_font_draw_glyph_func_t: * hb_font_draw_glyph_or_fail_func_t:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @font_data: @font user data pointer * @font_data: @font user data pointer
* @glyph: The glyph ID to query * @glyph: The glyph ID to query
@ -496,16 +496,17 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* Since: 7.0.0 * Return value: `true` if glyph was drawn, `false` otherwise
* *
* XSince: REPLACEME
**/ **/
typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_draw_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data, hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data); void *user_data);
/** /**
* hb_font_paint_glyph_func_t: * hb_font_paint_glyph_or_fail_func_t:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @font_data: @font user data pointer * @font_data: @font user data pointer
* @glyph: The glyph ID to query * @glyph: The glyph ID to query
@ -517,14 +518,16 @@ typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* Since: 7.0.0 * Return value: `true` if glyph was painted, `false` otherwise
*
* XSince: REPLACEME
*/ */
typedef void (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_paint_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs, void *paint_data, hb_paint_funcs_t *paint_funcs, void *paint_data,
unsigned int palette_index, unsigned int palette_index,
hb_color_t foreground, hb_color_t foreground,
void *user_data); void *user_data);
/* func setters */ /* func setters */
@ -785,36 +788,36 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
void *user_data, hb_destroy_func_t destroy); void *user_data, hb_destroy_func_t destroy);
/** /**
* hb_font_funcs_set_draw_glyph_func: * hb_font_funcs_set_draw_glyph_or_fail_func:
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_draw_glyph_func_t. * Sets the implementation function for #hb_font_draw_glyph_or_fail_func_t.
* *
* Since: 7.0.0 * XSince: REPLACEME
**/ **/
HB_EXTERN void HB_EXTERN void
hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, hb_font_funcs_set_draw_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
hb_font_draw_glyph_func_t func, hb_font_draw_glyph_or_fail_func_t func,
void *user_data, hb_destroy_func_t destroy); void *user_data, hb_destroy_func_t destroy);
/** /**
* hb_font_funcs_set_paint_glyph_func: * hb_font_funcs_set_paint_glyph_or_fail_func:
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is no longer needed * @destroy: (nullable): The function to call when @user_data is no longer needed
* *
* Sets the implementation function for #hb_font_paint_glyph_func_t. * Sets the implementation function for #hb_font_paint_glyph_or_fail_func_t.
* *
* Since: 7.0.0 * XSince: REPLACEME
*/ */
HB_EXTERN void HB_EXTERN void
hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs, hb_font_funcs_set_paint_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
hb_font_paint_glyph_func_t func, hb_font_paint_glyph_or_fail_func_t func,
void *user_data, hb_destroy_func_t destroy); void *user_data, hb_destroy_func_t destroy);
/* func dispatch */ /* func dispatch */
@ -896,17 +899,17 @@ hb_font_get_glyph_from_name (hb_font_t *font,
const char *name, int len, /* -1 means nul-terminated */ const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph); hb_codepoint_t *glyph);
HB_EXTERN void HB_EXTERN hb_bool_t
hb_font_draw_glyph (hb_font_t *font, hb_font_draw_glyph_or_fail (hb_font_t *font,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data); hb_draw_funcs_t *dfuncs, void *draw_data);
HB_EXTERN void HB_EXTERN hb_bool_t
hb_font_paint_glyph (hb_font_t *font, hb_font_paint_glyph_or_fail (hb_font_t *font,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_paint_funcs_t *pfuncs, void *paint_data, hb_paint_funcs_t *pfuncs, void *paint_data,
unsigned int palette_index, unsigned int palette_index,
hb_color_t foreground); hb_color_t foreground);
/* high-level funcs, with fallback */ /* high-level funcs, with fallback */
@ -979,6 +982,19 @@ hb_font_glyph_from_string (hb_font_t *font,
const char *s, int len, /* -1 means nul-terminated */ const char *s, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph); hb_codepoint_t *glyph);
/* Older alias for hb_font_draw_glyph_or_fail() with no return value. */
HB_EXTERN void
hb_font_draw_glyph (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data);
/* Paints color glyph; if failed, draws outline glyph. */
HB_EXTERN void
hb_font_paint_glyph (hb_font_t *font,
hb_codepoint_t glyph,
hb_paint_funcs_t *pfuncs, void *paint_data,
unsigned int palette_index,
hb_color_t foreground);
/* /*
* hb_font_t * hb_font_t
@ -1092,6 +1108,9 @@ hb_font_set_ptem (hb_font_t *font, float ptem);
HB_EXTERN float HB_EXTERN float
hb_font_get_ptem (hb_font_t *font); hb_font_get_ptem (hb_font_t *font);
HB_EXTERN hb_bool_t
hb_font_is_synthetic (hb_font_t *font);
HB_EXTERN void HB_EXTERN void
hb_font_set_synthetic_bold (hb_font_t *font, hb_font_set_synthetic_bold (hb_font_t *font,
float x_embolden, float y_embolden, float x_embolden, float y_embolden,

View File

@ -33,6 +33,8 @@
#include "hb-face.hh" #include "hb-face.hh"
#include "hb-atomic.hh" #include "hb-atomic.hh"
#include "hb-draw.hh"
#include "hb-paint-extents.hh"
#include "hb-shaper.hh" #include "hb-shaper.hh"
#include "hb-outline.hh" #include "hb-outline.hh"
@ -59,8 +61,8 @@
HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \ HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \
HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \ HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \
HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \ HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \
HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \ HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \
HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \ HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \
/* ^--- Add new callbacks here */ /* ^--- Add new callbacks here */
struct hb_font_funcs_t struct hb_font_funcs_t
@ -206,7 +208,7 @@ struct hb_font_t
void synthetic_glyph_extents (hb_glyph_extents_t *extents) void synthetic_glyph_extents (hb_glyph_extents_t *extents)
{ {
/* Apply slant. */ /* Slant. */
if (slant_xy) if (slant_xy)
{ {
hb_position_t x1 = extents->x_bearing; hb_position_t x1 = extents->x_bearing;
@ -221,6 +223,7 @@ struct hb_font_t
extents->width = x2 - extents->x_bearing; extents->width = x2 - extents->x_bearing;
} }
/* Embolden. */
if (x_strength || y_strength) if (x_strength || y_strength)
{ {
/* Y */ /* Y */
@ -263,19 +266,45 @@ struct hb_font_t
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT #undef HB_FONT_FUNC_IMPLEMENT
hb_bool_t get_font_h_extents (hb_font_extents_t *extents) hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
bool synthetic = true)
{ {
hb_memset (extents, 0, sizeof (*extents)); hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.font_h_extents (this, user_data, bool ret = klass->get.f.font_h_extents (this, user_data,
extents, extents,
!klass->user_data ? nullptr : klass->user_data->font_h_extents); !klass->user_data ? nullptr : klass->user_data->font_h_extents);
if (synthetic && ret)
{
/* Embolden */
int y_shift = y_scale < 0 ? -y_strength : y_strength;
extents->ascender += y_shift;
}
return ret;
} }
hb_bool_t get_font_v_extents (hb_font_extents_t *extents) hb_bool_t get_font_v_extents (hb_font_extents_t *extents,
bool synthetic = true)
{ {
hb_memset (extents, 0, sizeof (*extents)); hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.font_v_extents (this, user_data, bool ret = klass->get.f.font_v_extents (this, user_data,
extents, extents,
!klass->user_data ? nullptr : klass->user_data->font_v_extents); !klass->user_data ? nullptr : klass->user_data->font_v_extents);
if (synthetic && ret)
{
/* Embolden */
int x_shift = x_scale < 0 ? -x_strength : x_strength;
if (embolden_in_place)
{
extents->ascender += x_shift / 2;
extents->descender -= x_shift - x_shift / 2;
}
else
extents->ascender += x_shift;
}
return ret;
} }
bool has_glyph (hb_codepoint_t unicode) bool has_glyph (hb_codepoint_t unicode)
@ -316,15 +345,16 @@ struct hb_font_t
!klass->user_data ? nullptr : klass->user_data->variation_glyph); !klass->user_data ? nullptr : klass->user_data->variation_glyph);
} }
hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) hb_position_t get_glyph_h_advance (hb_codepoint_t glyph,
bool synthetic = true)
{ {
hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data, hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
glyph, glyph,
!klass->user_data ? nullptr : klass->user_data->glyph_h_advance); !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
if (x_strength && !embolden_in_place) if (synthetic && x_strength && !embolden_in_place)
{ {
/* Emboldening. */ /* Embolden */
hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
advance += advance ? strength : 0; advance += advance ? strength : 0;
} }
@ -332,15 +362,16 @@ struct hb_font_t
return advance; return advance;
} }
hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) hb_position_t get_glyph_v_advance (hb_codepoint_t glyph,
bool synthetic = true)
{ {
hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data, hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data,
glyph, glyph,
!klass->user_data ? nullptr : klass->user_data->glyph_v_advance); !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
if (y_strength && !embolden_in_place) if (synthetic && y_strength && !embolden_in_place)
{ {
/* Emboldening. */ /* Embolden */
hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
advance += advance ? strength : 0; advance += advance ? strength : 0;
} }
@ -352,7 +383,8 @@ struct hb_font_t
const hb_codepoint_t *first_glyph, const hb_codepoint_t *first_glyph,
unsigned int glyph_stride, unsigned int glyph_stride,
hb_position_t *first_advance, hb_position_t *first_advance,
unsigned int advance_stride) unsigned int advance_stride,
bool synthetic = true)
{ {
klass->get.f.glyph_h_advances (this, user_data, klass->get.f.glyph_h_advances (this, user_data,
count, count,
@ -360,9 +392,9 @@ struct hb_font_t
first_advance, advance_stride, first_advance, advance_stride,
!klass->user_data ? nullptr : klass->user_data->glyph_h_advances); !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
if (x_strength && !embolden_in_place) if (synthetic && x_strength && !embolden_in_place)
{ {
/* Emboldening. */ /* Embolden */
hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
@ -376,7 +408,8 @@ struct hb_font_t
const hb_codepoint_t *first_glyph, const hb_codepoint_t *first_glyph,
unsigned int glyph_stride, unsigned int glyph_stride,
hb_position_t *first_advance, hb_position_t *first_advance,
unsigned int advance_stride) unsigned int advance_stride,
bool synthetic = true)
{ {
klass->get.f.glyph_v_advances (this, user_data, klass->get.f.glyph_v_advances (this, user_data,
count, count,
@ -384,9 +417,9 @@ struct hb_font_t
first_advance, advance_stride, first_advance, advance_stride,
!klass->user_data ? nullptr : klass->user_data->glyph_v_advances); !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
if (y_strength && !embolden_in_place) if (synthetic && y_strength && !embolden_in_place)
{ {
/* Emboldening. */ /* Embolden */
hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
@ -439,9 +472,51 @@ struct hb_font_t
} }
hb_bool_t get_glyph_extents (hb_codepoint_t glyph, hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
hb_glyph_extents_t *extents) hb_glyph_extents_t *extents,
bool synthetic = true)
{ {
hb_memset (extents, 0, sizeof (*extents)); hb_memset (extents, 0, sizeof (*extents));
/* This is rather messy, but necessary. */
if (!synthetic)
{
return klass->get.f.glyph_extents (this, user_data,
glyph,
extents,
!klass->user_data ? nullptr : klass->user_data->glyph_extents);
}
if (!is_synthetic () &&
klass->get.f.glyph_extents (this, user_data,
glyph,
extents,
!klass->user_data ? nullptr : klass->user_data->glyph_extents))
return true;
/* Try getting extents from paint(), then draw(), *then* get_extents()
* and apply synthetic settings in the last case. */
#ifndef HB_NO_PAINT
hb_paint_extents_context_t paint_extents;
if (paint_glyph_or_fail (glyph,
hb_paint_extents_get_funcs (), &paint_extents,
0, 0))
{
*extents = paint_extents.get_extents ().to_glyph_extents ();
return true;
}
#endif
#ifndef HB_NO_DRAW
hb_extents_t draw_extents;
if (draw_glyph_or_fail (glyph,
hb_draw_extents_get_funcs (), &draw_extents))
{
*extents = draw_extents.to_glyph_extents ();
return true;
}
#endif
bool ret = klass->get.f.glyph_extents (this, user_data, bool ret = klass->get.f.glyph_extents (this, user_data,
glyph, glyph,
extents, extents,
@ -453,13 +528,30 @@ struct hb_font_t
} }
hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
hb_position_t *x, hb_position_t *y) hb_position_t *x, hb_position_t *y,
bool synthetic = true)
{ {
*x = *y = 0; *x = *y = 0;
return klass->get.f.glyph_contour_point (this, user_data, bool ret = klass->get.f.glyph_contour_point (this, user_data,
glyph, point_index, glyph, point_index,
x, y, x, y,
!klass->user_data ? nullptr : klass->user_data->glyph_contour_point); !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
if (synthetic && ret)
{
/* Slant */
if (slant_xy)
*x += roundf (*y * slant_xy);
/* Embolden */
if (!embolden_in_place)
{
int x_shift = x_scale < 0 ? -x_strength : x_strength;
*x += x_shift;
}
}
return ret;
} }
hb_bool_t get_glyph_name (hb_codepoint_t glyph, hb_bool_t get_glyph_name (hb_codepoint_t glyph,
@ -483,56 +575,94 @@ struct hb_font_t
!klass->user_data ? nullptr : klass->user_data->glyph_from_name); !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
} }
void draw_glyph (hb_codepoint_t glyph, bool draw_glyph_or_fail (hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data) hb_draw_funcs_t *draw_funcs, void *draw_data,
bool synthetic = true)
{ {
#ifndef HB_NO_DRAW
#ifndef HB_NO_OUTLINE #ifndef HB_NO_OUTLINE
bool embolden = x_strength || y_strength; bool embolden = x_strength || y_strength;
bool slanted = slant_xy;
synthetic = synthetic && (embolden || slanted);
#else #else
constexpr bool embolden = false; synthetic = false;
#endif #endif
if (!embolden) if (!synthetic)
{ {
klass->get.f.draw_glyph (this, user_data, return klass->get.f.draw_glyph_or_fail (this, user_data,
glyph, glyph,
draw_funcs, draw_data, draw_funcs, draw_data,
!klass->user_data ? nullptr : klass->user_data->draw_glyph); !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail);
return;
} }
#ifndef HB_NO_OUTLINE #ifndef HB_NO_OUTLINE
/* Emboldening. */
hb_outline_t outline;
klass->get.f.draw_glyph (this, user_data,
glyph,
hb_outline_recording_pen_get_funcs (), &outline,
!klass->user_data ? nullptr : klass->user_data->draw_glyph);
float x_shift = embolden_in_place ? 0 : (float) x_strength / 2; hb_outline_t outline;
float y_shift = (float) y_strength / 2; if (!klass->get.f.draw_glyph_or_fail (this, user_data,
if (x_scale < 0) x_shift = -x_shift; glyph,
if (y_scale < 0) y_shift = -y_shift; hb_outline_recording_pen_get_funcs (), &outline,
outline.embolden (x_strength, y_strength, x_shift, y_shift); !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail))
return false;
// Slant before embolden; produces nicer results.
if (slanted)
outline.slant (slant_xy);
if (embolden)
{
float x_shift = embolden_in_place ? 0 : (float) x_strength / 2;
float y_shift = (float) y_strength / 2;
if (x_scale < 0) x_shift = -x_shift;
if (y_scale < 0) y_shift = -y_shift;
outline.embolden (x_strength, y_strength, x_shift, y_shift);
}
outline.replay (draw_funcs, draw_data); outline.replay (draw_funcs, draw_data);
return true;
#endif #endif
#endif
return false;
} }
void paint_glyph (hb_codepoint_t glyph, bool paint_glyph_or_fail (hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs, void *paint_data, hb_paint_funcs_t *paint_funcs, void *paint_data,
unsigned int palette, unsigned int palette,
hb_color_t foreground) hb_color_t foreground,
bool synthetic = true)
{ {
klass->get.f.paint_glyph (this, user_data, #ifndef HB_NO_PAINT
glyph, /* Slant */
paint_funcs, paint_data, if (synthetic && slant_xy)
palette, foreground, hb_paint_push_transform (paint_funcs, paint_data,
!klass->user_data ? nullptr : klass->user_data->paint_glyph); 1.f, 0.f,
slant_xy, 1.f,
0.f, 0.f);
bool ret = klass->get.f.paint_glyph_or_fail (this, user_data,
glyph,
paint_funcs, paint_data,
palette, foreground,
!klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail);
if (synthetic && slant_xy)
hb_paint_pop_transform (paint_funcs, paint_data);
return ret;
#endif
return false;
} }
/* A bit higher-level, and with fallback */ /* A bit higher-level, and with fallback */
HB_INTERNAL
void paint_glyph (hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs, void *paint_data,
unsigned int palette,
hb_color_t foreground);
void get_h_extents_with_fallback (hb_font_extents_t *extents) void get_h_extents_with_fallback (hb_font_extents_t *extents)
{ {
if (!get_font_h_extents (extents)) if (!get_font_h_extents (extents))
@ -770,6 +900,11 @@ struct hb_font_t
return false; return false;
} }
bool is_synthetic () const
{
return x_embolden || y_embolden || slant;
}
void changed () void changed ()
{ {
float upem = face->get_upem (); float upem = face->get_upem ();

View File

@ -28,7 +28,7 @@
#include "hb.hh" #include "hb.hh"
#include "hb-decycler.hh" #include "hb-decycler.hh"
#include "hb-paint-extents.hh" #include "hb-paint-bounded.hh"
#include FT_COLOR_H #include FT_COLOR_H
@ -80,15 +80,30 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
struct hb_ft_paint_context_t struct hb_ft_paint_context_t
{ {
hb_ft_paint_context_t (const hb_ft_font_t *ft_font, hb_ft_paint_context_t (const hb_ft_font_t *ft_font_,
hb_font_t *font, hb_font_t *font_,
hb_paint_funcs_t *paint_funcs, void *paint_data, hb_paint_funcs_t *paint_funcs, void *paint_data,
hb_array_t<const FT_Color> palette, hb_array_t<const FT_Color> palette,
unsigned palette_index, unsigned palette_index,
hb_color_t foreground) : hb_color_t foreground) :
ft_font (ft_font), font(font), ft_font (ft_font_), font (font_),
funcs (paint_funcs), data (paint_data), funcs (paint_funcs), data (paint_data),
palette (palette), palette_index (palette_index), foreground (foreground) {} palette (palette), palette_index (palette_index), foreground (foreground)
{
if (font->is_synthetic ())
{
font = hb_font_create_sub_font (font);
hb_font_set_synthetic_bold (font, 0, 0, true);
hb_font_set_synthetic_slant (font, 0);
}
else
hb_font_reference (font);
}
~hb_ft_paint_context_t ()
{
hb_font_destroy (font);
}
void recurse (FT_OpaquePaint paint) void recurse (FT_OpaquePaint paint)
{ {
@ -512,52 +527,41 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
hb_decycler_node_t node (c.glyphs_decycler); hb_decycler_node_t node (c.glyphs_decycler);
node.visit (gid); node.visit (gid);
bool is_bounded = true; bool clip = false;
bool is_bounded = false;
FT_ClipBox clip_box; FT_ClipBox clip_box;
if (FT_Get_Color_Glyph_ClipBox (ft_face, gid, &clip_box)) if (FT_Get_Color_Glyph_ClipBox (ft_face, gid, &clip_box))
{ {
c.funcs->push_clip_rectangle (c.data, c.funcs->push_clip_rectangle (c.data,
clip_box.bottom_left.x + clip_box.bottom_left.x,
roundf (hb_min (font->slant_xy * clip_box.bottom_left.y,
font->slant_xy * clip_box.top_left.y)),
clip_box.bottom_left.y, clip_box.bottom_left.y,
clip_box.top_right.x + clip_box.top_right.x,
roundf (hb_max (font->slant_xy * clip_box.bottom_right.y,
font->slant_xy * clip_box.top_right.y)),
clip_box.top_right.y); clip_box.top_right.y);
clip = true;
is_bounded = true;
} }
else if (!is_bounded)
{ {
auto *bounded_funcs = hb_paint_bounded_get_funcs ();
auto *extents_funcs = hb_paint_extents_get_funcs (); hb_paint_bounded_context_t bounded_data;
hb_paint_extents_context_t extents_data;
hb_ft_paint_context_t ce (ft_font, font, hb_ft_paint_context_t ce (ft_font, font,
extents_funcs, &extents_data, bounded_funcs, &bounded_data,
palette_array, palette_index, foreground); palette_array, palette_index, foreground);
hb_decycler_node_t node2 (ce.glyphs_decycler); hb_decycler_node_t node2 (ce.glyphs_decycler);
node2.visit (gid); node2.visit (gid);
ce.funcs->push_font_transform (ce.data, font);
ce.recurse (paint); ce.recurse (paint);
ce.funcs->pop_transform (ce.data); is_bounded = bounded_data.is_bounded ();
hb_extents_t extents = extents_data.get_extents ();
is_bounded = extents_data.is_bounded ();
c.funcs->push_clip_rectangle (c.data,
extents.xmin,
extents.ymin,
extents.xmax,
extents.ymax);
} }
c.funcs->push_font_transform (c.data, font); c.funcs->push_font_transform (c.data, font);
if (is_bounded) if (is_bounded)
{
c.recurse (paint); c.recurse (paint);
}
c.funcs->pop_transform (c.data); c.funcs->pop_transform (c.data);
c.funcs->pop_clip (c.data);
if (clip)
c.funcs->pop_clip (c.data);
return true; return true;
} }

View File

@ -626,6 +626,41 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
} }
#endif #endif
static bool
hb_ft_is_colr_glyph (hb_font_t *font,
void *font_data,
hb_codepoint_t gid)
{
#ifndef HB_NO_PAINT
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
FT_Face ft_face = ft_font->ft_face;
/* COLRv1 */
FT_OpaquePaint paint = {0};
if (FT_Get_Color_Glyph_Paint (ft_face, gid,
FT_COLOR_NO_ROOT_TRANSFORM,
&paint))
return true;
/* COLRv0 */
FT_LayerIterator iterator;
FT_UInt layer_glyph_index;
FT_UInt layer_color_index;
iterator.p = NULL;
if (FT_Get_Color_Glyph_Layer (ft_face,
gid,
&layer_glyph_index,
&layer_color_index,
&iterator))
return true;
#endif
#endif
return false;
}
static hb_bool_t static hb_bool_t
hb_ft_get_glyph_extents (hb_font_t *font, hb_ft_get_glyph_extents (hb_font_t *font,
void *font_data, void *font_data,
@ -633,6 +668,10 @@ hb_ft_get_glyph_extents (hb_font_t *font,
hb_glyph_extents_t *extents, hb_glyph_extents_t *extents,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
// FreeType doesn't return COLR glyph extents.
if (hb_ft_is_colr_glyph (font, font_data, glyph))
return false;
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
_hb_ft_hb_font_check_changed (font, ft_font); _hb_ft_hb_font_check_changed (font, ft_font);
@ -797,7 +836,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender); metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
} }
metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength)); metrics->ascender = (hb_position_t) (y_mult * metrics->ascender);
metrics->descender = (hb_position_t) (y_mult * metrics->descender); metrics->descender = (hb_position_t) (y_mult * metrics->descender);
metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap); metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
@ -848,12 +887,12 @@ _hb_ft_cubic_to (const FT_Vector *control1,
return FT_Err_Ok; return FT_Err_Ok;
} }
static void static hb_bool_t
hb_ft_draw_glyph (hb_font_t *font, hb_ft_draw_glyph_or_fail (hb_font_t *font,
void *font_data, void *font_data,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data, hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
_hb_ft_hb_font_check_changed (font, ft_font); _hb_ft_hb_font_check_changed (font, ft_font);
@ -863,10 +902,10 @@ hb_ft_draw_glyph (hb_font_t *font,
if (unlikely (FT_Load_Glyph (ft_face, glyph, if (unlikely (FT_Load_Glyph (ft_face, glyph,
FT_LOAD_NO_BITMAP | ft_font->load_flags))) FT_LOAD_NO_BITMAP | ft_font->load_flags)))
return; return false;
if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
return; return false;
const FT_Outline_Funcs outline_funcs = { const FT_Outline_Funcs outline_funcs = {
_hb_ft_move_to, _hb_ft_move_to,
@ -877,11 +916,13 @@ hb_ft_draw_glyph (hb_font_t *font,
0, /* delta */ 0, /* delta */
}; };
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); hb_draw_session_t draw_session {draw_funcs, draw_data};
FT_Outline_Decompose (&ft_face->glyph->outline, FT_Outline_Decompose (&ft_face->glyph->outline,
&outline_funcs, &outline_funcs,
&draw_session); &draw_session);
return true;
} }
#endif #endif
@ -890,14 +931,14 @@ hb_ft_draw_glyph (hb_font_t *font,
#include "hb-ft-colr.hh" #include "hb-ft-colr.hh"
static void static hb_bool_t
hb_ft_paint_glyph (hb_font_t *font, hb_ft_paint_glyph_or_fail (hb_font_t *font,
void *font_data, void *font_data,
hb_codepoint_t gid, hb_codepoint_t gid,
hb_paint_funcs_t *paint_funcs, void *paint_data, hb_paint_funcs_t *paint_funcs, void *paint_data,
unsigned int palette_index, unsigned int palette_index,
hb_color_t foreground, hb_color_t foreground,
void *user_data) void *user_data)
{ {
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
_hb_ft_hb_font_check_changed (font, ft_font); _hb_ft_hb_font_check_changed (font, ft_font);
@ -905,7 +946,7 @@ hb_ft_paint_glyph (hb_font_t *font,
hb_lock_t lock (ft_font->lock); hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face; FT_Face ft_face = ft_font->ft_face;
FT_Long load_flags = ft_font->load_flags | FT_LOAD_NO_BITMAP | FT_LOAD_COLOR; FT_Long load_flags = ft_font->load_flags | FT_LOAD_COLOR;
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301 #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301
load_flags |= FT_LOAD_NO_SVG; load_flags |= FT_LOAD_NO_SVG;
#endif #endif
@ -914,7 +955,7 @@ hb_ft_paint_glyph (hb_font_t *font,
* eg. draw API can call back into the face.*/ * eg. draw API can call back into the face.*/
if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags))) if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags)))
return; return false;
if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
{ {
@ -922,26 +963,21 @@ hb_ft_paint_glyph (hb_font_t *font,
paint_funcs, paint_data, paint_funcs, paint_data,
palette_index, foreground, palette_index, foreground,
user_data)) user_data))
return; return true;
/* Simple outline. */ // Outline glyph
ft_font->lock.unlock (); return false;
paint_funcs->push_clip_glyph (paint_data, gid, font);
ft_font->lock.lock ();
paint_funcs->color (paint_data, true, foreground);
paint_funcs->pop_clip (paint_data);
return;
} }
auto *glyph = ft_face->glyph; auto *glyph = ft_face->glyph;
if (glyph->format == FT_GLYPH_FORMAT_BITMAP) if (glyph->format == FT_GLYPH_FORMAT_BITMAP)
{ {
bool ret = false;
auto &bitmap = glyph->bitmap; auto &bitmap = glyph->bitmap;
if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
{ {
if (bitmap.pitch != (signed) bitmap.width * 4) if (bitmap.pitch != (signed) bitmap.width * 4)
return; return ret;
ft_font->lock.unlock (); ft_font->lock.unlock ();
@ -951,27 +987,26 @@ hb_ft_paint_glyph (hb_font_t *font,
nullptr, nullptr); nullptr, nullptr);
hb_glyph_extents_t extents; hb_glyph_extents_t extents;
if (!hb_font_get_glyph_extents (font, gid, &extents)) if (!font->get_glyph_extents (gid, &extents, false))
goto out; goto out;
if (!paint_funcs->image (paint_data, if (paint_funcs->image (paint_data,
blob, blob,
bitmap.width, bitmap.width,
bitmap.rows, bitmap.rows,
HB_PAINT_IMAGE_FORMAT_BGRA, HB_PAINT_IMAGE_FORMAT_BGRA,
font->slant_xy, 0.f,
&extents)) &extents))
{ ret = true;
/* TODO Try a forced outline load and paint? */
}
out: out:
hb_blob_destroy (blob); hb_blob_destroy (blob);
ft_font->lock.lock (); ft_font->lock.lock ();
} }
return; return ret;
} }
return false;
} }
#endif #endif
#endif #endif
@ -1006,12 +1041,12 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
#ifndef HB_NO_DRAW #ifndef HB_NO_DRAW
hb_font_funcs_set_draw_glyph_func (funcs, hb_ft_draw_glyph, nullptr, nullptr); hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ft_draw_glyph_or_fail, nullptr, nullptr);
#endif #endif
#ifndef HB_NO_PAINT #ifndef HB_NO_PAINT
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300 #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr); hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ft_paint_glyph_or_fail, nullptr, nullptr);
#endif #endif
#endif #endif

View File

@ -0,0 +1,150 @@
/*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author(s): Behdad Esfahbod
*/
#include "hb.hh"
#ifdef HAVE_HARFRUZZ
#include "hb-shaper-impl.hh"
/*
* shaper face data
*/
extern "C" void *
_hb_harfruzz_shaper_face_data_create_rs (hb_face_t *face);
hb_harfruzz_face_data_t *
_hb_harfruzz_shaper_face_data_create (hb_face_t *face)
{
return (hb_harfruzz_face_data_t *) _hb_harfruzz_shaper_face_data_create_rs (face);
}
extern "C" void
_hb_harfruzz_shaper_face_data_destroy_rs (void *data);
void
_hb_harfruzz_shaper_face_data_destroy (hb_harfruzz_face_data_t *data)
{
_hb_harfruzz_shaper_face_data_destroy_rs (data);
}
/*
* shaper font data
*/
extern "C" void *
_hb_harfruzz_shaper_font_data_create_rs (hb_font_t *font, const void *face_data);
hb_harfruzz_font_data_t *
_hb_harfruzz_shaper_font_data_create (hb_font_t *font)
{
const hb_harfruzz_face_data_t *face_data = font->face->data.harfruzz;
return (hb_harfruzz_font_data_t *) _hb_harfruzz_shaper_font_data_create_rs (font, face_data);
}
extern "C" void
_hb_harfruzz_shaper_font_data_destroy_rs (void *data);
void
_hb_harfruzz_shaper_font_data_destroy (hb_harfruzz_font_data_t *data)
{
_hb_harfruzz_shaper_font_data_destroy_rs (data);
}
/*
* shape plan
*/
extern "C" void *
_hb_harfruzz_shape_plan_create_rs (const void *font_data,
hb_script_t script,
hb_language_t language,
hb_direction_t direction);
extern "C" void
_hb_harfruzz_shape_plan_destroy_rs (void *data);
/*
* shaper
*/
extern "C" hb_bool_t
_hb_harfruzz_shape_rs (const void *face_data,
const void *rs_shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features);
static hb_user_data_key_t hr_shape_plan_key = {0};
hb_bool_t
_hb_harfruzz_shape (hb_shape_plan_t *shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features)
{
const hb_harfruzz_font_data_t *font_data = font->data.harfruzz;
void *hr_shape_plan = nullptr;
if (!num_features)
{
retry:
hr_shape_plan = hb_shape_plan_get_user_data (shape_plan,
&hr_shape_plan_key);
if (unlikely (!hr_shape_plan))
{
hr_shape_plan = _hb_harfruzz_shape_plan_create_rs (font_data,
shape_plan->key.props.script,
shape_plan->key.props.language,
shape_plan->key.props.direction);
if (hr_shape_plan &&
!hb_shape_plan_set_user_data (shape_plan,
&hr_shape_plan_key,
hr_shape_plan,
_hb_harfruzz_shape_plan_destroy_rs,
false))
{
_hb_harfruzz_shape_plan_destroy_rs (hr_shape_plan);
goto retry;
}
}
}
return _hb_harfruzz_shape_rs (font_data,
hr_shape_plan,
font,
buffer,
features,
num_features);
}
#endif

View File

@ -273,7 +273,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
private: private:
/* Must only have one pointer. */ /* Must only have one pointer. */
hb_atomic_t<Stored *> instance; mutable hb_atomic_t<Stored *> instance;
}; };
/* Specializations. */ /* Specializations. */

View File

@ -412,15 +412,15 @@ 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_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face; 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 !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
if (ot_face->sbix->get_extents (font, glyph, extents)) return true; if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true; if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
#endif #endif
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT) #if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
if (ot_face->COLR->get_extents (font, glyph, extents)) return true; if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
#endif
#ifndef HB_NO_VAR_COMPOSITES
if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
#endif #endif
if (ot_face->glyf->get_extents (font, glyph, extents)) return true; if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
#ifndef HB_NO_OT_FONT_CFF #ifndef HB_NO_OT_FONT_CFF
@ -472,16 +472,9 @@ hb_ot_get_font_h_extents (hb_font_t *font,
hb_font_extents_t *metrics, hb_font_extents_t *metrics,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
bool ret = _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) && return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) && _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
/* Embolden */
int y_shift = font->y_strength;
if (font->y_scale < 0) y_shift = -y_shift;
metrics->ascender += y_shift;
return ret;
} }
#ifndef HB_NO_VERTICAL #ifndef HB_NO_VERTICAL
@ -498,50 +491,46 @@ hb_ot_get_font_v_extents (hb_font_t *font,
#endif #endif
#ifndef HB_NO_DRAW #ifndef HB_NO_DRAW
static void static hb_bool_t
hb_ot_draw_glyph (hb_font_t *font, hb_ot_draw_glyph_or_fail (hb_font_t *font,
void *font_data HB_UNUSED, void *font_data HB_UNUSED,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data, hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data) void *user_data)
{ {
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); hb_draw_session_t draw_session {draw_funcs, draw_data};
#ifndef HB_NO_VAR_COMPOSITES #ifndef HB_NO_VAR_COMPOSITES
if (!font->face->table.VARC->get_path (font, glyph, draw_session)) if (font->face->table.VARC->get_path (font, glyph, draw_session)) return true;
#endif #endif
// Keep the following in synch with VARC::get_path_at() // Keep the following in synch with VARC::get_path_at()
if (!font->face->table.glyf->get_path (font, glyph, draw_session)) if (font->face->table.glyf->get_path (font, glyph, draw_session)) return true;
#ifndef HB_NO_CFF #ifndef HB_NO_CFF
if (!font->face->table.cff2->get_path (font, glyph, draw_session)) if (font->face->table.cff2->get_path (font, glyph, draw_session)) return true;
if (!font->face->table.cff1->get_path (font, glyph, draw_session)) if (font->face->table.cff1->get_path (font, glyph, draw_session)) return true;
#endif #endif
{} return false;
} }
#endif #endif
#ifndef HB_NO_PAINT #ifndef HB_NO_PAINT
static void static hb_bool_t
hb_ot_paint_glyph (hb_font_t *font, hb_ot_paint_glyph_or_fail (hb_font_t *font,
void *font_data, void *font_data,
hb_codepoint_t glyph, hb_codepoint_t glyph,
hb_paint_funcs_t *paint_funcs, void *paint_data, hb_paint_funcs_t *paint_funcs, void *paint_data,
unsigned int palette, unsigned int palette,
hb_color_t foreground, hb_color_t foreground,
void *user_data) void *user_data)
{ {
#ifndef HB_NO_COLOR #ifndef HB_NO_COLOR
if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return; if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true;
if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return; if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
#ifndef HB_NO_OT_FONT_BITMAP #ifndef HB_NO_OT_FONT_BITMAP
if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return; if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return; if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
#endif #endif
#endif #endif
return false;
// Outline glyph
paint_funcs->push_clip_glyph (paint_data, glyph, font);
paint_funcs->color (paint_data, true, foreground);
paint_funcs->pop_clip (paint_data);
} }
#endif #endif
@ -568,11 +557,11 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
#endif #endif
#ifndef HB_NO_DRAW #ifndef HB_NO_DRAW
hb_font_funcs_set_draw_glyph_func (funcs, hb_ot_draw_glyph, nullptr, nullptr); hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr);
#endif #endif
#ifndef HB_NO_PAINT #ifndef HB_NO_PAINT
hb_font_funcs_set_paint_glyph_func (funcs, hb_ot_paint_glyph, nullptr, nullptr); hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr);
#endif #endif
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);

View File

@ -182,7 +182,7 @@ struct BaseCoord
void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
{ {
switch (u.format) { switch (u.format) {
case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); return;
default:return; default:return;
} }
} }

View File

@ -397,292 +397,277 @@ struct hb_collect_coverage_context_t :
set_t *set; set_t *set;
}; };
struct hb_ot_apply_context_t : struct matcher_t
hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
{ {
struct matcher_t typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
template <typename context_t>
void init (const context_t *c, bool context_match = false)
{ {
typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data); set_match_func (nullptr, nullptr);
lookup_props = c->lookup_props;
/* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
ignore_zwnj = c->table_index == 1 || (context_match && c->auto_zwnj);
/* Ignore ZWJ if we are matching context, or asked to. */
ignore_zwj = context_match || c->auto_zwj;
/* Ignore hidden glyphs (like CGJ) during GPOS. */
ignore_hidden = c->table_index == 1;
mask = context_match ? -1 : c->lookup_mask;
/* Per syllable matching is only for GSUB. */
per_syllable = c->table_index == 0 && c->per_syllable;
syllable = 0;
}
void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } void set_match_func (match_func_t match_func_,
void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } const void *match_data_)
void set_ignore_hidden (bool ignore_hidden_) { ignore_hidden = ignore_hidden_; } { match_func = match_func_; match_data = match_data_; }
void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
void set_mask (hb_mask_t mask_) { mask = mask_; }
void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; }
void set_syllable (uint8_t syllable_) { syllable = per_syllable ? syllable_ : 0; }
void set_match_func (match_func_t match_func_,
const void *match_data_)
{ match_func = match_func_; match_data = match_data_; }
enum may_match_t { enum may_match_t {
MATCH_NO, MATCH_NO,
MATCH_YES, MATCH_YES,
MATCH_MAYBE MATCH_MAYBE
};
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_match_t may_match (hb_glyph_info_t &info,
hb_codepoint_t glyph_data) const
{
if (!(info.mask & mask) ||
(syllable && syllable != info.syllable ()))
return MATCH_NO;
if (match_func)
return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
}
enum may_skip_t {
SKIP_NO,
SKIP_YES,
SKIP_MAYBE
};
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_skip_t may_skip (const hb_ot_apply_context_t *c,
const hb_glyph_info_t &info) const
{
if (!c->check_glyph_property (&info, lookup_props))
return SKIP_YES;
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
(ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
(ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
(ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
return SKIP_MAYBE;
return SKIP_NO;
}
protected:
unsigned int lookup_props = 0;
hb_mask_t mask = -1;
bool ignore_zwnj = false;
bool ignore_zwj = false;
bool ignore_hidden = false;
bool per_syllable = false;
uint8_t syllable = 0;
match_func_t match_func = nullptr;
const void *match_data = nullptr;
}; };
struct skipping_iterator_t #ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_match_t may_match (hb_glyph_info_t &info,
hb_codepoint_t glyph_data) const
{ {
void init (hb_ot_apply_context_t *c_, bool context_match = false) if (!(info.mask & mask) ||
{ (per_syllable && syllable && syllable != info.syllable ()))
c = c_; return MATCH_NO;
end = c->buffer->len;
match_glyph_data16 = nullptr; if (match_func)
return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
}
enum may_skip_t {
SKIP_NO,
SKIP_YES,
SKIP_MAYBE
};
template <typename context_t>
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_skip_t may_skip (const context_t *c,
const hb_glyph_info_t &info) const
{
if (!c->check_glyph_property (&info, lookup_props))
return SKIP_YES;
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
(ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
(ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
(ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
return SKIP_MAYBE;
return SKIP_NO;
}
public:
unsigned int lookup_props = 0;
hb_mask_t mask = -1;
bool ignore_zwnj = false;
bool ignore_zwj = false;
bool ignore_hidden = false;
bool per_syllable = false;
uint8_t syllable = 0;
match_func_t match_func = nullptr;
const void *match_data = nullptr;
};
template <typename context_t>
struct skipping_iterator_t
{
void init (context_t *c_, bool context_match = false)
{
c = c_;
end = c->buffer->len;
match_glyph_data16 = nullptr;
#ifndef HB_NO_BEYOND_64K #ifndef HB_NO_BEYOND_64K
match_glyph_data24 = nullptr; match_glyph_data24 = nullptr;
#endif #endif
matcher.set_match_func (nullptr, nullptr); matcher.init (c, context_match);
matcher.set_lookup_props (c->lookup_props); }
/* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */ void set_lookup_props (unsigned int lookup_props)
matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj)); {
/* Ignore ZWJ if we are matching context, or asked to. */ matcher.lookup_props = lookup_props;
matcher.set_ignore_zwj (context_match || c->auto_zwj); }
/* Ignore hidden glyphs (like CGJ) during GPOS. */ void set_match_func (matcher_t::match_func_t match_func_,
matcher.set_ignore_hidden (c->table_index == 1); const void *match_data_)
matcher.set_mask (context_match ? -1 : c->lookup_mask); {
/* Per syllable matching is only for GSUB. */ matcher.set_match_func (match_func_, match_data_);
matcher.set_per_syllable (c->table_index == 0 && c->per_syllable); }
matcher.set_syllable (0); void set_glyph_data (const HBUINT16 glyph_data[])
} {
void set_lookup_props (unsigned int lookup_props) match_glyph_data16 = glyph_data;
{
matcher.set_lookup_props (lookup_props);
}
void set_match_func (matcher_t::match_func_t match_func_,
const void *match_data_)
{
matcher.set_match_func (match_func_, match_data_);
}
void set_glyph_data (const HBUINT16 glyph_data[])
{
match_glyph_data16 = glyph_data;
#ifndef HB_NO_BEYOND_64K #ifndef HB_NO_BEYOND_64K
match_glyph_data24 = nullptr; match_glyph_data24 = nullptr;
#endif #endif
} }
#ifndef HB_NO_BEYOND_64K #ifndef HB_NO_BEYOND_64K
void set_glyph_data (const HBUINT24 glyph_data[]) void set_glyph_data (const HBUINT24 glyph_data[])
{ {
match_glyph_data16 = nullptr; match_glyph_data16 = nullptr;
match_glyph_data24 = glyph_data; match_glyph_data24 = glyph_data;
} }
#endif #endif
#ifndef HB_OPTIMIZE_SIZE #ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE HB_ALWAYS_INLINE
#endif #endif
void reset (unsigned int start_index_) void reset (unsigned int start_index_)
{ {
idx = start_index_; idx = start_index_;
end = c->buffer->len; end = c->buffer->len;
matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); matcher.syllable = start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0;
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
void reset_fast (unsigned int start_index_)
{
// Doesn't set end or syllable. Used by GPOS which doesn't care / change.
idx = start_index_;
}
void reject ()
{
backup_glyph_data ();
}
matcher_t::may_skip_t
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
enum match_t {
MATCH,
NOT_MATCH,
SKIP
};
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
match_t match (hb_glyph_info_t &info)
{
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
return SKIP;
matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
return MATCH;
if (skip == matcher_t::SKIP_NO)
return NOT_MATCH;
return SKIP;
} }
#ifndef HB_OPTIMIZE_SIZE #ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE HB_ALWAYS_INLINE
#endif #endif
bool next (unsigned *unsafe_to = nullptr) void reset_fast (unsigned int start_index_)
{ {
const signed stop = (signed) end - 1; // Doesn't set end or syllable. Used by GPOS which doesn't care / change.
while ((signed) idx < stop) idx = start_index_;
{ }
idx++;
switch (match (c->buffer->info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_to)
*unsafe_to = idx + 1;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_to)
*unsafe_to = end;
return false;
}
#ifndef HB_OPTIMIZE_SIZE #ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE HB_ALWAYS_INLINE
#endif #endif
bool prev (unsigned *unsafe_from = nullptr) matcher_t::may_skip_t may_skip (const hb_glyph_info_t &info) const
{ { return matcher.may_skip (c, info); }
const unsigned stop = 0;
while (idx > stop)
{
idx--;
switch (match (c->buffer->out_info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_from)
*unsafe_from = hb_max (1u, idx) - 1u;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_from)
*unsafe_from = 0;
return false;
}
HB_ALWAYS_INLINE enum match_t {
hb_codepoint_t MATCH,
get_glyph_data () NOT_MATCH,
{ SKIP
if (match_glyph_data16) return *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) return *match_glyph_data24;
#endif
return 0;
}
HB_ALWAYS_INLINE
void
advance_glyph_data ()
{
if (match_glyph_data16) match_glyph_data16++;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) match_glyph_data24++;
#endif
}
void
backup_glyph_data ()
{
if (match_glyph_data16) match_glyph_data16--;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) match_glyph_data24--;
#endif
}
unsigned int idx;
protected:
hb_ot_apply_context_t *c;
matcher_t matcher;
const HBUINT16 *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
const HBUINT24 *match_glyph_data24;
#endif
unsigned int end;
}; };
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
match_t match (hb_glyph_info_t &info)
{
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
return SKIP;
matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
return MATCH;
if (skip == matcher_t::SKIP_NO)
return NOT_MATCH;
return SKIP;
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
bool next (unsigned *unsafe_to = nullptr)
{
const signed stop = (signed) end - 1;
while ((signed) idx < stop)
{
idx++;
switch (match (c->buffer->info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_to)
*unsafe_to = idx + 1;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_to)
*unsafe_to = end;
return false;
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
bool prev (unsigned *unsafe_from = nullptr)
{
const unsigned stop = 0;
while (idx > stop)
{
idx--;
switch (match (c->buffer->out_info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_from)
*unsafe_from = hb_max (1u, idx) - 1u;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_from)
*unsafe_from = 0;
return false;
}
HB_ALWAYS_INLINE
hb_codepoint_t
get_glyph_data ()
{
if (match_glyph_data16) return *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) return *match_glyph_data24;
#endif
return 0;
}
HB_ALWAYS_INLINE
void
advance_glyph_data ()
{
if (match_glyph_data16) match_glyph_data16++;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) match_glyph_data24++;
#endif
}
unsigned int idx;
protected:
context_t *c;
matcher_t matcher;
const HBUINT16 *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
const HBUINT24 *match_glyph_data24;
#endif
unsigned int end;
};
struct hb_ot_apply_context_t :
hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
{
const char *get_name () { return "APPLY"; } const char *get_name () { return "APPLY"; }
typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index); typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
template <typename T> template <typename T>
@ -703,7 +688,7 @@ struct hb_ot_apply_context_t :
return ret; return ret;
} }
skipping_iterator_t iter_input, iter_context; skipping_iterator_t<hb_ot_apply_context_t> iter_input, iter_context;
unsigned int table_index; /* GSUB/GPOS */ unsigned int table_index; /* GSUB/GPOS */
hb_font_t *font; hb_font_t *font;
@ -1270,7 +1255,7 @@ static bool match_input (hb_ot_apply_context_t *c,
hb_buffer_t *buffer = c->buffer; hb_buffer_t *buffer = c->buffer;
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx); skippy_iter.reset (buffer->idx);
skippy_iter.set_match_func (match_func, match_data); skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (input); skippy_iter.set_glyph_data (input);
@ -1349,7 +1334,7 @@ static bool match_input (hb_ot_apply_context_t *c,
j--; j--;
} }
if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES) if (found && skippy_iter.may_skip (out[j]) == matcher_t::SKIP_YES)
ligbase = LIGBASE_MAY_SKIP; ligbase = LIGBASE_MAY_SKIP;
else else
ligbase = LIGBASE_MAY_NOT_SKIP; ligbase = LIGBASE_MAY_NOT_SKIP;
@ -1512,7 +1497,7 @@ static bool match_backtrack (hb_ot_apply_context_t *c,
{ {
TRACE_APPLY (nullptr); TRACE_APPLY (nullptr);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; auto &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->backtrack_len ()); skippy_iter.reset (c->buffer->backtrack_len ());
skippy_iter.set_match_func (match_func, match_data); skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (backtrack); skippy_iter.set_glyph_data (backtrack);
@ -1545,7 +1530,7 @@ static bool match_lookahead (hb_ot_apply_context_t *c,
{ {
TRACE_APPLY (nullptr); TRACE_APPLY (nullptr);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; auto &skippy_iter = c->iter_context;
assert (start_index >= 1); assert (start_index >= 1);
skippy_iter.reset (start_index - 1); skippy_iter.reset (start_index - 1);
skippy_iter.set_match_func (match_func, match_data); skippy_iter.set_match_func (match_func, match_data);
@ -2209,7 +2194,7 @@ struct RuleSet
* *
* Replicated from LigatureSet::apply(). */ * Replicated from LigatureSet::apply(). */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset (c->buffer->idx); skippy_iter.reset (c->buffer->idx);
skippy_iter.set_match_func (match_always, nullptr); skippy_iter.set_match_func (match_always, nullptr);
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr); skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
@ -3420,7 +3405,7 @@ struct ChainRuleSet
if (!c->auto_zwnj || !c->auto_zwj) if (!c->auto_zwnj || !c->auto_zwj)
goto slow; goto slow;
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; auto &skippy_iter = c->iter_input;
skippy_iter.reset (c->buffer->idx); skippy_iter.reset (c->buffer->idx);
skippy_iter.set_match_func (match_always, nullptr); skippy_iter.set_match_func (match_always, nullptr);
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr); skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);

View File

@ -290,7 +290,7 @@ struct post
const Array16Of<HBUINT16> *glyphNameIndex = nullptr; const Array16Of<HBUINT16> *glyphNameIndex = nullptr;
hb_vector_t<uint32_t> index_to_offset; hb_vector_t<uint32_t> index_to_offset;
const uint8_t *pool = nullptr; const uint8_t *pool = nullptr;
hb_atomic_t<uint16_t *> gids_sorted_by_name; mutable hb_atomic_t<uint16_t *> gids_sorted_by_name;
}; };
bool has_data () const { return version.to_int (); } bool has_data () const { return version.to_int (); }

View File

@ -260,7 +260,7 @@ struct arabic_shape_plan_t
* mask_array[NONE] == 0. */ * mask_array[NONE] == 0. */
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1]; hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
hb_atomic_t<arabic_fallback_plan_t *> fallback_plan; mutable hb_atomic_t<arabic_fallback_plan_t *> fallback_plan;
unsigned int do_fallback : 1; unsigned int do_fallback : 1;
unsigned int has_stch : 1; unsigned int has_stch : 1;

View File

@ -222,60 +222,60 @@ hb_use_u8[3345] =
133, 134, 0, 0, 0, 0, 0, 0, 0, 2, 2, 52, 30, 2, 2, 2, 133, 134, 0, 0, 0, 0, 0, 0, 0, 2, 2, 52, 30, 2, 2, 2,
2, 2, 2, 2, 2, 10, 22, 59, 99, 76, 135, 136, 137, 0, 0, 0, 2, 2, 2, 2, 2, 10, 22, 59, 99, 76, 135, 136, 137, 0, 0, 0,
0, 2, 138, 2, 2, 2, 2, 139, 0, 30, 2, 42, 5, 0, 79, 15, 0, 2, 138, 2, 2, 2, 2, 139, 0, 30, 2, 42, 5, 0, 79, 15,
2, 53, 22, 140, 52, 53, 2, 2, 105, 10, 9, 0, 0, 0, 0, 0, 2, 140, 20, 53, 128, 140, 2, 2, 141, 10, 9, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 141, 21, 25, 0, 0, 142, 143, 0, 0, 0, 0, 2, 2, 2, 2, 2, 142, 21, 25, 0, 0, 143, 144, 0, 0, 0,
0, 2, 65, 45, 23, 80, 47, 144, 0, 81, 81, 81, 81, 81, 81, 81, 0, 2, 65, 45, 23, 80, 47, 145, 0, 81, 81, 81, 81, 81, 81, 81,
81, 0, 0, 0, 0, 0, 0, 0, 6, 120, 120, 120, 120, 121, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 6, 120, 120, 120, 120, 121, 0, 0,
0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 30, 2, 2, 2, 0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 30, 2, 2, 2,
2, 2, 30, 2, 2, 2, 30, 9, 0, 128, 20, 27, 31, 0, 0, 145, 2, 2, 30, 2, 2, 2, 30, 9, 0, 128, 20, 27, 31, 0, 0, 146,
146, 2, 2, 30, 2, 30, 2, 2, 2, 2, 2, 2, 0, 14, 37, 0, 147, 2, 2, 30, 2, 30, 2, 2, 2, 2, 2, 2, 0, 14, 37, 0,
147, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0, 148, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 30, 2, 2, 9, 2, 2, 11, 41, 0, 0, 0, 0, 0, 0, 0, 0, 30, 2, 2, 9, 2, 2, 11, 41, 0, 0, 0,
0, 2, 2, 2, 0, 27, 22, 22, 30, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 27, 22, 22, 30, 2, 2, 2, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 27, 38, 0, 2, 2, 2, 116, 116, 116, 116, 0, 2, 2, 2, 2, 2, 27, 38, 0, 2, 2, 2, 116, 116, 116, 116,
116, 148, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0, 116, 149, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0,
0, 9, 2, 2, 9, 2, 2, 2, 2, 30, 2, 9, 0, 30, 2, 0, 0, 9, 2, 2, 9, 2, 2, 2, 2, 30, 2, 9, 0, 30, 2, 0,
0, 149, 150, 151, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 20, 0, 150, 151, 152, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 20,
20, 20, 22, 22, 134, 0, 0, 0, 0, 0, 152, 152, 152, 152, 152, 152, 20, 20, 22, 22, 134, 0, 0, 0, 0, 0, 153, 153, 153, 153, 153, 153,
152, 152, 152, 152, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0, 153, 153, 153, 153, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0,
153, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0, 154, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0,
0, 0, 31, 0, 0, 0, 0, 0, 0, 11, 49, 2, 2, 2, 2, 2, 0, 0, 31, 0, 0, 0, 0, 0, 0, 11, 49, 2, 2, 2, 2, 2,
2, 2, 2, 2, 128, 20, 22, 154, 22, 21, 155, 156, 2, 2, 2, 2, 2, 2, 2, 2, 128, 20, 22, 155, 22, 21, 156, 157, 2, 2, 2, 2,
2, 0, 0, 65, 157, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0, 2, 0, 0, 65, 158, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0,
0, 2, 65, 25, 20, 20, 20, 22, 22, 108, 158, 0, 0, 56, 159, 31, 0, 2, 65, 25, 20, 20, 20, 22, 22, 108, 159, 0, 0, 56, 160, 31,
160, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23, 161, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23,
19, 22, 22, 161, 44, 0, 0, 0, 49, 128, 0, 0, 0, 0, 0, 0, 19, 22, 22, 162, 44, 0, 0, 0, 49, 128, 0, 0, 0, 0, 0, 0,
0, 2, 2, 2, 9, 9, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 9, 9, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2,
30, 2, 2, 2, 2, 2, 2, 2, 10, 18, 19, 21, 22, 162, 31, 0, 30, 2, 2, 2, 2, 2, 2, 2, 10, 18, 19, 21, 22, 163, 31, 0,
0, 11, 11, 30, 2, 2, 2, 9, 30, 9, 2, 30, 2, 2, 58, 17, 0, 11, 11, 30, 2, 2, 2, 9, 30, 9, 2, 30, 2, 2, 58, 17,
23, 16, 23, 47, 32, 33, 32, 34, 0, 0, 0, 0, 35, 0, 0, 0, 23, 16, 23, 47, 32, 33, 32, 34, 0, 0, 0, 0, 35, 0, 0, 0,
2, 2, 23, 0, 11, 11, 11, 46, 0, 11, 11, 46, 0, 0, 0, 0, 2, 2, 23, 0, 11, 11, 11, 46, 0, 11, 11, 46, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 30, 0, 9, 2, 2, 2, 30, 45, 59, 20, 0, 2, 2, 2, 2, 2, 30, 0, 9, 2, 2, 2, 30, 45, 59, 20,
20, 31, 33, 32, 32, 25, 163, 29, 164, 165, 37, 0, 0, 0, 0, 0, 20, 31, 33, 32, 32, 25, 164, 29, 165, 166, 37, 0, 0, 0, 0, 0,
0, 12, 26, 0, 0, 0, 0, 0, 0, 2, 2, 65, 25, 20, 20, 20, 0, 12, 26, 0, 0, 0, 0, 0, 0, 2, 2, 65, 25, 20, 20, 20,
22, 23, 126, 15, 17, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 22, 23, 126, 15, 17, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
166, 167, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25, 167, 168, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25,
160, 11, 168, 9, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 161, 11, 169, 9, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
65, 25, 20, 20, 0, 48, 48, 11, 169, 37, 0, 0, 0, 0, 0, 0, 65, 25, 20, 20, 0, 48, 48, 11, 170, 37, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 2, 2, 20, 0, 23, 19, 20, 20, 21, 16, 82, 0, 0, 0, 0, 0, 2, 2, 20, 0, 23, 19, 20, 20, 21, 16, 82,
169, 38, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 10, 170, 170, 38, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 10, 171,
25, 20, 22, 22, 168, 9, 0, 0, 0, 2, 2, 2, 2, 2, 9, 43, 25, 20, 22, 22, 169, 9, 0, 0, 0, 2, 2, 2, 2, 2, 9, 43,
136, 23, 22, 20, 76, 21, 22, 0, 0, 2, 2, 2, 9, 0, 0, 0, 136, 23, 22, 20, 76, 21, 22, 0, 0, 2, 2, 2, 9, 0, 0, 0,
0, 2, 2, 2, 2, 2, 2, 18, 19, 20, 21, 22, 105, 169, 37, 0, 0, 2, 2, 2, 2, 2, 2, 18, 19, 20, 21, 22, 105, 170, 37, 0,
0, 2, 2, 2, 9, 30, 0, 2, 2, 2, 2, 30, 9, 2, 2, 2, 0, 2, 2, 2, 9, 30, 0, 2, 2, 2, 2, 30, 9, 2, 2, 2,
2, 23, 23, 18, 32, 33, 12, 171, 165, 172, 173, 0, 0, 0, 0, 0, 2, 23, 23, 18, 32, 33, 12, 172, 166, 173, 174, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 0, 2, 2, 2, 65, 25, 20, 20, 0, 22, 23, 0, 2, 2, 2, 2, 0, 2, 2, 2, 65, 25, 20, 20, 0, 22, 23,
29, 108, 0, 33, 0, 0, 0, 0, 0, 52, 20, 22, 22, 22, 140, 2, 29, 108, 0, 33, 0, 0, 0, 0, 0, 52, 20, 22, 22, 22, 140, 2,
2, 2, 174, 175, 11, 15, 176, 61, 177, 0, 0, 1, 147, 0, 0, 0, 2, 2, 175, 141, 11, 15, 176, 61, 177, 0, 0, 1, 148, 0, 0, 0,
0, 52, 20, 22, 16, 19, 20, 2, 2, 2, 2, 158, 158, 158, 178, 178, 0, 52, 20, 22, 16, 19, 20, 2, 2, 2, 2, 159, 159, 159, 178, 178,
178, 178, 178, 178, 15, 179, 0, 30, 0, 22, 20, 20, 31, 22, 22, 11, 178, 178, 178, 178, 15, 179, 0, 30, 0, 22, 20, 20, 31, 22, 22, 11,
169, 0, 61, 61, 61, 61, 61, 61, 61, 66, 21, 82, 46, 0, 0, 0, 170, 0, 61, 61, 61, 61, 61, 61, 61, 66, 21, 82, 46, 0, 0, 0,
0, 2, 2, 2, 9, 2, 30, 2, 2, 52, 22, 22, 31, 0, 38, 22, 0, 2, 2, 2, 9, 2, 30, 2, 2, 52, 22, 22, 31, 0, 38, 22,
27, 11, 159, 180, 181, 0, 0, 0, 0, 2, 2, 2, 30, 9, 2, 2, 27, 11, 160, 180, 181, 0, 0, 0, 0, 2, 2, 2, 30, 9, 2, 2,
2, 2, 2, 2, 2, 2, 23, 23, 47, 22, 35, 82, 68, 0, 0, 0, 2, 2, 2, 2, 2, 2, 23, 23, 47, 22, 35, 82, 68, 0, 0, 0,
0, 2, 182, 66, 47, 0, 0, 0, 0, 11, 183, 2, 2, 2, 2, 2, 0, 2, 182, 66, 47, 0, 0, 0, 0, 11, 183, 2, 2, 2, 2, 2,
2, 2, 2, 23, 22, 20, 31, 0, 48, 16, 143, 0, 0, 0, 0, 0, 2, 2, 2, 23, 22, 20, 31, 0, 48, 16, 144, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 156, 0, 0, 184, 184, 184, 184, 184, 184, 184, 0, 2, 2, 2, 2, 2, 157, 0, 0, 184, 184, 184, 184, 184, 184, 184,
184, 185, 185, 185, 186, 187, 185, 184, 184, 188, 184, 184, 189, 190, 190, 190, 184, 185, 185, 185, 186, 187, 185, 184, 184, 188, 184, 184, 189, 190, 190, 190,
190, 190, 190, 190, 0, 0, 0, 0, 0, 184, 184, 184, 184, 184, 191, 0, 190, 190, 190, 190, 0, 0, 0, 0, 0, 184, 184, 184, 184, 184, 191, 0,
0, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 192, 193, 0, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 192, 193,
@ -306,11 +306,11 @@ hb_use_u8[3345] =
CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, SB, CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, SB,
SE, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B, SE, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,
CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv,
FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, FPst, VBlw, B, VBlw,VMAbv, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,
IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre,
IS,CMAbv, O, VPst, B, R, R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,VMPst, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,
O,VMAbv,CMBlw, IS, R,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, CMBlw,VMPst, O,VMAbv,CMBlw, IS, R,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst,
VPst, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv, VAbv,VMAbv, VPst, MPst, R, MPst,CMBlw, B,FMBlw, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv,
IS, VBlw, IS, R, MBlw, GB, VAbv, R,VMPst, G, G, J, J, J, SB, SE, IS, VBlw, IS, R, MBlw, GB, VAbv, R,VMPst, G, G, J, J, J, SB, SE,
J, HR, G, G, HM, HM, HM, G, O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O, J, HR, G, G, HM, HM, HM, G, O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O,
VBlw, VBlw,
@ -528,60 +528,60 @@ hb_use_u8[3657] =
2, 2, 131, 23, 22, 20, 48, 132, 133, 134, 0, 0, 0, 0, 0, 0, 2, 2, 131, 23, 22, 20, 48, 132, 133, 134, 0, 0, 0, 0, 0, 0,
0, 2, 2, 52, 30, 2, 2, 2, 2, 2, 2, 2, 2, 10, 22, 59, 0, 2, 2, 52, 30, 2, 2, 2, 2, 2, 2, 2, 2, 10, 22, 59,
99, 76, 135, 136, 137, 0, 0, 0, 0, 2, 138, 2, 2, 2, 2, 139, 99, 76, 135, 136, 137, 0, 0, 0, 0, 2, 138, 2, 2, 2, 2, 139,
0, 30, 2, 42, 5, 0, 79, 15, 2, 53, 22, 140, 52, 53, 2, 2, 0, 30, 2, 42, 5, 0, 79, 15, 2, 140, 20, 53, 128, 140, 2, 2,
105, 10, 9, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 141, 21, 141, 10, 9, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 142, 21,
25, 0, 0, 142, 143, 0, 0, 0, 0, 2, 65, 45, 23, 80, 47, 144, 25, 0, 0, 143, 144, 0, 0, 0, 0, 2, 65, 45, 23, 80, 47, 145,
0, 81, 81, 81, 81, 81, 81, 81, 81, 0, 0, 0, 0, 0, 0, 0, 0, 81, 81, 81, 81, 81, 81, 81, 81, 0, 0, 0, 0, 0, 0, 0,
6, 120, 120, 120, 120, 121, 0, 0, 0, 2, 2, 2, 2, 2, 9, 2, 6, 120, 120, 120, 120, 121, 0, 0, 0, 2, 2, 2, 2, 2, 9, 2,
2, 2, 9, 2, 30, 2, 2, 2, 2, 2, 30, 2, 2, 2, 30, 9, 2, 2, 9, 2, 30, 2, 2, 2, 2, 2, 30, 2, 2, 2, 30, 9,
0, 128, 20, 27, 31, 0, 0, 145, 146, 2, 2, 30, 2, 30, 2, 2, 0, 128, 20, 27, 31, 0, 0, 146, 147, 2, 2, 30, 2, 30, 2, 2,
2, 2, 2, 2, 0, 14, 37, 0, 147, 2, 2, 13, 37, 0, 30, 2, 2, 2, 2, 2, 0, 14, 37, 0, 148, 2, 2, 13, 37, 0, 30, 2,
2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 2, 2,
9, 2, 2, 11, 41, 0, 0, 0, 0, 2, 2, 2, 0, 27, 22, 22, 9, 2, 2, 11, 41, 0, 0, 0, 0, 2, 2, 2, 0, 27, 22, 22,
30, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 27, 38, 30, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 27, 38,
0, 2, 2, 2, 116, 116, 116, 116, 116, 148, 2, 9, 0, 0, 0, 0, 0, 2, 2, 2, 116, 116, 116, 116, 116, 149, 2, 9, 0, 0, 0, 0,
0, 2, 14, 14, 0, 0, 0, 0, 0, 9, 2, 2, 9, 2, 2, 2, 0, 2, 14, 14, 0, 0, 0, 0, 0, 9, 2, 2, 9, 2, 2, 2,
2, 30, 2, 9, 0, 30, 2, 0, 0, 149, 150, 151, 2, 2, 2, 2, 2, 30, 2, 9, 0, 30, 2, 0, 0, 150, 151, 152, 2, 2, 2, 2,
2, 2, 2, 2, 2, 22, 22, 20, 20, 20, 22, 22, 134, 0, 0, 0, 2, 2, 2, 2, 2, 22, 22, 20, 20, 20, 22, 22, 134, 0, 0, 0,
0, 0, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 2, 2, 2, 2, 0, 0, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 2, 2, 2, 2,
2, 53, 52, 53, 0, 0, 0, 0, 153, 11, 74, 2, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0, 154, 11, 74, 2, 2, 2, 2, 2,
2, 18, 19, 21, 16, 24, 37, 0, 0, 0, 31, 0, 0, 0, 0, 0, 2, 18, 19, 21, 16, 24, 37, 0, 0, 0, 31, 0, 0, 0, 0, 0,
0, 11, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 20, 22, 154, 0, 11, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 20, 22, 155,
22, 21, 155, 156, 2, 2, 2, 2, 2, 0, 0, 65, 157, 0, 0, 0, 22, 21, 156, 157, 2, 2, 2, 2, 2, 0, 0, 65, 158, 0, 0, 0,
0, 2, 13, 0, 0, 0, 0, 0, 0, 2, 65, 25, 20, 20, 20, 22, 0, 2, 13, 0, 0, 0, 0, 0, 0, 2, 65, 25, 20, 20, 20, 22,
22, 108, 158, 0, 0, 56, 159, 31, 160, 30, 2, 2, 2, 2, 2, 2, 22, 108, 159, 0, 0, 56, 160, 31, 161, 30, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 23, 19, 22, 22, 161, 44, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 23, 19, 22, 22, 162, 44, 0, 0, 0,
49, 128, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 9, 2, 2, 49, 128, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 9, 2, 2,
30, 2, 2, 2, 2, 2, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2,
10, 18, 19, 21, 22, 162, 31, 0, 0, 11, 11, 30, 2, 2, 2, 9, 10, 18, 19, 21, 22, 163, 31, 0, 0, 11, 11, 30, 2, 2, 2, 9,
30, 9, 2, 30, 2, 2, 58, 17, 23, 16, 23, 47, 32, 33, 32, 34, 30, 9, 2, 30, 2, 2, 58, 17, 23, 16, 23, 47, 32, 33, 32, 34,
0, 0, 0, 0, 35, 0, 0, 0, 2, 2, 23, 0, 11, 11, 11, 46, 0, 0, 0, 0, 35, 0, 0, 0, 2, 2, 23, 0, 11, 11, 11, 46,
0, 11, 11, 46, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 30, 0, 0, 11, 11, 46, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 30, 0,
9, 2, 2, 2, 30, 45, 59, 20, 20, 31, 33, 32, 32, 25, 163, 29, 9, 2, 2, 2, 30, 45, 59, 20, 20, 31, 33, 32, 32, 25, 164, 29,
164, 165, 37, 0, 0, 0, 0, 0, 0, 12, 26, 0, 0, 0, 0, 0, 165, 166, 37, 0, 0, 0, 0, 0, 0, 12, 26, 0, 0, 0, 0, 0,
0, 2, 2, 65, 25, 20, 20, 20, 22, 23, 126, 15, 17, 0, 0, 0, 0, 2, 2, 65, 25, 20, 20, 20, 22, 23, 126, 15, 17, 0, 0, 0,
0, 2, 2, 2, 2, 2, 0, 0, 166, 167, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 167, 168, 0, 0, 0, 0, 0, 0,
0, 18, 19, 20, 20, 66, 99, 25, 160, 11, 168, 9, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25, 161, 11, 169, 9, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 2, 2, 65, 25, 20, 20, 0, 48, 48, 11, 0, 2, 2, 2, 2, 2, 2, 2, 65, 25, 20, 20, 0, 48, 48, 11,
169, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 20, 170, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 20,
0, 23, 19, 20, 20, 21, 16, 82, 169, 38, 0, 0, 0, 0, 0, 0, 0, 23, 19, 20, 20, 21, 16, 82, 170, 38, 0, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 10, 170, 25, 20, 22, 22, 168, 9, 0, 0, 0, 2, 2, 2, 2, 2, 10, 171, 25, 20, 22, 22, 169, 9, 0, 0,
0, 2, 2, 2, 2, 2, 9, 43, 136, 23, 22, 20, 76, 21, 22, 0, 0, 2, 2, 2, 2, 2, 9, 43, 136, 23, 22, 20, 76, 21, 22, 0,
0, 2, 2, 2, 9, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 9, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 18,
19, 20, 21, 22, 105, 169, 37, 0, 0, 2, 2, 2, 9, 30, 0, 2, 19, 20, 21, 22, 105, 170, 37, 0, 0, 2, 2, 2, 9, 30, 0, 2,
2, 2, 2, 30, 9, 2, 2, 2, 2, 23, 23, 18, 32, 33, 12, 171, 2, 2, 2, 30, 9, 2, 2, 2, 2, 23, 23, 18, 32, 33, 12, 172,
165, 172, 173, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 166, 173, 174, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2,
2, 65, 25, 20, 20, 0, 22, 23, 29, 108, 0, 33, 0, 0, 0, 0, 2, 65, 25, 20, 20, 0, 22, 23, 29, 108, 0, 33, 0, 0, 0, 0,
0, 52, 20, 22, 22, 22, 140, 2, 2, 2, 174, 175, 11, 15, 176, 61, 0, 52, 20, 22, 22, 22, 140, 2, 2, 2, 175, 141, 11, 15, 176, 61,
177, 0, 0, 1, 147, 0, 0, 0, 0, 52, 20, 22, 16, 19, 20, 2, 177, 0, 0, 1, 148, 0, 0, 0, 0, 52, 20, 22, 16, 19, 20, 2,
2, 2, 2, 158, 158, 158, 178, 178, 178, 178, 178, 178, 15, 179, 0, 30, 2, 2, 2, 159, 159, 159, 178, 178, 178, 178, 178, 178, 15, 179, 0, 30,
0, 22, 20, 20, 31, 22, 22, 11, 169, 0, 61, 61, 61, 61, 61, 61, 0, 22, 20, 20, 31, 22, 22, 11, 170, 0, 61, 61, 61, 61, 61, 61,
61, 66, 21, 82, 46, 0, 0, 0, 0, 2, 2, 2, 9, 2, 30, 2, 61, 66, 21, 82, 46, 0, 0, 0, 0, 2, 2, 2, 9, 2, 30, 2,
2, 52, 22, 22, 31, 0, 38, 22, 27, 11, 159, 180, 181, 0, 0, 0, 2, 52, 22, 22, 31, 0, 38, 22, 27, 11, 160, 180, 181, 0, 0, 0,
0, 2, 2, 2, 30, 9, 2, 2, 2, 2, 2, 2, 2, 2, 23, 23, 0, 2, 2, 2, 30, 9, 2, 2, 2, 2, 2, 2, 2, 2, 23, 23,
47, 22, 35, 82, 68, 0, 0, 0, 0, 2, 182, 66, 47, 0, 0, 0, 47, 22, 35, 82, 68, 0, 0, 0, 0, 2, 182, 66, 47, 0, 0, 0,
0, 11, 183, 2, 2, 2, 2, 2, 2, 2, 2, 23, 22, 20, 31, 0, 0, 11, 183, 2, 2, 2, 2, 2, 2, 2, 2, 23, 22, 20, 31, 0,
48, 16, 143, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 156, 0, 48, 16, 144, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 157, 0,
0, 184, 184, 184, 184, 184, 184, 184, 184, 185, 185, 185, 186, 187, 185, 184, 0, 184, 184, 184, 184, 184, 184, 184, 184, 185, 185, 185, 186, 187, 185, 184,
184, 188, 184, 184, 189, 190, 190, 190, 190, 190, 190, 190, 0, 0, 0, 0, 184, 188, 184, 184, 189, 190, 190, 190, 190, 190, 190, 190, 0, 0, 0, 0,
0, 184, 184, 184, 184, 184, 191, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 184, 184, 184, 184, 184, 191, 0, 0, 2, 2, 2, 2, 2, 2, 2,
@ -612,12 +612,12 @@ hb_use_u8[3657] =
IS, RK, RK, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, IS, RK, RK, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ,
CGJ, WJ, WJ, WJ, O,FMPst, O, SB, SE, O, H, MPst, VPst, H,VMAbv, VAbv, CGJ, WJ, WJ, WJ, O,FMPst, O, SB, SE, O, H, MPst, VPst, H,VMAbv, VAbv,
VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw,
MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, VBlw,VMAbv, B, VPre, O,
O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst,
B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R,CMBlw, CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R,
VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,VMPst, O,VMAbv,CMBlw, IS, R,FMAbv, B, CS, R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,VMPst, O,VMAbv,CMBlw, IS, R,FMAbv,
CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, MPst, R, MPst,CMBlw, B,FMBlw, VBlw, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, MPst, R, MPst,CMBlw, B,
VMAbv, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, R, MBlw, GB, VAbv, R, FMBlw, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, R, MBlw, GB, VAbv, R,
VMPst, G, G, J, J, J, SB, SE, J, HR, G, G, HM, HM, HM, G, VMPst, G, G, J, J, J, SB, SE, J, HR, G, G, HM, HM, HM, G,
O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O, VBlw, O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O, VBlw,
}; };

View File

@ -117,7 +117,7 @@ hb_ot_var_get_axes (hb_face_t *face,
* in the specified face. * in the specified face.
* *
* Since: 1.4.2 * Since: 1.4.2
* Deprecated: 2.2.0 - use hb_ot_var_find_axis_info() instead * Deprecated: 2.2.0: use hb_ot_var_find_axis_info() instead
**/ **/
hb_bool_t hb_bool_t
hb_ot_var_find_axis (hb_face_t *face, hb_ot_var_find_axis (hb_face_t *face,

View File

@ -84,6 +84,12 @@ void hb_outline_t::replay (hb_draw_funcs_t *pen, void *pen_data) const
} }
} }
void hb_outline_t::slant (float slant_xy)
{
for (auto &p : points)
p.x += slant_xy * p.y;
}
float hb_outline_t::control_area () const float hb_outline_t::control_area () const
{ {
float a = 0; float a = 0;

View File

@ -69,6 +69,7 @@ struct hb_outline_t
HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const; HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const;
HB_INTERNAL float control_area () const; HB_INTERNAL float control_area () const;
HB_INTERNAL void slant (float slant_xy);
HB_INTERNAL void embolden (float x_strength, float y_strength, HB_INTERNAL void embolden (float x_strength, float y_strength,
float x_shift, float y_shift); float x_shift, float y_shift);

View File

@ -0,0 +1,207 @@
/*
* Copyright © 2022 Behdad Esfahbod
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include "hb.hh"
#ifndef HB_NO_PAINT
#include "hb-paint-bounded.hh"
#include "hb-machinery.hh"
/*
* This file implements boundedness computation of COLRv1 fonts as described in:
*
* https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness
*/
static void
hb_paint_bounded_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
hb_codepoint_t glyph,
hb_font_t *font,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->push_clip ();
}
static void
hb_paint_bounded_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
float xmin, float ymin, float xmax, float ymax,
void *user_data)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->push_clip ();
}
static void
hb_paint_bounded_pop_clip (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->pop_clip ();
}
static void
hb_paint_bounded_push_group (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->push_group ();
}
static void
hb_paint_bounded_pop_group (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
hb_paint_composite_mode_t mode,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->pop_group (mode);
}
static hb_bool_t
hb_paint_bounded_paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
hb_blob_t *blob HB_UNUSED,
unsigned int width HB_UNUSED,
unsigned int height HB_UNUSED,
hb_tag_t format HB_UNUSED,
float slant HB_UNUSED,
hb_glyph_extents_t *glyph_extents,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->push_clip ();
c->paint ();
c->pop_clip ();
return true;
}
static void
hb_paint_bounded_paint_color (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
hb_bool_t use_foreground HB_UNUSED,
hb_color_t color HB_UNUSED,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->paint ();
}
static void
hb_paint_bounded_paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
hb_color_line_t *color_line HB_UNUSED,
float x0 HB_UNUSED, float y0 HB_UNUSED,
float x1 HB_UNUSED, float y1 HB_UNUSED,
float x2 HB_UNUSED, float y2 HB_UNUSED,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->paint ();
}
static void
hb_paint_bounded_paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
hb_color_line_t *color_line HB_UNUSED,
float x0 HB_UNUSED, float y0 HB_UNUSED, float r0 HB_UNUSED,
float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->paint ();
}
static void
hb_paint_bounded_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data,
hb_color_line_t *color_line HB_UNUSED,
float cx HB_UNUSED, float cy HB_UNUSED,
float start_angle HB_UNUSED,
float end_angle HB_UNUSED,
void *user_data HB_UNUSED)
{
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
c->paint ();
}
static inline void free_static_paint_bounded_funcs ();
static struct hb_paint_bounded_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t<hb_paint_bounded_funcs_lazy_loader_t>
{
static hb_paint_funcs_t *create ()
{
hb_paint_funcs_t *funcs = hb_paint_funcs_create ();
hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_paint_bounded_push_clip_glyph, nullptr, nullptr);
hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_paint_bounded_push_clip_rectangle, nullptr, nullptr);
hb_paint_funcs_set_pop_clip_func (funcs, hb_paint_bounded_pop_clip, nullptr, nullptr);
hb_paint_funcs_set_push_group_func (funcs, hb_paint_bounded_push_group, nullptr, nullptr);
hb_paint_funcs_set_pop_group_func (funcs, hb_paint_bounded_pop_group, nullptr, nullptr);
hb_paint_funcs_set_color_func (funcs, hb_paint_bounded_paint_color, nullptr, nullptr);
hb_paint_funcs_set_image_func (funcs, hb_paint_bounded_paint_image, nullptr, nullptr);
hb_paint_funcs_set_linear_gradient_func (funcs, hb_paint_bounded_paint_linear_gradient, nullptr, nullptr);
hb_paint_funcs_set_radial_gradient_func (funcs, hb_paint_bounded_paint_radial_gradient, nullptr, nullptr);
hb_paint_funcs_set_sweep_gradient_func (funcs, hb_paint_bounded_paint_sweep_gradient, nullptr, nullptr);
hb_paint_funcs_make_immutable (funcs);
hb_atexit (free_static_paint_bounded_funcs);
return funcs;
}
} static_paint_bounded_funcs;
static inline
void free_static_paint_bounded_funcs ()
{
static_paint_bounded_funcs.free_instance ();
}
hb_paint_funcs_t *
hb_paint_bounded_get_funcs ()
{
return static_paint_bounded_funcs.get_unconst ();
}
#endif

View File

@ -0,0 +1,117 @@
/*
* Copyright © 2022 Behdad Esfahbod
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#ifndef HB_PAINT_BOUNDED_HH
#define HB_PAINT_BOUNDED_HH
#include "hb.hh"
#include "hb-paint.h"
#include "hb-geometry.hh"
typedef struct hb_paint_bounded_context_t hb_paint_bounded_context_t;
struct hb_paint_bounded_context_t
{
void clear ()
{
clips = 0;
bounded = true;
groups.clear ();
}
hb_paint_bounded_context_t ()
{
clear ();
}
bool is_bounded ()
{
return bounded;
}
void push_clip ()
{
clips++;
}
void pop_clip ()
{
if (clips == 0) return;
clips--;
}
void push_group ()
{
groups.push (bounded);
bounded = true;
}
void pop_group (hb_paint_composite_mode_t mode)
{
const bool src_bounded = bounded;
bounded = groups.pop ();
bool &backdrop_bounded = bounded;
// https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite
switch ((int) mode)
{
case HB_PAINT_COMPOSITE_MODE_CLEAR:
backdrop_bounded = true;
break;
case HB_PAINT_COMPOSITE_MODE_SRC:
case HB_PAINT_COMPOSITE_MODE_SRC_OUT:
backdrop_bounded = src_bounded;
break;
case HB_PAINT_COMPOSITE_MODE_DEST:
case HB_PAINT_COMPOSITE_MODE_DEST_OUT:
break;
case HB_PAINT_COMPOSITE_MODE_SRC_IN:
case HB_PAINT_COMPOSITE_MODE_DEST_IN:
backdrop_bounded = backdrop_bounded && src_bounded;
break;
default:
backdrop_bounded = backdrop_bounded || src_bounded;
break;
}
}
void paint ()
{
if (!clips)
bounded = false;
}
protected:
bool bounded; // true if current drawing bounded
unsigned clips; // number of active clips
hb_vector_t<bool> groups; // true if group bounded
};
HB_INTERNAL hb_paint_funcs_t *
hb_paint_bounded_get_funcs ();
#endif /* HB_PAINT_BOUNDED_HH */

View File

@ -28,14 +28,13 @@
#include "hb-paint-extents.hh" #include "hb-paint-extents.hh"
#include "hb-draw.h" #include "hb-draw.hh"
#include "hb-machinery.hh" #include "hb-machinery.hh"
/* /*
* This file implements bounds-extraction as well as boundedness * This file implements bounds-extraction computation of COLRv1 fonts as described in:
* computation of COLRv1 fonts as described in:
* *
* https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness
*/ */
@ -63,93 +62,6 @@ hb_paint_extents_pop_transform (hb_paint_funcs_t *funcs HB_UNUSED,
c->pop_transform (); c->pop_transform ();
} }
static void
hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (to_x, to_y);
}
static void
hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (to_x, to_y);
}
static void
hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (control_x, control_y);
extents->add_point (to_x, to_y);
}
static void
hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *data,
hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_extents_t *extents = (hb_extents_t *) data;
extents->add_point (control1_x, control1_y);
extents->add_point (control2_x, control2_y);
extents->add_point (to_x, to_y);
}
static inline void free_static_draw_extents_funcs ();
static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_draw_extents_funcs_lazy_loader_t>
{
static hb_draw_funcs_t *create ()
{
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
hb_draw_funcs_make_immutable (funcs);
hb_atexit (free_static_draw_extents_funcs);
return funcs;
}
} static_draw_extents_funcs;
static inline
void free_static_draw_extents_funcs ()
{
static_draw_extents_funcs.free_instance ();
}
static hb_draw_funcs_t *
hb_draw_extents_get_funcs ()
{
return static_draw_extents_funcs.get_unconst ();
}
static void static void
hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED, hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
void *paint_data, void *paint_data,
@ -221,6 +133,9 @@ hb_paint_extents_paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
{ {
hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
if (!glyph_extents)
return false; // Happens with SVG images.
hb_extents_t extents = {(float) glyph_extents->x_bearing, hb_extents_t extents = {(float) glyph_extents->x_bearing,
(float) glyph_extents->y_bearing + glyph_extents->height, (float) glyph_extents->y_bearing + glyph_extents->height,
(float) glyph_extents->x_bearing + glyph_extents->width, (float) glyph_extents->x_bearing + glyph_extents->width,

View File

@ -87,7 +87,7 @@ hb_paint_image_nil (hb_paint_funcs_t *funcs, void *paint_data,
unsigned int width, unsigned int width,
unsigned int height, unsigned int height,
hb_tag_t format, hb_tag_t format,
float slant_xy, float slant_xy_deprecated,
hb_glyph_extents_t *extents, hb_glyph_extents_t *extents,
void *user_data) { return false; } void *user_data) { return false; }
@ -615,7 +615,7 @@ hb_paint_color (hb_paint_funcs_t *funcs, void *paint_data,
* @width: width of the raster image in pixels, or 0 * @width: width of the raster image in pixels, or 0
* @height: height of the raster image in pixels, or 0 * @height: height of the raster image in pixels, or 0
* @format: the image format as a tag * @format: the image format as a tag
* @slant: the synthetic slant ratio to be applied to the image during rendering * @slant: Deprecated. set to 0.0
* @extents: (nullable): the extents of the glyph * @extents: (nullable): the extents of the glyph
* *
* Perform a "image" paint operation. * Perform a "image" paint operation.
@ -628,10 +628,10 @@ hb_paint_image (hb_paint_funcs_t *funcs, void *paint_data,
unsigned int width, unsigned int width,
unsigned int height, unsigned int height,
hb_tag_t format, hb_tag_t format,
float slant, HB_UNUSED float slant,
hb_glyph_extents_t *extents) hb_glyph_extents_t *extents)
{ {
funcs->image (paint_data, image, width, height, format, slant, extents); funcs->image (paint_data, image, width, height, format, 0.f, extents);
} }
/** /**

View File

@ -167,8 +167,10 @@ typedef hb_bool_t (*hb_paint_color_glyph_func_t) (hb_paint_funcs_t *funcs,
* A virtual method for the #hb_paint_funcs_t to clip * A virtual method for the #hb_paint_funcs_t to clip
* subsequent paint calls to the outline of a glyph. * subsequent paint calls to the outline of a glyph.
* *
* The coordinates of the glyph outline are interpreted according * The coordinates of the glyph outline are expected in the
* to the current transform. * current @font scale (ie. the results of calling
* hb_font_draw_glyph() with @font). The outline is
* transformed by the current transform.
* *
* This clip is applied in addition to the current clip, * This clip is applied in addition to the current clip,
* and remains in effect until a matching call to * and remains in effect until a matching call to
@ -281,7 +283,7 @@ typedef void (*hb_paint_color_func_t) (hb_paint_funcs_t *funcs,
* @width: width of the raster image in pixels, or 0 * @width: width of the raster image in pixels, or 0
* @height: height of the raster image in pixels, or 0 * @height: height of the raster image in pixels, or 0
* @format: the image format as a tag * @format: the image format as a tag
* @slant: the synthetic slant ratio to be applied to the image during rendering * @slant: Deprecated. Always set to 0.0.
* @extents: (nullable): glyph extents for desired rendering * @extents: (nullable): glyph extents for desired rendering
* @user_data: User data pointer passed to hb_paint_funcs_set_image_func() * @user_data: User data pointer passed to hb_paint_funcs_set_image_func()
* *

View File

@ -162,10 +162,11 @@ struct hb_paint_funcs_t
{ {
float upem = font->face->get_upem (); float upem = font->face->get_upem ();
int xscale = font->x_scale, yscale = font->y_scale; int xscale = font->x_scale, yscale = font->y_scale;
float slant = font->slant_xy;
push_transform (paint_data, push_transform (paint_data,
xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0); xscale/upem, 0,
0, yscale/upem,
0, 0);
} }
void push_inverse_font_transform (void *paint_data, void push_inverse_font_transform (void *paint_data,
@ -174,10 +175,11 @@ struct hb_paint_funcs_t
float upem = font->face->get_upem (); float upem = font->face->get_upem ();
int xscale = font->x_scale ? font->x_scale : upem; int xscale = font->x_scale ? font->x_scale : upem;
int yscale = font->y_scale ? font->y_scale : upem; int yscale = font->y_scale ? font->y_scale : upem;
float slant = font->slant_xy;
push_transform (paint_data, push_transform (paint_data,
upem/xscale, 0, -slant * upem/xscale, upem/yscale, 0, 0); upem/xscale, 0,
0, upem/yscale,
0, 0);
} }
HB_NODISCARD HB_NODISCARD

View File

@ -57,6 +57,10 @@ HB_SHAPER_IMPLEMENT (directwrite)
HB_SHAPER_IMPLEMENT (coretext) HB_SHAPER_IMPLEMENT (coretext)
#endif #endif
#ifdef HAVE_HARFRUZZ
HB_SHAPER_IMPLEMENT (harfruzz)
#endif
#ifndef HB_NO_FALLBACK_SHAPE #ifndef HB_NO_FALLBACK_SHAPE
HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
#endif #endif

View File

@ -47,20 +47,20 @@ HB_BEGIN_DECLS
* *
* The minor component of the library version available at compile-time. * The minor component of the library version available at compile-time.
*/ */
#define HB_VERSION_MINOR 1 #define HB_VERSION_MINOR 2
/** /**
* HB_VERSION_MICRO: * HB_VERSION_MICRO:
* *
* The micro component of the library version available at compile-time. * The micro component of the library version available at compile-time.
*/ */
#define HB_VERSION_MICRO 0 #define HB_VERSION_MICRO 1
/** /**
* HB_VERSION_STRING: * HB_VERSION_STRING:
* *
* A string literal containing the library version available at compile-time. * A string literal containing the library version available at compile-time.
*/ */
#define HB_VERSION_STRING "11.1.0" #define HB_VERSION_STRING "11.2.1"
/** /**
* HB_VERSION_ATLEAST: * HB_VERSION_ATLEAST: