tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxHarfBuzzShaper.h (9184B)


      1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef GFX_HARFBUZZSHAPER_H
      7 #define GFX_HARFBUZZSHAPER_H
      8 
      9 #include "gfxFont.h"
     10 
     11 #include "harfbuzz/hb.h"
     12 #include "nsUnicodeProperties.h"
     13 #include "mozilla/gfx/2D.h"
     14 #include "mozilla/MruCache.h"
     15 #include "mozilla/Mutex.h"
     16 
     17 class gfxHarfBuzzShaper : public gfxFontShaper {
     18 public:
     19  explicit gfxHarfBuzzShaper(gfxFont* aFont);
     20  virtual ~gfxHarfBuzzShaper();
     21 
     22  /*
     23   * For HarfBuzz font callback functions, font_data is a ptr to a
     24   * FontCallbackData struct
     25   */
     26  struct FontCallbackData {
     27    gfxHarfBuzzShaper* mShaper;
     28  };
     29 
     30  // Initializes the shaper and returns whether this was successful.
     31  bool Initialize();
     32 
     33  // Returns whether the shaper has been successfully initialized.
     34  bool IsInitialized() const { return mHBFont != nullptr; }
     35 
     36  bool ShapeText(DrawTarget* aDrawTarget, const char16_t* aText,
     37                 uint32_t aOffset, uint32_t aLength, Script aScript,
     38                 nsAtom* aLanguage, bool aVertical, RoundingFlags aRounding,
     39                 gfxShapedText* aShapedText) override;
     40 
     41  // get a given font table in harfbuzz blob form
     42  hb_blob_t* GetFontTable(hb_tag_t aTag) const;
     43 
     44  // map unicode character to glyph ID
     45  hb_codepoint_t GetNominalGlyph(hb_codepoint_t unicode) const;
     46  unsigned int GetNominalGlyphs(unsigned int count,
     47                                const hb_codepoint_t* first_unicode,
     48                                unsigned int unicode_stride,
     49                                hb_codepoint_t* first_glyph,
     50                                unsigned int glyph_stride);
     51  hb_codepoint_t GetVariationGlyph(hb_codepoint_t unicode,
     52                                   hb_codepoint_t variation_selector) const;
     53 
     54  // get harfbuzz glyph advance, in font design units
     55  hb_position_t GetGlyphHAdvance(hb_codepoint_t glyph) const;
     56  void GetGlyphHAdvances(unsigned int count, const hb_codepoint_t* first_glyph,
     57                         unsigned int glyph_stride,
     58                         hb_position_t* first_advance,
     59                         unsigned int advance_stride) const;
     60 
     61  // Get vertical glyph advance, or -1 if not available; caller should check
     62  // for a negative result and provide a fallback or fail, as appropriate.
     63  hb_position_t GetGlyphVAdvance(hb_codepoint_t glyph);
     64 
     65  void GetGlyphVOrigin(hb_codepoint_t aGlyph, hb_position_t* aX,
     66                       hb_position_t* aY) const;
     67 
     68  hb_position_t GetHKerning(uint16_t aFirstGlyph, uint16_t aSecondGlyph) const;
     69 
     70  hb_bool_t GetGlyphExtents(hb_codepoint_t aGlyph,
     71                            hb_glyph_extents_t* aExtents) const;
     72 
     73  bool UseVerticalPresentationForms() const {
     74    return mUseVerticalPresentationForms;
     75  }
     76 
     77  static hb_script_t GetHBScriptUsedForShaping(Script aScript) {
     78    // Decide what harfbuzz script code will be used for shaping
     79    hb_script_t hbScript;
     80    if (aScript <= Script::INHERITED) {
     81      // For unresolved "common" or "inherited" runs,
     82      // default to Latin for now.
     83      hbScript = HB_SCRIPT_LATIN;
     84    } else {
     85      hbScript = hb_script_t(mozilla::unicode::GetScriptTagForCode(aScript));
     86    }
     87    return hbScript;
     88  }
     89 
     90  static hb_codepoint_t GetVerticalPresentationForm(hb_codepoint_t aUnicode);
     91 
     92  // Create an hb_font corresponding to the given gfxFont instance, with size
     93  // and variations set appropriately. If aFontFuncs and aCallbackData are
     94  // provided, they may be used as harfbuzz font callbacks for advances, glyph
     95  // bounds, etc; if not, the built-in hb_ot font functions will be used.
     96  static hb_font_t* CreateHBFont(gfxFont* aFont,
     97                                 hb_font_funcs_t* aFontFuncs = nullptr,
     98                                 FontCallbackData* aCallbackData = nullptr);
     99 
    100  hb_font_t* GetHBFont() const { return mHBFont; }
    101  hb_face_t* GetHBFace() const { return hb_font_get_face(mHBFont); }
    102 
    103 protected:
    104  // This is called with the cache locked, but if mUseFontGetGlyph is true, it
    105  // may unlock it temporarily. So in this case, it may invalidate an earlier
    106  // cache entry reference.
    107  hb_codepoint_t GetGlyphUncached(hb_codepoint_t unicode) const
    108      MOZ_REQUIRES(mCacheLock);
    109 
    110  hb_position_t GetGlyphHAdvanceUncached(hb_codepoint_t gid) const;
    111 
    112  nsresult SetGlyphsFromRun(gfxShapedText* aShapedText, uint32_t aOffset,
    113                            uint32_t aLength, const char16_t* aText,
    114                            bool aVertical, RoundingFlags aRounding);
    115 
    116  // retrieve glyph positions, applying advance adjustments and attachments
    117  // returns results in appUnits
    118  nscoord GetGlyphPositions(gfxContext* aContext, nsTArray<nsPoint>& aPositions,
    119                            uint32_t aAppUnitsPerDevUnit);
    120 
    121  void InitializeVertical();
    122  bool LoadHmtxTable();
    123 
    124  struct Glyf {  // we only need the bounding-box at the beginning
    125                 // of the glyph record, not the actual outline data
    126    mozilla::AutoSwap_PRInt16 numberOfContours;
    127    mozilla::AutoSwap_PRInt16 xMin;
    128    mozilla::AutoSwap_PRInt16 yMin;
    129    mozilla::AutoSwap_PRInt16 xMax;
    130    mozilla::AutoSwap_PRInt16 yMax;
    131  };
    132 
    133  const Glyf* FindGlyf(hb_codepoint_t aGlyph, bool* aEmptyGlyf) const;
    134 
    135  // size-specific font object, owned by the gfxHarfBuzzShaper
    136  hb_font_t* mHBFont;
    137 
    138  // harfbuzz buffer for the shaping process
    139  hb_buffer_t* mBuffer;
    140 
    141  mutable mozilla::Mutex mCacheLock = mozilla::Mutex("shaperCacheMutex");
    142 
    143  struct CmapCacheData {
    144    uint32_t mCodepoint;
    145    uint32_t mGlyphId;
    146  };
    147 
    148  struct CmapCache
    149      : public mozilla::MruCache<uint32_t, CmapCacheData, CmapCache, 251> {
    150    static mozilla::HashNumber Hash(const uint32_t& aKey) { return aKey; }
    151    static bool Match(const uint32_t& aKey, const CmapCacheData& aData) {
    152      return aKey == aData.mCodepoint;
    153    }
    154  };
    155 
    156  mutable mozilla::UniquePtr<CmapCache> mCmapCache MOZ_GUARDED_BY(mCacheLock);
    157 
    158  struct WidthCacheData {
    159    hb_codepoint_t mGlyphId;
    160    hb_position_t mAdvance;
    161  };
    162 
    163  struct WidthCache
    164      : public mozilla::MruCache<uint32_t, WidthCacheData, WidthCache, 251> {
    165    static mozilla::HashNumber Hash(const hb_codepoint_t& aKey) { return aKey; }
    166    static bool Match(const uint32_t& aKey, const WidthCacheData& aData) {
    167      return aKey == aData.mGlyphId;
    168    }
    169  };
    170 
    171  mutable mozilla::UniquePtr<WidthCache> mWidthCache MOZ_GUARDED_BY(mCacheLock);
    172 
    173  FontCallbackData mCallbackData;
    174 
    175  // Following table references etc are declared "mutable" because the
    176  // harfbuzz callback functions take a const ptr to the shaper, but
    177  // wish to cache tables here to avoid repeatedly looking them up
    178  // in the font.
    179 
    180  // Old-style TrueType kern table, if we're not doing GPOS kerning
    181  mutable hb_blob_t* mKernTable;
    182 
    183  // Cached copy of the hmtx table.
    184  mutable hb_blob_t* mHmtxTable;
    185 
    186  // For vertical fonts, cached vmtx and VORG table, if present.
    187  mutable hb_blob_t* mVmtxTable;
    188  mutable hb_blob_t* mVORGTable;
    189  // And for vertical TrueType (not CFF) fonts that have vmtx,
    190  // we also use loca and glyf to get glyph bounding boxes.
    191  mutable hb_blob_t* mLocaTable;
    192  mutable hb_blob_t* mGlyfTable;
    193 
    194  // Cached pointer to cmap subtable to be used for char-to-glyph mapping.
    195  // This comes from GetFontTablePtr; if it is non-null, our destructor
    196  // must call ReleaseFontTablePtr to avoid permanently caching the table.
    197  mutable hb_blob_t* mCmapTable;
    198  mutable int32_t mCmapFormat;
    199  mutable uint32_t mSubtableOffset;
    200  mutable uint32_t mUVSTableOffset;
    201 
    202  // Cached copy of numLongMetrics field from the hhea table,
    203  // for use when looking up glyph metrics; initialized to 0 by the
    204  // constructor so we can tell it hasn't been set yet.
    205  // This is a signed value so that we can use -1 to indicate
    206  // an error (if the hhea table was not available).
    207  mutable int32_t mNumLongHMetrics;
    208  // Similarly for vhea if it's a vertical font.
    209  mutable int32_t mNumLongVMetrics;
    210 
    211  // Default y-coordinate for glyph vertical origin, used if the font
    212  // does not actually have vertical-layout metrics.
    213  mutable gfxFloat mDefaultVOrg;
    214 
    215  // Number of glyphs in the font (set from 'maxp' during initialization).
    216  uint32_t mNumGlyphs = 0;
    217 
    218  // Whether the font implements GetGlyph, or we should read tables
    219  // directly
    220  bool mUseFontGetGlyph;
    221 
    222  // Whether the font is an MS Symbol-encoded font, in which case we will
    223  // try remapping U+0020..00FF to U+F020..F0FF for characters in the U+00xx
    224  // range that are otherwise unsupported.
    225  bool mIsSymbolFont;
    226 
    227  // Whether the font implements GetGlyphWidth, or we should read tables
    228  // directly to get ideal widths
    229  bool mUseFontGlyphWidths;
    230 
    231  bool mInitialized;
    232  bool mVerticalInitialized;
    233 
    234  // Whether to use vertical presentation forms for CJK characters
    235  // when available (only set if the 'vert' feature is not available).
    236  bool mUseVerticalPresentationForms;
    237 
    238  // these are set from the FindGlyf callback on first use of the glyf data
    239  mutable bool mLoadedLocaGlyf;
    240  mutable bool mLocaLongOffsets;
    241 };
    242 
    243 #endif /* GFX_HARFBUZZSHAPER_H */