/work/obj-fuzz/dist/include/gfxFontEntry.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
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_FONTENTRY_H |
7 | | #define GFX_FONTENTRY_H |
8 | | |
9 | | #include "gfxTypes.h" |
10 | | #include "nsString.h" |
11 | | #include "gfxFontConstants.h" |
12 | | #include "gfxFontFeatures.h" |
13 | | #include "gfxFontUtils.h" |
14 | | #include "gfxFontVariations.h" |
15 | | #include "nsTArray.h" |
16 | | #include "nsTHashtable.h" |
17 | | #include "mozilla/HashFunctions.h" |
18 | | #include "mozilla/MemoryReporting.h" |
19 | | #include "MainThreadUtils.h" |
20 | | #include "nsUnicodeScriptCodes.h" |
21 | | #include "nsDataHashtable.h" |
22 | | #include "harfbuzz/hb.h" |
23 | | #include "mozilla/FontPropertyTypes.h" |
24 | | #include "mozilla/gfx/2D.h" |
25 | | #include "mozilla/UniquePtr.h" |
26 | | #include "mozilla/WeakPtr.h" |
27 | | #include <math.h> |
28 | | |
29 | | typedef struct gr_face gr_face; |
30 | | typedef struct FT_MM_Var_ FT_MM_Var; |
31 | | |
32 | | #ifdef DEBUG |
33 | | #include <stdio.h> |
34 | | #endif |
35 | | |
36 | | struct gfxFontStyle; |
37 | | class gfxContext; |
38 | | class gfxFont; |
39 | | class gfxFontFamily; |
40 | | class gfxUserFontData; |
41 | | class gfxSVGGlyphs; |
42 | | class FontInfoData; |
43 | | struct FontListSizes; |
44 | | class nsAtom; |
45 | | |
46 | | namespace mozilla { |
47 | | class SVGContextPaint; |
48 | | }; |
49 | | |
50 | 0 | #define NO_FONT_LANGUAGE_OVERRIDE 0 |
51 | | |
52 | | class gfxCharacterMap : public gfxSparseBitSet { |
53 | | public: |
54 | | nsrefcnt AddRef() { |
55 | | MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); |
56 | | ++mRefCnt; |
57 | | NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this)); |
58 | | return mRefCnt; |
59 | | } |
60 | | |
61 | | nsrefcnt Release() { |
62 | | MOZ_ASSERT(0 != mRefCnt, "dup release"); |
63 | | --mRefCnt; |
64 | | NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap"); |
65 | | if (mRefCnt == 0) { |
66 | | NotifyReleased(); |
67 | | // |this| has been deleted. |
68 | | return 0; |
69 | | } |
70 | | return mRefCnt; |
71 | | } |
72 | | |
73 | | gfxCharacterMap() : |
74 | | mHash(0), mBuildOnTheFly(false), mShared(false) |
75 | | { } |
76 | | |
77 | | explicit gfxCharacterMap(const gfxSparseBitSet& aOther) : |
78 | | gfxSparseBitSet(aOther), |
79 | | mHash(0), mBuildOnTheFly(false), mShared(false) |
80 | 0 | { } |
81 | | |
82 | | void CalcHash() { mHash = GetChecksum(); } |
83 | | |
84 | 0 | size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { |
85 | 0 | return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf); |
86 | 0 | } |
87 | | |
88 | | // hash of the cmap bitvector |
89 | | uint32_t mHash; |
90 | | |
91 | | // if cmap is built on the fly it's never shared |
92 | | bool mBuildOnTheFly; |
93 | | |
94 | | // cmap is shared globally |
95 | | bool mShared; |
96 | | |
97 | | protected: |
98 | | void NotifyReleased(); |
99 | | |
100 | | nsAutoRefCnt mRefCnt; |
101 | | |
102 | | private: |
103 | | gfxCharacterMap(const gfxCharacterMap&); |
104 | | gfxCharacterMap& operator=(const gfxCharacterMap&); |
105 | | }; |
106 | | |
107 | | // Info on an individual font feature, for reporting available features |
108 | | // to DevTools via the GetFeatureInfo method. |
109 | | struct gfxFontFeatureInfo { |
110 | | uint32_t mTag; |
111 | | uint32_t mScript; |
112 | | uint32_t mLangSys; |
113 | | }; |
114 | | |
115 | | class gfxFontEntry { |
116 | | public: |
117 | | typedef mozilla::gfx::DrawTarget DrawTarget; |
118 | | typedef mozilla::unicode::Script Script; |
119 | | typedef mozilla::FontWeight FontWeight; |
120 | | typedef mozilla::FontSlantStyle FontSlantStyle; |
121 | | typedef mozilla::FontStretch FontStretch; |
122 | | typedef mozilla::WeightRange WeightRange; |
123 | | typedef mozilla::SlantStyleRange SlantStyleRange; |
124 | | typedef mozilla::StretchRange StretchRange; |
125 | | |
126 | | // Used by stylo |
127 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry) |
128 | | |
129 | | explicit gfxFontEntry(const nsACString& aName, bool aIsStandardFace = false); |
130 | | |
131 | | // Create a new entry that refers to the same font as this, but without |
132 | | // additional state that may have been set up (such as family name). |
133 | | // (This is only to be used for system fonts in the platform font list, |
134 | | // not user fonts.) |
135 | | virtual gfxFontEntry* Clone() const = 0; |
136 | | |
137 | | // unique name for the face, *not* the family; not necessarily the |
138 | | // "real" or user-friendly name, may be an internal identifier |
139 | | const nsCString& Name() const { return mName; } |
140 | | |
141 | | // family name |
142 | | const nsCString& FamilyName() const { return mFamilyName; } |
143 | | |
144 | | // The following two methods may be relatively expensive, as they |
145 | | // will (usually, except on Linux) load and parse the 'name' table; |
146 | | // they are intended only for the font-inspection API, not for |
147 | | // perf-critical layout/drawing work. |
148 | | |
149 | | // The "real" name of the face, if available from the font resource; |
150 | | // returns Name() if nothing better is available. |
151 | | virtual nsCString RealFaceName(); |
152 | | |
153 | | WeightRange Weight() const { return mWeightRange; } |
154 | | StretchRange Stretch() const { return mStretchRange; } |
155 | | SlantStyleRange SlantStyle() const { return mStyleRange; } |
156 | | |
157 | | bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; } |
158 | | bool IsLocalUserFont() const { return mIsLocalUserFont; } |
159 | | bool IsFixedPitch() const { return mFixedPitch; } |
160 | | bool IsItalic() const { return SlantStyle().Min().IsItalic(); } |
161 | | bool IsOblique() const { return SlantStyle().Min().IsOblique(); } |
162 | | bool IsUpright() const { return SlantStyle().Min().IsNormal(); } |
163 | | inline bool SupportsItalic(); |
164 | | inline bool SupportsBold(); // defined below, because of RangeFlags use |
165 | | bool IgnoreGDEF() const { return mIgnoreGDEF; } |
166 | | bool IgnoreGSUB() const { return mIgnoreGSUB; } |
167 | | |
168 | | // Return whether the face corresponds to "normal" CSS style properties: |
169 | | // font-style: normal; |
170 | | // font-weight: normal; |
171 | | // font-stretch: normal; |
172 | | // If this is false, we might want to fall back to a different face and |
173 | | // possibly apply synthetic styling. |
174 | | bool IsNormalStyle() const |
175 | | { |
176 | | return IsUpright() && |
177 | | Weight().Min() <= FontWeight::Normal() && |
178 | | Weight().Max() >= FontWeight::Normal() && |
179 | | Stretch().Min() <= FontStretch::Normal() && |
180 | | Stretch().Max() >= FontStretch::Normal(); |
181 | | } |
182 | | |
183 | | // whether a feature is supported by the font (limited to a small set |
184 | | // of features for which some form of fallback needs to be implemented) |
185 | | virtual bool SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag); |
186 | | bool SupportsGraphiteFeature(uint32_t aFeatureTag); |
187 | | |
188 | | // returns a set containing all input glyph ids for a given feature |
189 | | const hb_set_t* |
190 | | InputsForOpenTypeFeature(Script aScript, uint32_t aFeatureTag); |
191 | | |
192 | | virtual bool HasFontTable(uint32_t aTableTag); |
193 | | |
194 | | inline bool HasGraphiteTables() { |
195 | | if (!mCheckedForGraphiteTables) { |
196 | | CheckForGraphiteTables(); |
197 | | mCheckedForGraphiteTables = true; |
198 | | } |
199 | | return mHasGraphiteTables; |
200 | | } |
201 | | |
202 | 0 | inline bool HasCmapTable() { |
203 | 0 | if (!mCharacterMap) { |
204 | 0 | ReadCMAP(); |
205 | 0 | NS_ASSERTION(mCharacterMap, "failed to initialize character map"); |
206 | 0 | } |
207 | 0 | return mHasCmapTable; |
208 | 0 | } |
209 | | |
210 | | inline bool HasCharacter(uint32_t ch) { |
211 | | if (mCharacterMap && mCharacterMap->test(ch)) { |
212 | | return true; |
213 | | } |
214 | | return TestCharacterMap(ch); |
215 | | } |
216 | | |
217 | | virtual bool SkipDuringSystemFallback() { return false; } |
218 | | nsresult InitializeUVSMap(); |
219 | | uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS); |
220 | | |
221 | | // All concrete gfxFontEntry subclasses (except gfxUserFontEntry) need |
222 | | // to override this, otherwise the font will never be used as it will |
223 | | // be considered to support no characters. |
224 | | // ReadCMAP() must *always* set the mCharacterMap pointer to a valid |
225 | | // gfxCharacterMap, even if empty, as other code assumes this pointer |
226 | | // can be safely dereferenced. |
227 | | virtual nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); |
228 | | |
229 | | bool TryGetSVGData(gfxFont* aFont); |
230 | | bool HasSVGGlyph(uint32_t aGlyphId); |
231 | | bool GetSVGGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphId, |
232 | | gfxFloat aSize, gfxRect* aResult); |
233 | | void RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId, |
234 | | mozilla::SVGContextPaint* aContextPaint); |
235 | | // Call this when glyph geometry or rendering has changed |
236 | | // (e.g. animated SVG glyphs) |
237 | | void NotifyGlyphsChanged(); |
238 | | |
239 | | bool TryGetColorGlyphs(); |
240 | | bool GetColorLayersInfo(uint32_t aGlyphId, |
241 | | const mozilla::gfx::Color& aDefaultColor, |
242 | | nsTArray<uint16_t>& layerGlyphs, |
243 | | nsTArray<mozilla::gfx::Color>& layerColors); |
244 | | |
245 | | // Access to raw font table data (needed for Harfbuzz): |
246 | | // returns a pointer to data owned by the fontEntry or the OS, |
247 | | // which will remain valid until the blob is destroyed. |
248 | | // The data MUST be treated as read-only; we may be getting a |
249 | | // reference to a shared system font cache. |
250 | | // |
251 | | // The default implementation uses CopyFontTable to get the data |
252 | | // into a byte array, and maintains a cache of loaded tables. |
253 | | // |
254 | | // Subclasses should override this if they can provide more efficient |
255 | | // access than copying table data into our own buffers. |
256 | | // |
257 | | // Get blob that encapsulates a specific font table, or nullptr if |
258 | | // the table doesn't exist in the font. |
259 | | // |
260 | | // Caller is responsible to call hb_blob_destroy() on the returned blob |
261 | | // (if non-nullptr) when no longer required. For transient access to a |
262 | | // table, use of AutoTable (below) is generally preferred. |
263 | | virtual hb_blob_t *GetFontTable(uint32_t aTag); |
264 | | |
265 | | // Stack-based utility to return a specified table, automatically releasing |
266 | | // the blob when the AutoTable goes out of scope. |
267 | | class AutoTable { |
268 | | public: |
269 | | AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag) |
270 | | { |
271 | | mBlob = aFontEntry->GetFontTable(aTag); |
272 | | } |
273 | | ~AutoTable() { |
274 | | if (mBlob) { |
275 | | hb_blob_destroy(mBlob); |
276 | | } |
277 | | } |
278 | | operator hb_blob_t*() const { return mBlob; } |
279 | | private: |
280 | | hb_blob_t* mBlob; |
281 | | // not implemented: |
282 | | AutoTable(const AutoTable&) = delete; |
283 | | AutoTable& operator=(const AutoTable&) = delete; |
284 | | }; |
285 | | |
286 | | // Return a font instance for a particular style. This may be a newly- |
287 | | // created instance, or a font already in the global cache. |
288 | | // We can't return a UniquePtr here, because we may be returning a shared |
289 | | // cached instance; but we also don't return already_AddRefed, because |
290 | | // the caller may only need to use the font temporarily and doesn't need |
291 | | // a strong reference. |
292 | | gfxFont* FindOrMakeFont(const gfxFontStyle *aStyle, |
293 | | gfxCharacterMap* aUnicodeRangeMap = nullptr); |
294 | | |
295 | | // Get an existing font table cache entry in aBlob if it has been |
296 | | // registered, or return false if not. Callers must call |
297 | | // hb_blob_destroy on aBlob if true is returned. |
298 | | // |
299 | | // Note that some gfxFont implementations may not call this at all, |
300 | | // if it is more efficient to get the table from the OS at that level. |
301 | | bool GetExistingFontTable(uint32_t aTag, hb_blob_t** aBlob); |
302 | | |
303 | | // Elements of aTable are transferred (not copied) to and returned in a |
304 | | // new hb_blob_t which is registered on the gfxFontEntry, but the initial |
305 | | // reference is owned by the caller. Removing the last reference |
306 | | // unregisters the table from the font entry. |
307 | | // |
308 | | // Pass nullptr for aBuffer to indicate that the table is not present and |
309 | | // nullptr will be returned. Also returns nullptr on OOM. |
310 | | hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag, |
311 | | nsTArray<uint8_t>* aTable); |
312 | | |
313 | | // Get the font's unitsPerEm from the 'head' table, in the case of an |
314 | | // sfnt resource. Will return kInvalidUPEM for non-sfnt fonts, |
315 | | // if present on the platform. |
316 | | uint16_t UnitsPerEm(); |
317 | | enum { |
318 | | kMinUPEM = 16, // Limits on valid unitsPerEm range, from the |
319 | | kMaxUPEM = 16384, // OpenType spec |
320 | | kInvalidUPEM = uint16_t(-1) |
321 | | }; |
322 | | |
323 | | // Shaper face accessors: |
324 | | // NOTE that harfbuzz and graphite handle ownership/lifetime of the face |
325 | | // object in completely different ways. |
326 | | |
327 | | // Get HarfBuzz face corresponding to this font file. |
328 | | // Caller must release with hb_face_destroy() when finished with it, |
329 | | // and the font entry will be notified via ForgetHBFace. |
330 | | hb_face_t* GetHBFace(); |
331 | | virtual void ForgetHBFace(); |
332 | | |
333 | | // Get Graphite face corresponding to this font file. |
334 | | // Caller must call gfxFontEntry::ReleaseGrFace when finished with it. |
335 | | gr_face* GetGrFace(); |
336 | | virtual void ReleaseGrFace(gr_face* aFace); |
337 | | |
338 | | // Does the font have graphite contextuals that involve the space glyph |
339 | | // (and therefore we should bypass the word cache)? |
340 | | bool HasGraphiteSpaceContextuals(); |
341 | | |
342 | | // Release any SVG-glyphs document this font may have loaded. |
343 | | void DisconnectSVG(); |
344 | | |
345 | | // Called to notify that aFont is being destroyed. Needed when we're tracking |
346 | | // the fonts belonging to this font entry. |
347 | | void NotifyFontDestroyed(gfxFont* aFont); |
348 | | |
349 | | // For memory reporting of the platform font list. |
350 | | virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
351 | | FontListSizes* aSizes) const; |
352 | | virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
353 | | FontListSizes* aSizes) const; |
354 | | |
355 | | // Used for reporting on individual font entries in the user font cache, |
356 | | // which are not present in the platform font list. |
357 | | size_t |
358 | | ComputedSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
359 | | |
360 | | // Used when checking for complex script support, to mask off cmap ranges |
361 | | struct ScriptRange { |
362 | | uint32_t rangeStart; |
363 | | uint32_t rangeEnd; |
364 | | hb_tag_t tags[3]; // one or two OpenType script tags to check, |
365 | | // plus a NULL terminator |
366 | | }; |
367 | | |
368 | | bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags); |
369 | | |
370 | | /** |
371 | | * Font-variation query methods. |
372 | | * |
373 | | * Font backends that don't support variations should provide empty |
374 | | * implementations. |
375 | | */ |
376 | | virtual bool HasVariations() = 0; |
377 | | |
378 | | virtual void |
379 | | GetVariationAxes(nsTArray<gfxFontVariationAxis>& aVariationAxes) = 0; |
380 | | |
381 | | virtual void |
382 | | GetVariationInstances(nsTArray<gfxFontVariationInstance>& aInstances) = 0; |
383 | | |
384 | | bool HasBoldVariableWeight(); |
385 | | bool HasItalicVariation(); |
386 | | void CheckForVariationAxes(); |
387 | | |
388 | | // Set up the entry's weight/stretch/style ranges according to axes found |
389 | | // by GetVariationAxes (for installed fonts; do NOT call this for user |
390 | | // fonts, where the ranges are provided by @font-face descriptors). |
391 | | void SetupVariationRanges(); |
392 | | |
393 | | // Get variation axis settings that should be used to implement a particular |
394 | | // font style using this resource. |
395 | | void GetVariationsForStyle(nsTArray<gfxFontVariation>& aResult, |
396 | | const gfxFontStyle& aStyle); |
397 | | |
398 | | // Get the font's list of features (if any) for DevTools support. |
399 | | void GetFeatureInfo(nsTArray<gfxFontFeatureInfo>& aFeatureInfo); |
400 | | |
401 | | // This is only called on platforms where we use FreeType. |
402 | | virtual FT_MM_Var* GetMMVar() { return nullptr; } |
403 | | |
404 | | nsCString mName; |
405 | | nsCString mFamilyName; |
406 | | |
407 | | RefPtr<gfxCharacterMap> mCharacterMap; |
408 | | |
409 | | mozilla::UniquePtr<uint8_t[]> mUVSData; |
410 | | mozilla::UniquePtr<gfxUserFontData> mUserFontData; |
411 | | mozilla::UniquePtr<gfxSVGGlyphs> mSVGGlyphs; |
412 | | // list of gfxFonts that are using SVG glyphs |
413 | | nsTArray<gfxFont*> mFontsUsingSVGGlyphs; |
414 | | nsTArray<gfxFontFeature> mFeatureSettings; |
415 | | nsTArray<gfxFontVariation> mVariationSettings; |
416 | | mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,bool>> mSupportedFeatures; |
417 | | mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,hb_set_t*>> mFeatureInputs; |
418 | | |
419 | | // Color Layer font support |
420 | | hb_blob_t* mCOLR = nullptr; |
421 | | hb_blob_t* mCPAL = nullptr; |
422 | | |
423 | | // bitvector of substitution space features per script, one each |
424 | | // for default and non-default features |
425 | | uint32_t mDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32]; |
426 | | uint32_t mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32]; |
427 | | |
428 | | uint32_t mUVSOffset = 0; |
429 | | |
430 | | uint32_t mLanguageOverride = NO_FONT_LANGUAGE_OVERRIDE; |
431 | | |
432 | | WeightRange mWeightRange = WeightRange(FontWeight(500)); |
433 | | StretchRange mStretchRange = StretchRange(FontStretch::Normal()); |
434 | | SlantStyleRange mStyleRange = SlantStyleRange(FontSlantStyle::Normal()); |
435 | | |
436 | | // For user fonts (only), we need to record whether or not weight/stretch/ |
437 | | // slant variations should be clamped to the range specified in the entry |
438 | | // properties. When the @font-face rule omitted one or more of these |
439 | | // descriptors, it is treated as the initial value for font-matching (and |
440 | | // so that is what we record in the font entry), but when rendering the |
441 | | // range is NOT clamped. |
442 | | enum class RangeFlags : uint8_t { |
443 | | eNoFlags = 0, |
444 | | eAutoWeight = (1 << 0), |
445 | | eAutoStretch = (1 << 1), |
446 | | eAutoSlantStyle = (1 << 2), |
447 | | |
448 | | // Flag to record whether the face has a variable "wght" axis |
449 | | // that supports "bold" values, used to disable the application |
450 | | // of synthetic-bold effects. |
451 | | eBoldVariableWeight = (1 << 3), |
452 | | // Whether the face has an 'ital' axis. |
453 | | eItalicVariation = (1 << 4), |
454 | | |
455 | | // Flags to record if the face uses a non-CSS-compatible scale |
456 | | // for weight and/or stretch, in which case we won't map the |
457 | | // properties to the variation axes (though they can still be |
458 | | // explicitly set using font-variation-settings). |
459 | | eNonCSSWeight = (1 << 5), |
460 | | eNonCSSStretch = (1 << 6) |
461 | | }; |
462 | | RangeFlags mRangeFlags = RangeFlags::eNoFlags; |
463 | | |
464 | | // NOTE that there are currently exactly 24 one-bit flags defined here, |
465 | | // so together with the 8-bit RangeFlags above, this packs neatly to a |
466 | | // 32-bit boundary. Worth considering if further flags are wanted. |
467 | | bool mFixedPitch : 1; |
468 | | bool mIsBadUnderlineFont : 1; |
469 | | bool mIsUserFontContainer : 1; // userfont entry |
470 | | bool mIsDataUserFont : 1; // platform font entry (data) |
471 | | bool mIsLocalUserFont : 1; // platform font entry (local) |
472 | | bool mStandardFace : 1; |
473 | | bool mIgnoreGDEF : 1; |
474 | | bool mIgnoreGSUB : 1; |
475 | | bool mSVGInitialized : 1; |
476 | | bool mHasSpaceFeaturesInitialized : 1; |
477 | | bool mHasSpaceFeatures : 1; |
478 | | bool mHasSpaceFeaturesKerning : 1; |
479 | | bool mHasSpaceFeaturesNonKerning : 1; |
480 | | bool mSkipDefaultFeatureSpaceCheck : 1; |
481 | | bool mGraphiteSpaceContextualsInitialized : 1; |
482 | | bool mHasGraphiteSpaceContextuals : 1; |
483 | | bool mSpaceGlyphIsInvisible : 1; |
484 | | bool mSpaceGlyphIsInvisibleInitialized : 1; |
485 | | bool mHasGraphiteTables : 1; |
486 | | bool mCheckedForGraphiteTables : 1; |
487 | | bool mHasCmapTable : 1; |
488 | | bool mGrFaceInitialized : 1; |
489 | | bool mCheckedForColorGlyph : 1; |
490 | | bool mCheckedForVariationAxes : 1; |
491 | | |
492 | | protected: |
493 | | friend class gfxPlatformFontList; |
494 | | friend class gfxMacPlatformFontList; |
495 | | friend class gfxUserFcFontEntry; |
496 | | friend class gfxFontFamily; |
497 | | friend class gfxSingleFaceMacFontFamily; |
498 | | friend class gfxUserFontEntry; |
499 | | |
500 | | gfxFontEntry(); |
501 | | |
502 | | // Protected destructor, to discourage deletion outside of Release(): |
503 | | virtual ~gfxFontEntry(); |
504 | | |
505 | | virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle) = 0; |
506 | | |
507 | | virtual void CheckForGraphiteTables(); |
508 | | |
509 | | // Copy a font table into aBuffer. |
510 | | // The caller will be responsible for ownership of the data. |
511 | | virtual nsresult CopyFontTable(uint32_t aTableTag, |
512 | | nsTArray<uint8_t>& aBuffer) { |
513 | | MOZ_ASSERT_UNREACHABLE("forgot to override either GetFontTable or " |
514 | | "CopyFontTable?"); |
515 | | return NS_ERROR_FAILURE; |
516 | | } |
517 | | |
518 | | // lookup the cmap in cached font data |
519 | | virtual already_AddRefed<gfxCharacterMap> |
520 | | GetCMAPFromFontInfo(FontInfoData *aFontInfoData, |
521 | | uint32_t& aUVSOffset); |
522 | | |
523 | | // helper for HasCharacter(), which is what client code should call |
524 | | virtual bool TestCharacterMap(uint32_t aCh); |
525 | | |
526 | | // Shaper-specific face objects, shared by all instantiations of the same |
527 | | // physical font, regardless of size. |
528 | | // Usually, only one of these will actually be created for any given font |
529 | | // entry, depending on the font tables that are present. |
530 | | |
531 | | // hb_face_t is refcounted internally, so each shaper that's using it will |
532 | | // bump the ref count when it acquires the face, and "destroy" (release) it |
533 | | // in its destructor. The font entry has only this non-owning reference to |
534 | | // the face; when the face is deleted, it will tell the font entry to forget |
535 | | // it, so that a new face will be created next time it is needed. |
536 | | hb_face_t* mHBFace = nullptr; |
537 | | |
538 | | static hb_blob_t* HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData); |
539 | | |
540 | | // Callback that the hb_face will use to tell us when it is being deleted. |
541 | | static void HBFaceDeletedCallback(void *aUserData); |
542 | | |
543 | | // gr_face is -not- refcounted, so it will be owned directly by the font |
544 | | // entry, and we'll keep a count of how many references we've handed out; |
545 | | // each shaper is responsible to call ReleaseGrFace on its entry when |
546 | | // finished with it, so that we know when it can be deleted. |
547 | | gr_face* mGrFace = nullptr; |
548 | | |
549 | | // hashtable to map raw table data ptr back to its owning blob, for use by |
550 | | // graphite table-release callback |
551 | | nsDataHashtable<nsPtrHashKey<const void>,void*>* mGrTableMap = nullptr; |
552 | | |
553 | | // number of current users of this entry's mGrFace |
554 | | nsrefcnt mGrFaceRefCnt = 0; |
555 | | |
556 | | static const void* GrGetTable(const void *aAppFaceHandle, |
557 | | unsigned int aName, |
558 | | size_t *aLen); |
559 | | static void GrReleaseTable(const void *aAppFaceHandle, |
560 | | const void *aTableBuffer); |
561 | | |
562 | | // For memory reporting: size of user-font data belonging to this entry. |
563 | | // We record this in the font entry because the actual data block may be |
564 | | // handed over to platform APIs, so that it would become difficult (and |
565 | | // platform-specific) to measure it directly at report-gathering time. |
566 | | uint32_t mComputedSizeOfUserFont = 0; |
567 | | |
568 | | // Font's unitsPerEm from the 'head' table, if available (will be set to |
569 | | // kInvalidUPEM for non-sfnt font formats) |
570 | | uint16_t mUnitsPerEm = 0; |
571 | | |
572 | | private: |
573 | | /** |
574 | | * Font table hashtable, to support GetFontTable for harfbuzz. |
575 | | * |
576 | | * The harfbuzz shaper (and potentially other clients) needs access to raw |
577 | | * font table data. This needs to be cached so that it can be used |
578 | | * repeatedly (each time we construct a text run; in some cases, for |
579 | | * each character/glyph within the run) without re-fetching large tables |
580 | | * every time. |
581 | | * |
582 | | * Because we may instantiate many gfxFonts for the same physical font |
583 | | * file (at different sizes), we should ensure that they can share a |
584 | | * single cached copy of the font tables. To do this, we implement table |
585 | | * access and sharing on the fontEntry rather than the font itself. |
586 | | * |
587 | | * The default implementation uses GetFontTable() to read font table |
588 | | * data into byte arrays, and wraps them in blobs which are registered in |
589 | | * a hashtable. The hashtable can then return pre-existing blobs to |
590 | | * harfbuzz. |
591 | | * |
592 | | * Harfbuzz will "destroy" the blobs when it is finished with them. When |
593 | | * the last blob reference is removed, the FontTableBlobData user data |
594 | | * will remove the blob from the hashtable if still registered. |
595 | | */ |
596 | | |
597 | | class FontTableBlobData; |
598 | | |
599 | | /** |
600 | | * FontTableHashEntry manages the entries of hb_blob_t's containing font |
601 | | * table data. |
602 | | * |
603 | | * This is used to share font tables across fonts with the same |
604 | | * font entry (but different sizes) for use by HarfBuzz. The hashtable |
605 | | * does not own a strong reference to the blob, but keeps a weak pointer, |
606 | | * managed by FontTableBlobData. Similarly FontTableBlobData keeps only a |
607 | | * weak pointer to the hashtable, managed by FontTableHashEntry. |
608 | | */ |
609 | | |
610 | | class FontTableHashEntry : public nsUint32HashKey |
611 | | { |
612 | | public: |
613 | | // Declarations for nsTHashtable |
614 | | |
615 | | typedef nsUint32HashKey KeyClass; |
616 | | typedef KeyClass::KeyType KeyType; |
617 | | typedef KeyClass::KeyTypePointer KeyTypePointer; |
618 | | |
619 | | explicit FontTableHashEntry(KeyTypePointer aTag) |
620 | | : KeyClass(aTag) |
621 | | , mSharedBlobData(nullptr) |
622 | | , mBlob(nullptr) |
623 | | { } |
624 | | |
625 | | // NOTE: This assumes the new entry belongs to the same hashtable as |
626 | | // the old, because the mHashtable pointer in mSharedBlobData (if |
627 | | // present) will not be updated. |
628 | | FontTableHashEntry(FontTableHashEntry&& toMove) |
629 | | : KeyClass(std::move(toMove)) |
630 | | , mSharedBlobData(std::move(toMove.mSharedBlobData)) |
631 | | , mBlob(std::move(toMove.mBlob)) |
632 | 0 | { |
633 | 0 | toMove.mSharedBlobData = nullptr; |
634 | 0 | toMove.mBlob = nullptr; |
635 | 0 | } |
636 | | |
637 | | ~FontTableHashEntry() { Clear(); } |
638 | | |
639 | | // FontTable/Blob API |
640 | | |
641 | | // Transfer (not copy) elements of aTable to a new hb_blob_t and |
642 | | // return ownership to the caller. A weak reference to the blob is |
643 | | // recorded in the hashtable entry so that others may use the same |
644 | | // table. |
645 | | hb_blob_t * |
646 | | ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable, |
647 | | nsTHashtable<FontTableHashEntry> *aHashtable); |
648 | | |
649 | | // Return a strong reference to the blob. |
650 | | // Callers must hb_blob_destroy the returned blob. |
651 | | hb_blob_t *GetBlob() const; |
652 | | |
653 | | void Clear(); |
654 | | |
655 | | size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
656 | | |
657 | | private: |
658 | | static void DeleteFontTableBlobData(void *aBlobData); |
659 | | // not implemented |
660 | | FontTableHashEntry& operator=(FontTableHashEntry& toCopy); |
661 | | |
662 | | FontTableBlobData *mSharedBlobData; |
663 | | hb_blob_t *mBlob; |
664 | | }; |
665 | | |
666 | | mozilla::UniquePtr<nsTHashtable<FontTableHashEntry> > mFontTableCache; |
667 | | |
668 | | gfxFontEntry(const gfxFontEntry&); |
669 | | gfxFontEntry& operator=(const gfxFontEntry&); |
670 | | }; |
671 | | |
672 | | MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontEntry::RangeFlags) |
673 | | |
674 | | inline bool |
675 | | gfxFontEntry::SupportsItalic() |
676 | | { |
677 | | return SlantStyle().Max().IsItalic() || |
678 | | ((mRangeFlags & RangeFlags::eAutoSlantStyle) == |
679 | | RangeFlags::eAutoSlantStyle && |
680 | | HasItalicVariation()); |
681 | | } |
682 | | |
683 | | inline bool |
684 | | gfxFontEntry::SupportsBold() |
685 | | { |
686 | | // bold == weights 600 and above |
687 | | // We return true if the face has a max weight descriptor >= 600, |
688 | | // OR if it's a user font with auto-weight (no descriptor) and has |
689 | | // a weight axis that supports values >= 600 |
690 | | return Weight().Max().IsBold() || |
691 | | ((mRangeFlags & RangeFlags::eAutoWeight) == |
692 | | RangeFlags::eAutoWeight && |
693 | | HasBoldVariableWeight()); |
694 | | } |
695 | | |
696 | | // used when iterating over all fonts looking for a match for a given character |
697 | | struct GlobalFontMatch { |
698 | | GlobalFontMatch(const uint32_t aCharacter, |
699 | | const gfxFontStyle& aStyle) : |
700 | | mStyle(aStyle), mCh(aCharacter), |
701 | | mCount(0), mCmapsTested(0), mMatchDistance(INFINITY) |
702 | | { |
703 | | } |
704 | | |
705 | | RefPtr<gfxFontEntry> mBestMatch; // current best match |
706 | | RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to |
707 | | const gfxFontStyle& mStyle; // style to match |
708 | | const uint32_t mCh; // codepoint to be matched |
709 | | uint32_t mCount; // number of fonts matched |
710 | | uint32_t mCmapsTested; // number of cmaps tested |
711 | | float mMatchDistance; // metric indicating closest match |
712 | | }; |
713 | | |
714 | | class gfxFontFamily { |
715 | | public: |
716 | | // Used by stylo |
717 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFamily) |
718 | | |
719 | | explicit gfxFontFamily(const nsACString& aName) : |
720 | | mName(aName), |
721 | | mOtherFamilyNamesInitialized(false), |
722 | | mHasOtherFamilyNames(false), |
723 | | mFaceNamesInitialized(false), |
724 | | mHasStyles(false), |
725 | | mIsSimpleFamily(false), |
726 | | mIsBadUnderlineFamily(false), |
727 | | mFamilyCharacterMapInitialized(false), |
728 | | mSkipDefaultFeatureSpaceCheck(false), |
729 | | mCheckForFallbackFaces(false), |
730 | | mCheckedForLegacyFamilyNames(false) |
731 | | { } |
732 | | |
733 | | const nsCString& Name() { return mName; } |
734 | | |
735 | | virtual void LocalizedName(nsACString& aLocalizedName); |
736 | | virtual bool HasOtherFamilyNames(); |
737 | | |
738 | | // See https://bugzilla.mozilla.org/show_bug.cgi?id=835204: |
739 | | // check the font's 'name' table to see if it has a legacy family name |
740 | | // that would have been used by GDI (e.g. to split extra-bold or light |
741 | | // faces in a large family into separate "styled families" because of |
742 | | // GDI's 4-faces-per-family limitation). If found, the styled family |
743 | | // name will be added to the font list's "other family names" table. |
744 | | bool CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList); |
745 | | |
746 | | nsTArray<RefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; } |
747 | | |
748 | | void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) { |
749 | | // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces |
750 | | // of Times New Roman, because of buggy table in those fonts |
751 | | if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() && |
752 | | Name().EqualsLiteral("Times New Roman")) |
753 | | { |
754 | | aFontEntry->mIgnoreGDEF = true; |
755 | | } |
756 | | if (aFontEntry->mFamilyName.IsEmpty()) { |
757 | | aFontEntry->mFamilyName = Name(); |
758 | | } else { |
759 | | MOZ_ASSERT(aFontEntry->mFamilyName.Equals(Name())); |
760 | | } |
761 | | aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck; |
762 | | mAvailableFonts.AppendElement(aFontEntry); |
763 | | |
764 | | // If we're adding a face to a family that has been marked as "simple", |
765 | | // we need to ensure any null entries are removed, as well as clearing |
766 | | // the flag (which may be set again later). |
767 | | if (mIsSimpleFamily) { |
768 | | for (size_t i = mAvailableFonts.Length() - 1; i-- > 0; ) { |
769 | | if (!mAvailableFonts[i]) { |
770 | | mAvailableFonts.RemoveElementAt(i); |
771 | | } |
772 | | } |
773 | | mIsSimpleFamily = false; |
774 | | } |
775 | | } |
776 | | |
777 | | // note that the styles for this family have been added |
778 | | bool HasStyles() { return mHasStyles; } |
779 | | void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; } |
780 | | |
781 | | // choose a specific face to match a style using CSS font matching |
782 | | // rules (weight matching occurs here). may return a face that doesn't |
783 | | // precisely match (e.g. normal face when no italic face exists). |
784 | | gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle, |
785 | | bool aIgnoreSizeTolerance = false); |
786 | | |
787 | | virtual void |
788 | | FindAllFontsForStyle(const gfxFontStyle& aFontStyle, |
789 | | nsTArray<gfxFontEntry*>& aFontEntryList, |
790 | | bool aIgnoreSizeTolerance = false); |
791 | | |
792 | | // checks for a matching font within the family |
793 | | // used as part of the font fallback process |
794 | | void FindFontForChar(GlobalFontMatch* aMatchData); |
795 | | |
796 | | // checks all fonts for a matching font within the family |
797 | | void SearchAllFontsForChar(GlobalFontMatch* aMatchData); |
798 | | |
799 | | // read in other family names, if any, and use functor to add each into cache |
800 | | virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList); |
801 | | |
802 | | // helper method for reading localized family names from the name table |
803 | | // of a single face |
804 | | static void ReadOtherFamilyNamesForFace(const nsACString& aFamilyName, |
805 | | const char *aNameData, |
806 | | uint32_t aDataLength, |
807 | | nsTArray<nsCString>& aOtherFamilyNames, |
808 | | bool useFullName); |
809 | | |
810 | | // set when other family names have been read in |
811 | 0 | void SetOtherFamilyNamesInitialized() { |
812 | 0 | mOtherFamilyNamesInitialized = true; |
813 | 0 | } |
814 | | |
815 | | // read in other localized family names, fullnames and Postscript names |
816 | | // for all faces and append to lookup tables |
817 | | virtual void ReadFaceNames(gfxPlatformFontList *aPlatformFontList, |
818 | | bool aNeedFullnamePostscriptNames, |
819 | | FontInfoData *aFontInfoData = nullptr); |
820 | | |
821 | | // find faces belonging to this family (platform implementations override this; |
822 | | // should be made pure virtual once all subclasses have been updated) |
823 | | virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) { } |
824 | | |
825 | | // search for a specific face using the Postscript name |
826 | | gfxFontEntry* FindFont(const nsACString& aPostscriptName); |
827 | | |
828 | | // read in cmaps for all the faces |
829 | | void ReadAllCMAPs(FontInfoData *aFontInfoData = nullptr); |
830 | | |
831 | | bool TestCharacterMap(uint32_t aCh) { |
832 | | if (!mFamilyCharacterMapInitialized) { |
833 | | ReadAllCMAPs(); |
834 | | } |
835 | | return mFamilyCharacterMap.test(aCh); |
836 | | } |
837 | | |
838 | | void ResetCharacterMap() { |
839 | | mFamilyCharacterMap.reset(); |
840 | | mFamilyCharacterMapInitialized = false; |
841 | | } |
842 | | |
843 | | // mark this family as being in the "bad" underline offset blacklist |
844 | | void SetBadUnderlineFamily() { |
845 | | mIsBadUnderlineFamily = true; |
846 | | if (mHasStyles) { |
847 | | SetBadUnderlineFonts(); |
848 | | } |
849 | | } |
850 | | |
851 | | bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; } |
852 | | bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; } |
853 | | |
854 | | // sort available fonts to put preferred (standard) faces towards the end |
855 | | void SortAvailableFonts(); |
856 | | |
857 | | // check whether the family fits into the simple 4-face model, |
858 | | // so we can use simplified style-matching; |
859 | | // if so set the mIsSimpleFamily flag (defaults to False before we've checked) |
860 | | void CheckForSimpleFamily(); |
861 | | |
862 | | // For memory reporter |
863 | | virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
864 | | FontListSizes* aSizes) const; |
865 | | virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
866 | | FontListSizes* aSizes) const; |
867 | | |
868 | | #ifdef DEBUG |
869 | | // Only used for debugging checks - does a linear search |
870 | | bool ContainsFace(gfxFontEntry* aFontEntry); |
871 | | #endif |
872 | | |
873 | 0 | void SetSkipSpaceFeatureCheck(bool aSkipCheck) { |
874 | 0 | mSkipDefaultFeatureSpaceCheck = aSkipCheck; |
875 | 0 | } |
876 | | |
877 | | // Check whether this family is appropriate to include in the Preferences |
878 | | // font list for the given langGroup and CSS generic, if the platform lets |
879 | | // us determine this. |
880 | | // Return true if the family should be included in the list, false to omit. |
881 | | // Default implementation returns true for everything, so no filtering |
882 | | // will occur; individual platforms may override. |
883 | | virtual bool FilterForFontList(nsAtom* aLangGroup, |
884 | | const nsACString& aGeneric) const { |
885 | | return true; |
886 | | } |
887 | | |
888 | | protected: |
889 | | // Protected destructor, to discourage deletion outside of Release(): |
890 | | virtual ~gfxFontFamily(); |
891 | | |
892 | | bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList, |
893 | | hb_blob_t *aNameTable, |
894 | | bool useFullName = false); |
895 | | |
896 | | // set whether this font family is in "bad" underline offset blacklist. |
897 | | void SetBadUnderlineFonts() { |
898 | | uint32_t i, numFonts = mAvailableFonts.Length(); |
899 | | for (i = 0; i < numFonts; i++) { |
900 | | if (mAvailableFonts[i]) { |
901 | | mAvailableFonts[i]->mIsBadUnderlineFont = true; |
902 | | } |
903 | | } |
904 | | } |
905 | | |
906 | | nsCString mName; |
907 | | nsTArray<RefPtr<gfxFontEntry> > mAvailableFonts; |
908 | | gfxSparseBitSet mFamilyCharacterMap; |
909 | | bool mOtherFamilyNamesInitialized : 1; |
910 | | bool mHasOtherFamilyNames : 1; |
911 | | bool mFaceNamesInitialized : 1; |
912 | | bool mHasStyles : 1; |
913 | | bool mIsSimpleFamily : 1; |
914 | | bool mIsBadUnderlineFamily : 1; |
915 | | bool mFamilyCharacterMapInitialized : 1; |
916 | | bool mSkipDefaultFeatureSpaceCheck : 1; |
917 | | bool mCheckForFallbackFaces : 1; // check other faces for character |
918 | | bool mCheckedForLegacyFamilyNames : 1; |
919 | | |
920 | | enum { |
921 | | // for "simple" families, the faces are stored in mAvailableFonts |
922 | | // with fixed positions: |
923 | | kRegularFaceIndex = 0, |
924 | | kBoldFaceIndex = 1, |
925 | | kItalicFaceIndex = 2, |
926 | | kBoldItalicFaceIndex = 3, |
927 | | // mask values for selecting face with bold and/or italic attributes |
928 | | kBoldMask = 0x01, |
929 | | kItalicMask = 0x02 |
930 | | }; |
931 | | }; |
932 | | |
933 | | // Struct used in the gfxFontGroup font list to keep track of a font family |
934 | | // together with the CSS generic (if any) that was mapped to it in this |
935 | | // particular case (so it can be reported to the DevTools font inspector). |
936 | | struct FamilyAndGeneric final { |
937 | | FamilyAndGeneric() |
938 | | : mFamily(nullptr) |
939 | | , mGeneric(mozilla::FontFamilyType::eFamily_none) |
940 | 0 | { |
941 | 0 | } |
942 | | FamilyAndGeneric(const FamilyAndGeneric& aOther) |
943 | | : mFamily(aOther.mFamily) |
944 | | , mGeneric(aOther.mGeneric) |
945 | | { |
946 | | } |
947 | | explicit FamilyAndGeneric(gfxFontFamily* aFamily, |
948 | | mozilla::FontFamilyType aGeneric = |
949 | | mozilla::FontFamilyType::eFamily_none) |
950 | | : mFamily(aFamily) |
951 | | , mGeneric(aGeneric) |
952 | | { |
953 | | } |
954 | | gfxFontFamily* mFamily; |
955 | | mozilla::FontFamilyType mGeneric; |
956 | | }; |
957 | | |
958 | | #endif |