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/. */
6 #ifndef GFX_HARFBUZZSHAPER_H
7 #define GFX_HARFBUZZSHAPER_H
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"
17 class gfxHarfBuzzShaper
: public gfxFontShaper
{
19 explicit gfxHarfBuzzShaper(gfxFont
* aFont
);
20 virtual ~gfxHarfBuzzShaper();
23 * For HarfBuzz font callback functions, font_data is a ptr to a
24 * FontCallbackData struct
26 struct FontCallbackData
{
27 gfxHarfBuzzShaper
* mShaper
;
30 // Initializes the shaper and returns whether this was successful.
33 // Returns whether the shaper has been successfully initialized.
34 bool IsInitialized() const { return mHBFont
!= nullptr; }
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
;
41 // get a given font table in harfbuzz blob form
42 hb_blob_t
* GetFontTable(hb_tag_t aTag
) const;
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;
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;
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
);
65 void GetGlyphVOrigin(hb_codepoint_t aGlyph
, hb_position_t
* aX
,
66 hb_position_t
* aY
) const;
68 hb_position_t
GetHKerning(uint16_t aFirstGlyph
, uint16_t aSecondGlyph
) const;
70 hb_bool_t
GetGlyphExtents(hb_codepoint_t aGlyph
,
71 hb_glyph_extents_t
* aExtents
) const;
73 bool UseVerticalPresentationForms() const {
74 return mUseVerticalPresentationForms
;
77 static hb_script_t
GetHBScriptUsedForShaping(Script aScript
) {
78 // Decide what harfbuzz script code will be used for shaping
80 if (aScript
<= Script::INHERITED
) {
81 // For unresolved "common" or "inherited" runs,
82 // default to Latin for now.
83 hbScript
= HB_SCRIPT_LATIN
;
85 hbScript
= hb_script_t(mozilla::unicode::GetScriptTagForCode(aScript
));
90 static hb_codepoint_t
GetVerticalPresentationForm(hb_codepoint_t aUnicode
);
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);
100 hb_font_t
* GetHBFont() const { return mHBFont
; }
101 hb_face_t
* GetHBFace() const { return hb_font_get_face(mHBFont
); }
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
);
110 hb_position_t
GetGlyphHAdvanceUncached(hb_codepoint_t gid
) const;
112 nsresult
SetGlyphsFromRun(gfxShapedText
* aShapedText
, uint32_t aOffset
,
113 uint32_t aLength
, const char16_t
* aText
,
114 bool aVertical
, RoundingFlags aRounding
);
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
);
121 void InitializeVertical();
122 bool LoadHmtxTable();
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
;
133 const Glyf
* FindGlyf(hb_codepoint_t aGlyph
, bool* aEmptyGlyf
) const;
135 // size-specific font object, owned by the gfxHarfBuzzShaper
138 // harfbuzz buffer for the shaping process
139 hb_buffer_t
* mBuffer
;
141 mutable mozilla::Mutex mCacheLock
= mozilla::Mutex("shaperCacheMutex");
143 struct CmapCacheData
{
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
;
156 mutable mozilla::UniquePtr
<CmapCache
> mCmapCache
MOZ_GUARDED_BY(mCacheLock
);
158 struct WidthCacheData
{
159 hb_codepoint_t mGlyphId
;
160 hb_position_t mAdvance
;
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
;
171 mutable mozilla::UniquePtr
<WidthCache
> mWidthCache
MOZ_GUARDED_BY(mCacheLock
);
173 FontCallbackData mCallbackData
;
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
180 // Old-style TrueType kern table, if we're not doing GPOS kerning
181 mutable hb_blob_t
* mKernTable
;
183 // Cached copy of the hmtx table.
184 mutable hb_blob_t
* mHmtxTable
;
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
;
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
;
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
;
211 // Default y-coordinate for glyph vertical origin, used if the font
212 // does not actually have vertical-layout metrics.
213 mutable gfxFloat mDefaultVOrg
;
215 // Whether the font implements GetGlyph, or we should read tables
217 bool mUseFontGetGlyph
;
219 // Whether the font is an MS Symbol-encoded font, in which case we will
220 // try remapping U+0020..00FF to U+F020..F0FF for characters in the U+00xx
221 // range that are otherwise unsupported.
224 // Whether the font implements GetGlyphWidth, or we should read tables
225 // directly to get ideal widths
226 bool mUseFontGlyphWidths
;
229 bool mVerticalInitialized
;
231 // Whether to use vertical presentation forms for CJK characters
232 // when available (only set if the 'vert' feature is not available).
233 bool mUseVerticalPresentationForms
;
235 // these are set from the FindGlyf callback on first use of the glyf data
236 mutable bool mLoadedLocaGlyf
;
237 mutable bool mLocaLongOffsets
;
240 #endif /* GFX_HARFBUZZSHAPER_H */