Commit 0d4cddb9 authored by Jonathan Kew's avatar Jonathan Kew Committed by Pier Angelo Vendrame
Browse files

Bug 2009213 - Use local statics for harfbuzz callback pointers, to ensure...

Bug 2009213 - Use local statics for harfbuzz callback pointers, to ensure thread-safe initialization. r=gfx-reviewers,lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D278945
parent c2a8e013
Loading
Loading
Loading
Loading
+57 −54
Original line number Diff line number Diff line
@@ -1181,9 +1181,6 @@ static void AddOpenTypeFeature(uint32_t aTag, uint32_t aValue, void* aUserArg) {
 * gfxFontShaper override to initialize the text run using HarfBuzz
 */

static hb_font_funcs_t* sHBFontFuncs = nullptr;
static hb_font_funcs_t* sNominalGlyphFunc = nullptr;
static hb_unicode_funcs_t* sHBUnicodeFuncs = nullptr;
MOZ_RUNINIT static const hb_script_t sMathScript =
    hb_ot_tag_to_script(HB_TAG('m', 'a', 't', 'h'));

@@ -1192,52 +1189,58 @@ bool gfxHarfBuzzShaper::Initialize() {
  // other thread can yet be using it.
  MOZ_PUSH_IGNORE_THREAD_SAFETY

  if (!sHBFontFuncs) {
    // static function callback pointers, initialized by the first
    // harfbuzz shaper used
    sHBFontFuncs = hb_font_funcs_create();
    hb_font_funcs_set_nominal_glyph_func(sHBFontFuncs, HBGetNominalGlyph,
                                         nullptr, nullptr);
    hb_font_funcs_set_nominal_glyphs_func(sHBFontFuncs, HBGetNominalGlyphs,
                                          nullptr, nullptr);
    hb_font_funcs_set_variation_glyph_func(sHBFontFuncs, HBGetVariationGlyph,
                                           nullptr, nullptr);
    hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs, HBGetGlyphHAdvance,
                                           nullptr, nullptr);
    hb_font_funcs_set_glyph_h_advances_func(sHBFontFuncs, HBGetGlyphHAdvances,
                                            nullptr, nullptr);
    hb_font_funcs_set_glyph_v_advance_func(sHBFontFuncs, HBGetGlyphVAdvance,
                                           nullptr, nullptr);
    hb_font_funcs_set_glyph_v_origin_func(sHBFontFuncs, HBGetGlyphVOrigin,
                                          nullptr, nullptr);
    hb_font_funcs_set_glyph_extents_func(sHBFontFuncs, HBGetGlyphExtents,
                                         nullptr, nullptr);
    hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs, HBGetContourPoint,
  // Function callback pointers; these are local statics to ensure thread-safe
  // initialization on first use.
  static hb_font_funcs_t* sHBFontFuncs = [] {
    auto* funcs = hb_font_funcs_create();
    hb_font_funcs_set_nominal_glyph_func(funcs, HBGetNominalGlyph, nullptr,
                                         nullptr);
    hb_font_funcs_set_nominal_glyphs_func(funcs, HBGetNominalGlyphs, nullptr,
                                          nullptr);
    hb_font_funcs_set_variation_glyph_func(funcs, HBGetVariationGlyph, nullptr,
                                           nullptr);
    hb_font_funcs_set_glyph_h_advance_func(funcs, HBGetGlyphHAdvance, nullptr,
                                           nullptr);
    hb_font_funcs_set_glyph_h_advances_func(funcs, HBGetGlyphHAdvances, nullptr,
                                            nullptr);
    hb_font_funcs_set_glyph_v_advance_func(funcs, HBGetGlyphVAdvance, nullptr,
                                           nullptr);
    hb_font_funcs_set_glyph_v_origin_func(funcs, HBGetGlyphVOrigin, nullptr,
                                          nullptr);
    hb_font_funcs_set_glyph_extents_func(funcs, HBGetGlyphExtents, nullptr,
                                         nullptr);
    hb_font_funcs_set_glyph_contour_point_func(funcs, HBGetContourPoint,
                                               nullptr, nullptr);
    hb_font_funcs_set_glyph_h_kerning_func(sHBFontFuncs, HBGetHKerning, nullptr,
    hb_font_funcs_set_glyph_h_kerning_func(funcs, HBGetHKerning, nullptr,
                                           nullptr);
    hb_font_funcs_make_immutable(sHBFontFuncs);
    hb_font_funcs_make_immutable(funcs);
    return funcs;
  }();

    sNominalGlyphFunc = hb_font_funcs_create();
    hb_font_funcs_set_nominal_glyph_func(sNominalGlyphFunc, HBGetNominalGlyph,
                                         nullptr, nullptr);
    hb_font_funcs_make_immutable(sNominalGlyphFunc);
  static hb_font_funcs_t* sNominalGlyphFunc = [] {
    auto* funcs = hb_font_funcs_create();
    hb_font_funcs_set_nominal_glyph_func(funcs, HBGetNominalGlyph, nullptr,
                                         nullptr);
    hb_font_funcs_make_immutable(funcs);
    return funcs;
  }();

    sHBUnicodeFuncs = hb_unicode_funcs_create(hb_unicode_funcs_get_empty());
    hb_unicode_funcs_set_mirroring_func(sHBUnicodeFuncs, HBGetMirroring,
                                        nullptr, nullptr);
    hb_unicode_funcs_set_script_func(sHBUnicodeFuncs, HBGetScript, nullptr,
  static hb_unicode_funcs_t* sHBUnicodeFuncs = [] {
    auto* funcs = hb_unicode_funcs_create(hb_unicode_funcs_get_empty());
    hb_unicode_funcs_set_mirroring_func(funcs, HBGetMirroring, nullptr,
                                        nullptr);
    hb_unicode_funcs_set_general_category_func(
        sHBUnicodeFuncs, HBGetGeneralCategory, nullptr, nullptr);
    hb_unicode_funcs_set_combining_class_func(
        sHBUnicodeFuncs, HBGetCombiningClass, nullptr, nullptr);
    hb_unicode_funcs_set_compose_func(sHBUnicodeFuncs, HBUnicodeCompose,
    hb_unicode_funcs_set_script_func(funcs, HBGetScript, nullptr, nullptr);
    hb_unicode_funcs_set_general_category_func(funcs, HBGetGeneralCategory,
                                               nullptr, nullptr);
    hb_unicode_funcs_set_decompose_func(sHBUnicodeFuncs, HBUnicodeDecompose,
    hb_unicode_funcs_set_combining_class_func(funcs, HBGetCombiningClass,
                                              nullptr, nullptr);
    hb_unicode_funcs_make_immutable(sHBUnicodeFuncs);
  }
    hb_unicode_funcs_set_compose_func(funcs, HBUnicodeCompose, nullptr,
                                      nullptr);
    hb_unicode_funcs_set_decompose_func(funcs, HBUnicodeDecompose, nullptr,
                                        nullptr);
    hb_unicode_funcs_make_immutable(funcs);
    return funcs;
  }();

  gfxFontEntry* entry = mFont->GetFontEntry();
  if (!mUseFontGetGlyph) {
@@ -1280,11 +1283,10 @@ bool gfxHarfBuzzShaper::Initialize() {
  hb_buffer_set_cluster_level(mBuffer,
                              HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);

  auto* funcs =
      mFont->GetFontEntry()->HasFontTable(TRUETYPE_TAG('C', 'F', 'F', ' '))
          ? sNominalGlyphFunc
          : sHBFontFuncs;
  mHBFont = CreateHBFont(mFont, funcs, this);
  bool isCFF =
      mFont->GetFontEntry()->HasFontTable(TRUETYPE_TAG('C', 'F', 'F', ' '));
  auto* funcs = isCFF ? sNominalGlyphFunc : sHBFontFuncs;
  mHBFont = CreateHBFont(mFont, funcs, this, isCFF);

  MOZ_POP_THREAD_SAFETY

@@ -1293,12 +1295,13 @@ bool gfxHarfBuzzShaper::Initialize() {

hb_font_t* gfxHarfBuzzShaper::CreateHBFont(gfxFont* aFont,
                                           hb_font_funcs_t* aFontFuncs,
                                           void* aCallbackData) {
                                           void* aCallbackData,
                                           bool aCreateSubfont) {
  auto face(aFont->GetFontEntry()->GetHBFace());
  hb_font_t* result = hb_font_create(face);

  if (aFontFuncs && aCallbackData) {
    if (aFontFuncs == sNominalGlyphFunc) {
    if (aCreateSubfont) {
      hb_font_t* subfont = hb_font_create_sub_font(result);
      hb_font_destroy(result);
      result = subfont;
+2 −1
Original line number Diff line number Diff line
@@ -103,7 +103,8 @@ class gfxHarfBuzzShaper : public gfxFontShaper {
  // bounds, etc; if not, the built-in hb_ot font functions will be used.
  static hb_font_t* CreateHBFont(gfxFont* aFont,
                                 hb_font_funcs_t* aFontFuncs = nullptr,
                                 void* aCallbackData = nullptr);
                                 void* aCallbackData = nullptr,
                                 bool aCreateSubfont = false);

 protected:
  // Initializes the shaper and returns whether this was successful.