[ft] Use mutex to lock access to FT_Face
Makes our FT-backed hb_font_t safe to use from multiple threads. Still, the underlying FT_Face should NOT be used from other threads by client or other libraries. Maybe I add a lock()/unlock() public API ala PangoFT2 and cairo-ft. Maybe not.
This commit is contained in:
parent
d18c3c5861
commit
be2f148da4
18
src/hb-ft.cc
18
src/hb-ft.cc
|
@ -60,6 +60,7 @@
|
|||
|
||||
struct hb_ft_font_t
|
||||
{
|
||||
mutable hb_mutex_t lock;
|
||||
FT_Face ft_face;
|
||||
int load_flags;
|
||||
bool symbol; /* Whether selected cmap is symbol cmap. */
|
||||
|
@ -77,6 +78,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
|
|||
if (unlikely (!ft_font))
|
||||
return nullptr;
|
||||
|
||||
ft_font->lock.init ();
|
||||
ft_font->ft_face = ft_face;
|
||||
ft_font->symbol = symbol;
|
||||
ft_font->unref = unref;
|
||||
|
@ -105,6 +107,8 @@ _hb_ft_font_destroy (void *data)
|
|||
if (ft_font->unref)
|
||||
_hb_ft_face_destroy (ft_font->ft_face);
|
||||
|
||||
ft_font->lock.fini ();
|
||||
|
||||
free (ft_font);
|
||||
}
|
||||
|
||||
|
@ -172,6 +176,7 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
|
||||
|
||||
if (unlikely (!g))
|
||||
|
@ -206,6 +211,7 @@ hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
unsigned int done;
|
||||
for (done = 0;
|
||||
done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
|
||||
|
@ -229,6 +235,7 @@ hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
|
||||
|
||||
if (unlikely (!g))
|
||||
|
@ -248,6 +255,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
int load_flags = ft_font->load_flags;
|
||||
int mult = font->x_scale < 0 ? -1 : +1;
|
||||
|
@ -285,6 +293,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Fixed v;
|
||||
|
||||
if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
|
||||
|
@ -307,6 +316,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
|
||||
|
@ -333,6 +343,7 @@ hb_ft_get_glyph_extents (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
|
||||
|
@ -365,6 +376,7 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
|
||||
|
@ -390,8 +402,10 @@ hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size);
|
||||
hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
|
||||
if (ret && (size && !*name))
|
||||
ret = false;
|
||||
|
||||
|
@ -406,6 +420,7 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
if (len < 0)
|
||||
|
@ -438,6 +453,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
metrics->ascender = ft_face->size->metrics.ascender;
|
||||
metrics->descender = ft_face->size->metrics.descender;
|
||||
|
|
|
@ -137,5 +137,13 @@ struct hb_mutex_t
|
|||
inline void fini (void) { hb_mutex_impl_finish (&m); }
|
||||
};
|
||||
|
||||
struct hb_lock_t
|
||||
{
|
||||
hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
|
||||
~hb_lock_t (void) { mutex.unlock (); }
|
||||
private:
|
||||
hb_mutex_t &mutex;
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_MUTEX_HH */
|
||||
|
|
|
@ -164,11 +164,8 @@ main (int argc, char **argv)
|
|||
|
||||
test_body ();
|
||||
|
||||
/* hb-font backed by FreeType functions can only be used from
|
||||
* one thread at a time, because that's FT_Face's MT guarantee.
|
||||
* So, disable this, even though it works "most of the time". */
|
||||
//hb_ft_font_set_funcs (font);
|
||||
//test_body ();
|
||||
hb_ft_font_set_funcs (font);
|
||||
test_body ();
|
||||
|
||||
hb_buffer_destroy (ref_buffer);
|
||||
|
||||
|
|
Loading…
Reference in New Issue