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 */