Line data Source code
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 "nsTArray.h"
15 : #include "nsTHashtable.h"
16 : #include "mozilla/HashFunctions.h"
17 : #include "mozilla/MemoryReporting.h"
18 : #include "MainThreadUtils.h"
19 : #include "nsUnicodeScriptCodes.h"
20 : #include "nsDataHashtable.h"
21 : #include "harfbuzz/hb.h"
22 : #include "mozilla/gfx/2D.h"
23 : #include "mozilla/UniquePtr.h"
24 : #include "mozilla/WeakPtr.h"
25 :
26 : typedef struct gr_face gr_face;
27 :
28 : #ifdef DEBUG
29 : #include <stdio.h>
30 : #endif
31 :
32 : struct gfxFontStyle;
33 : class gfxContext;
34 : class gfxFont;
35 : class gfxFontFamily;
36 : class gfxUserFontData;
37 : class gfxSVGGlyphs;
38 : class FontInfoData;
39 : struct FontListSizes;
40 : class nsIAtom;
41 :
42 : namespace mozilla {
43 : class SVGContextPaint;
44 : };
45 :
46 0 : class gfxCharacterMap : public gfxSparseBitSet {
47 : public:
48 0 : nsrefcnt AddRef() {
49 0 : NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
50 0 : ++mRefCnt;
51 0 : NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this));
52 0 : return mRefCnt;
53 : }
54 :
55 0 : nsrefcnt Release() {
56 0 : NS_PRECONDITION(0 != mRefCnt, "dup release");
57 0 : --mRefCnt;
58 0 : NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap");
59 0 : if (mRefCnt == 0) {
60 0 : NotifyReleased();
61 : // |this| has been deleted.
62 0 : return 0;
63 : }
64 0 : return mRefCnt;
65 : }
66 :
67 0 : gfxCharacterMap() :
68 0 : mHash(0), mBuildOnTheFly(false), mShared(false)
69 0 : { }
70 :
71 : explicit gfxCharacterMap(const gfxSparseBitSet& aOther) :
72 : gfxSparseBitSet(aOther),
73 : mHash(0), mBuildOnTheFly(false), mShared(false)
74 : { }
75 :
76 0 : void CalcHash() { mHash = GetChecksum(); }
77 :
78 : size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
79 : return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
80 : }
81 :
82 : // hash of the cmap bitvector
83 : uint32_t mHash;
84 :
85 : // if cmap is built on the fly it's never shared
86 : bool mBuildOnTheFly;
87 :
88 : // cmap is shared globally
89 : bool mShared;
90 :
91 : protected:
92 : void NotifyReleased();
93 :
94 : nsAutoRefCnt mRefCnt;
95 :
96 : private:
97 : gfxCharacterMap(const gfxCharacterMap&);
98 : gfxCharacterMap& operator=(const gfxCharacterMap&);
99 : };
100 :
101 : class gfxFontEntry {
102 : public:
103 : typedef mozilla::gfx::DrawTarget DrawTarget;
104 : typedef mozilla::unicode::Script Script;
105 :
106 : // Used by stylo
107 401 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry)
108 :
109 : explicit gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false);
110 :
111 : // unique name for the face, *not* the family; not necessarily the
112 : // "real" or user-friendly name, may be an internal identifier
113 0 : const nsString& Name() const { return mName; }
114 :
115 : // family name
116 34 : const nsString& FamilyName() const { return mFamilyName; }
117 :
118 : // The following two methods may be relatively expensive, as they
119 : // will (usually, except on Linux) load and parse the 'name' table;
120 : // they are intended only for the font-inspection API, not for
121 : // perf-critical layout/drawing work.
122 :
123 : // The "real" name of the face, if available from the font resource;
124 : // returns Name() if nothing better is available.
125 : virtual nsString RealFaceName();
126 :
127 179 : uint16_t Weight() const { return mWeight; }
128 41 : int16_t Stretch() const { return mStretch; }
129 :
130 126 : bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; }
131 0 : bool IsLocalUserFont() const { return mIsLocalUserFont; }
132 0 : bool IsFixedPitch() const { return mFixedPitch; }
133 114 : bool IsItalic() const { return mStyle == NS_FONT_STYLE_ITALIC; }
134 10 : bool IsOblique() const { return mStyle == NS_FONT_STYLE_OBLIQUE; }
135 115 : bool IsUpright() const { return mStyle == NS_FONT_STYLE_NORMAL; }
136 14 : bool IsBold() const { return mWeight >= 600; } // bold == weights 600 and above
137 4 : bool IgnoreGDEF() const { return mIgnoreGDEF; }
138 4 : bool IgnoreGSUB() const { return mIgnoreGSUB; }
139 :
140 : // whether a feature is supported by the font (limited to a small set
141 : // of features for which some form of fallback needs to be implemented)
142 : bool SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
143 : bool SupportsGraphiteFeature(uint32_t aFeatureTag);
144 :
145 : // returns a set containing all input glyph ids for a given feature
146 : const hb_set_t*
147 : InputsForOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
148 :
149 : virtual bool IsSymbolFont();
150 :
151 : virtual bool HasFontTable(uint32_t aTableTag);
152 :
153 105 : inline bool HasGraphiteTables() {
154 105 : if (!mCheckedForGraphiteTables) {
155 2 : CheckForGraphiteTables();
156 2 : mCheckedForGraphiteTables = true;
157 : }
158 105 : return mHasGraphiteTables;
159 : }
160 :
161 0 : inline bool HasCmapTable() {
162 0 : if (!mCharacterMap) {
163 0 : ReadCMAP();
164 0 : NS_ASSERTION(mCharacterMap, "failed to initialize character map");
165 : }
166 0 : return mHasCmapTable;
167 : }
168 :
169 860 : inline bool HasCharacter(uint32_t ch) {
170 860 : if (mCharacterMap && mCharacterMap->test(ch)) {
171 0 : return true;
172 : }
173 860 : return TestCharacterMap(ch);
174 : }
175 :
176 0 : virtual bool SkipDuringSystemFallback() { return false; }
177 : nsresult InitializeUVSMap();
178 : uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS);
179 :
180 : // All concrete gfxFontEntry subclasses (except gfxUserFontEntry) need
181 : // to override this, otherwise the font will never be used as it will
182 : // be considered to support no characters.
183 : // ReadCMAP() must *always* set the mCharacterMap pointer to a valid
184 : // gfxCharacterMap, even if empty, as other code assumes this pointer
185 : // can be safely dereferenced.
186 : virtual nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
187 :
188 : bool TryGetSVGData(gfxFont* aFont);
189 : bool HasSVGGlyph(uint32_t aGlyphId);
190 : bool GetSVGGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphId,
191 : gfxRect *aResult);
192 : void RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId,
193 : mozilla::SVGContextPaint* aContextPaint);
194 : // Call this when glyph geometry or rendering has changed
195 : // (e.g. animated SVG glyphs)
196 : void NotifyGlyphsChanged();
197 :
198 : bool TryGetColorGlyphs();
199 : bool GetColorLayersInfo(uint32_t aGlyphId,
200 : const mozilla::gfx::Color& aDefaultColor,
201 : nsTArray<uint16_t>& layerGlyphs,
202 : nsTArray<mozilla::gfx::Color>& layerColors);
203 :
204 0 : virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
205 0 : return true;
206 : }
207 0 : virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
208 0 : return true;
209 : }
210 :
211 : // Access to raw font table data (needed for Harfbuzz):
212 : // returns a pointer to data owned by the fontEntry or the OS,
213 : // which will remain valid until the blob is destroyed.
214 : // The data MUST be treated as read-only; we may be getting a
215 : // reference to a shared system font cache.
216 : //
217 : // The default implementation uses CopyFontTable to get the data
218 : // into a byte array, and maintains a cache of loaded tables.
219 : //
220 : // Subclasses should override this if they can provide more efficient
221 : // access than copying table data into our own buffers.
222 : //
223 : // Get blob that encapsulates a specific font table, or nullptr if
224 : // the table doesn't exist in the font.
225 : //
226 : // Caller is responsible to call hb_blob_destroy() on the returned blob
227 : // (if non-nullptr) when no longer required. For transient access to a
228 : // table, use of AutoTable (below) is generally preferred.
229 : virtual hb_blob_t *GetFontTable(uint32_t aTag);
230 :
231 : // Stack-based utility to return a specified table, automatically releasing
232 : // the blob when the AutoTable goes out of scope.
233 : class AutoTable {
234 : public:
235 4 : AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag)
236 4 : {
237 4 : mBlob = aFontEntry->GetFontTable(aTag);
238 4 : }
239 8 : ~AutoTable() {
240 4 : if (mBlob) {
241 2 : hb_blob_destroy(mBlob);
242 : }
243 4 : }
244 6 : operator hb_blob_t*() const { return mBlob; }
245 : private:
246 : hb_blob_t* mBlob;
247 : // not implemented:
248 : AutoTable(const AutoTable&) = delete;
249 : AutoTable& operator=(const AutoTable&) = delete;
250 : };
251 :
252 : // Return a font instance for a particular style. This may be a newly-
253 : // created instance, or a font already in the global cache.
254 : // We can't return a UniquePtr here, because we may be returning a shared
255 : // cached instance; but we also don't return already_AddRefed, because
256 : // the caller may only need to use the font temporarily and doesn't need
257 : // a strong reference.
258 : gfxFont* FindOrMakeFont(const gfxFontStyle *aStyle,
259 : bool aNeedsBold,
260 : gfxCharacterMap* aUnicodeRangeMap = nullptr);
261 :
262 : // Get an existing font table cache entry in aBlob if it has been
263 : // registered, or return false if not. Callers must call
264 : // hb_blob_destroy on aBlob if true is returned.
265 : //
266 : // Note that some gfxFont implementations may not call this at all,
267 : // if it is more efficient to get the table from the OS at that level.
268 : bool GetExistingFontTable(uint32_t aTag, hb_blob_t** aBlob);
269 :
270 : // Elements of aTable are transferred (not copied) to and returned in a
271 : // new hb_blob_t which is registered on the gfxFontEntry, but the initial
272 : // reference is owned by the caller. Removing the last reference
273 : // unregisters the table from the font entry.
274 : //
275 : // Pass nullptr for aBuffer to indicate that the table is not present and
276 : // nullptr will be returned. Also returns nullptr on OOM.
277 : hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag,
278 : nsTArray<uint8_t>* aTable);
279 :
280 : // Get the font's unitsPerEm from the 'head' table, in the case of an
281 : // sfnt resource. Will return kInvalidUPEM for non-sfnt fonts,
282 : // if present on the platform.
283 : uint16_t UnitsPerEm();
284 : enum {
285 : kMinUPEM = 16, // Limits on valid unitsPerEm range, from the
286 : kMaxUPEM = 16384, // OpenType spec
287 : kInvalidUPEM = uint16_t(-1)
288 : };
289 :
290 : // Shaper face accessors:
291 : // NOTE that harfbuzz and graphite handle ownership/lifetime of the face
292 : // object in completely different ways.
293 :
294 : // Get HarfBuzz face corresponding to this font file.
295 : // Caller must release with hb_face_destroy() when finished with it,
296 : // and the font entry will be notified via ForgetHBFace.
297 : hb_face_t* GetHBFace();
298 : virtual void ForgetHBFace();
299 :
300 : // Get Graphite face corresponding to this font file.
301 : // Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
302 : gr_face* GetGrFace();
303 : virtual void ReleaseGrFace(gr_face* aFace);
304 :
305 : // Does the font have graphite contextuals that involve the space glyph
306 : // (and therefore we should bypass the word cache)?
307 : bool HasGraphiteSpaceContextuals();
308 :
309 : // Release any SVG-glyphs document this font may have loaded.
310 : void DisconnectSVG();
311 :
312 : // Called to notify that aFont is being destroyed. Needed when we're tracking
313 : // the fonts belonging to this font entry.
314 : void NotifyFontDestroyed(gfxFont* aFont);
315 :
316 : // For memory reporting of the platform font list.
317 : virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
318 : FontListSizes* aSizes) const;
319 : virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
320 : FontListSizes* aSizes) const;
321 :
322 : // Used for reporting on individual font entries in the user font cache,
323 : // which are not present in the platform font list.
324 : size_t
325 : ComputedSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
326 :
327 : // Used when checking for complex script support, to mask off cmap ranges
328 : struct ScriptRange {
329 : uint32_t rangeStart;
330 : uint32_t rangeEnd;
331 : hb_tag_t tags[3]; // one or two OpenType script tags to check,
332 : // plus a NULL terminator
333 : };
334 :
335 : bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags);
336 :
337 : nsString mName;
338 : nsString mFamilyName;
339 :
340 : uint8_t mStyle : 2; // italic/oblique
341 : bool mFixedPitch : 1;
342 : bool mIsValid : 1;
343 : bool mIsBadUnderlineFont : 1;
344 : bool mIsUserFontContainer : 1; // userfont entry
345 : bool mIsDataUserFont : 1; // platform font entry (data)
346 : bool mIsLocalUserFont : 1; // platform font entry (local)
347 : bool mStandardFace : 1;
348 : bool mSymbolFont : 1;
349 : bool mIgnoreGDEF : 1;
350 : bool mIgnoreGSUB : 1;
351 : bool mSVGInitialized : 1;
352 : bool mHasSpaceFeaturesInitialized : 1;
353 : bool mHasSpaceFeatures : 1;
354 : bool mHasSpaceFeaturesKerning : 1;
355 : bool mHasSpaceFeaturesNonKerning : 1;
356 : bool mSkipDefaultFeatureSpaceCheck : 1;
357 : bool mGraphiteSpaceContextualsInitialized : 1;
358 : bool mHasGraphiteSpaceContextuals : 1;
359 : bool mSpaceGlyphIsInvisible : 1;
360 : bool mSpaceGlyphIsInvisibleInitialized : 1;
361 : bool mHasGraphiteTables : 1;
362 : bool mCheckedForGraphiteTables : 1;
363 : bool mHasCmapTable : 1;
364 : bool mGrFaceInitialized : 1;
365 : bool mCheckedForColorGlyph : 1;
366 :
367 : // bitvector of substitution space features per script, one each
368 : // for default and non-default features
369 : uint32_t mDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
370 : uint32_t mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
371 :
372 : uint16_t mWeight;
373 : int16_t mStretch;
374 :
375 : RefPtr<gfxCharacterMap> mCharacterMap;
376 : uint32_t mUVSOffset;
377 : mozilla::UniquePtr<uint8_t[]> mUVSData;
378 : mozilla::UniquePtr<gfxUserFontData> mUserFontData;
379 : mozilla::UniquePtr<gfxSVGGlyphs> mSVGGlyphs;
380 : // list of gfxFonts that are using SVG glyphs
381 : nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
382 : nsTArray<gfxFontFeature> mFeatureSettings;
383 : mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,bool>> mSupportedFeatures;
384 : mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,hb_set_t*>> mFeatureInputs;
385 : uint32_t mLanguageOverride;
386 :
387 : // Color Layer font support
388 : hb_blob_t* mCOLR;
389 : hb_blob_t* mCPAL;
390 :
391 : protected:
392 : friend class gfxPlatformFontList;
393 : friend class gfxMacPlatformFontList;
394 : friend class gfxUserFcFontEntry;
395 : friend class gfxFontFamily;
396 : friend class gfxSingleFaceMacFontFamily;
397 : friend class gfxUserFontEntry;
398 :
399 : gfxFontEntry();
400 :
401 : // Protected destructor, to discourage deletion outside of Release():
402 : virtual ~gfxFontEntry();
403 :
404 : virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
405 : bool aNeedsBold) = 0;
406 :
407 : virtual void CheckForGraphiteTables();
408 :
409 : // Copy a font table into aBuffer.
410 : // The caller will be responsible for ownership of the data.
411 0 : virtual nsresult CopyFontTable(uint32_t aTableTag,
412 : nsTArray<uint8_t>& aBuffer) {
413 0 : NS_NOTREACHED("forgot to override either GetFontTable or CopyFontTable?");
414 0 : return NS_ERROR_FAILURE;
415 : }
416 :
417 : // lookup the cmap in cached font data
418 : virtual already_AddRefed<gfxCharacterMap>
419 : GetCMAPFromFontInfo(FontInfoData *aFontInfoData,
420 : uint32_t& aUVSOffset,
421 : bool& aSymbolFont);
422 :
423 : // helper for HasCharacter(), which is what client code should call
424 : virtual bool TestCharacterMap(uint32_t aCh);
425 :
426 : // Font's unitsPerEm from the 'head' table, if available (will be set to
427 : // kInvalidUPEM for non-sfnt font formats)
428 : uint16_t mUnitsPerEm;
429 :
430 : // Shaper-specific face objects, shared by all instantiations of the same
431 : // physical font, regardless of size.
432 : // Usually, only one of these will actually be created for any given font
433 : // entry, depending on the font tables that are present.
434 :
435 : // hb_face_t is refcounted internally, so each shaper that's using it will
436 : // bump the ref count when it acquires the face, and "destroy" (release) it
437 : // in its destructor. The font entry has only this non-owning reference to
438 : // the face; when the face is deleted, it will tell the font entry to forget
439 : // it, so that a new face will be created next time it is needed.
440 : hb_face_t* mHBFace;
441 :
442 : static hb_blob_t* HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData);
443 :
444 : // Callback that the hb_face will use to tell us when it is being deleted.
445 : static void HBFaceDeletedCallback(void *aUserData);
446 :
447 : // gr_face is -not- refcounted, so it will be owned directly by the font
448 : // entry, and we'll keep a count of how many references we've handed out;
449 : // each shaper is responsible to call ReleaseGrFace on its entry when
450 : // finished with it, so that we know when it can be deleted.
451 : gr_face* mGrFace;
452 :
453 : // hashtable to map raw table data ptr back to its owning blob, for use by
454 : // graphite table-release callback
455 : nsDataHashtable<nsPtrHashKey<const void>,void*>* mGrTableMap;
456 :
457 : // number of current users of this entry's mGrFace
458 : nsrefcnt mGrFaceRefCnt;
459 :
460 : static const void* GrGetTable(const void *aAppFaceHandle,
461 : unsigned int aName,
462 : size_t *aLen);
463 : static void GrReleaseTable(const void *aAppFaceHandle,
464 : const void *aTableBuffer);
465 :
466 : // For memory reporting: size of user-font data belonging to this entry.
467 : // We record this in the font entry because the actual data block may be
468 : // handed over to platform APIs, so that it would become difficult (and
469 : // platform-specific) to measure it directly at report-gathering time.
470 : uint32_t mComputedSizeOfUserFont;
471 :
472 : private:
473 : /**
474 : * Font table hashtable, to support GetFontTable for harfbuzz.
475 : *
476 : * The harfbuzz shaper (and potentially other clients) needs access to raw
477 : * font table data. This needs to be cached so that it can be used
478 : * repeatedly (each time we construct a text run; in some cases, for
479 : * each character/glyph within the run) without re-fetching large tables
480 : * every time.
481 : *
482 : * Because we may instantiate many gfxFonts for the same physical font
483 : * file (at different sizes), we should ensure that they can share a
484 : * single cached copy of the font tables. To do this, we implement table
485 : * access and sharing on the fontEntry rather than the font itself.
486 : *
487 : * The default implementation uses GetFontTable() to read font table
488 : * data into byte arrays, and wraps them in blobs which are registered in
489 : * a hashtable. The hashtable can then return pre-existing blobs to
490 : * harfbuzz.
491 : *
492 : * Harfbuzz will "destroy" the blobs when it is finished with them. When
493 : * the last blob reference is removed, the FontTableBlobData user data
494 : * will remove the blob from the hashtable if still registered.
495 : */
496 :
497 : class FontTableBlobData;
498 :
499 : /**
500 : * FontTableHashEntry manages the entries of hb_blob_t's containing font
501 : * table data.
502 : *
503 : * This is used to share font tables across fonts with the same
504 : * font entry (but different sizes) for use by HarfBuzz. The hashtable
505 : * does not own a strong reference to the blob, but keeps a weak pointer,
506 : * managed by FontTableBlobData. Similarly FontTableBlobData keeps only a
507 : * weak pointer to the hashtable, managed by FontTableHashEntry.
508 : */
509 :
510 : class FontTableHashEntry : public nsUint32HashKey
511 : {
512 : public:
513 : // Declarations for nsTHashtable
514 :
515 : typedef nsUint32HashKey KeyClass;
516 : typedef KeyClass::KeyType KeyType;
517 : typedef KeyClass::KeyTypePointer KeyTypePointer;
518 :
519 21 : explicit FontTableHashEntry(KeyTypePointer aTag)
520 21 : : KeyClass(aTag)
521 : , mSharedBlobData(nullptr)
522 21 : , mBlob(nullptr)
523 21 : { }
524 :
525 : // NOTE: This assumes the new entry belongs to the same hashtable as
526 : // the old, because the mHashtable pointer in mSharedBlobData (if
527 : // present) will not be updated.
528 : FontTableHashEntry(FontTableHashEntry&& toMove)
529 : : KeyClass(mozilla::Move(toMove))
530 : , mSharedBlobData(mozilla::Move(toMove.mSharedBlobData))
531 : , mBlob(mozilla::Move(toMove.mBlob))
532 : {
533 : toMove.mSharedBlobData = nullptr;
534 : toMove.mBlob = nullptr;
535 : }
536 :
537 9 : ~FontTableHashEntry() { Clear(); }
538 :
539 : // FontTable/Blob API
540 :
541 : // Transfer (not copy) elements of aTable to a new hb_blob_t and
542 : // return ownership to the caller. A weak reference to the blob is
543 : // recorded in the hashtable entry so that others may use the same
544 : // table.
545 : hb_blob_t *
546 : ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable,
547 : nsTHashtable<FontTableHashEntry> *aHashtable);
548 :
549 : // Return a strong reference to the blob.
550 : // Callers must hb_blob_destroy the returned blob.
551 : hb_blob_t *GetBlob() const;
552 :
553 : void Clear();
554 :
555 : size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
556 :
557 : private:
558 : static void DeleteFontTableBlobData(void *aBlobData);
559 : // not implemented
560 : FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
561 :
562 : FontTableBlobData *mSharedBlobData;
563 : hb_blob_t *mBlob;
564 : };
565 :
566 : mozilla::UniquePtr<nsTHashtable<FontTableHashEntry> > mFontTableCache;
567 :
568 : gfxFontEntry(const gfxFontEntry&);
569 : gfxFontEntry& operator=(const gfxFontEntry&);
570 : };
571 :
572 :
573 : // used when iterating over all fonts looking for a match for a given character
574 0 : struct GlobalFontMatch {
575 0 : GlobalFontMatch(const uint32_t aCharacter,
576 : mozilla::unicode::Script aRunScript,
577 0 : const gfxFontStyle *aStyle) :
578 : mCh(aCharacter), mRunScript(aRunScript), mStyle(aStyle),
579 0 : mMatchRank(0), mCount(0), mCmapsTested(0)
580 : {
581 :
582 0 : }
583 :
584 : const uint32_t mCh; // codepoint to be matched
585 : mozilla::unicode::Script mRunScript; // Unicode script for the codepoint
586 : const gfxFontStyle* mStyle; // style to match
587 : int32_t mMatchRank; // metric indicating closest match
588 : RefPtr<gfxFontEntry> mBestMatch; // current best match
589 : RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to
590 : uint32_t mCount; // number of fonts matched
591 : uint32_t mCmapsTested; // number of cmaps tested
592 : };
593 :
594 : class gfxFontFamily {
595 : public:
596 : // Used by stylo
597 2170 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFamily)
598 :
599 558 : explicit gfxFontFamily(const nsAString& aName) :
600 : mName(aName),
601 : mOtherFamilyNamesInitialized(false),
602 : mHasOtherFamilyNames(false),
603 : mFaceNamesInitialized(false),
604 : mHasStyles(false),
605 : mIsSimpleFamily(false),
606 : mIsBadUnderlineFamily(false),
607 : mFamilyCharacterMapInitialized(false),
608 : mSkipDefaultFeatureSpaceCheck(false),
609 558 : mCheckForFallbackFaces(false)
610 558 : { }
611 :
612 139 : const nsString& Name() { return mName; }
613 :
614 : virtual void LocalizedName(nsAString& aLocalizedName);
615 : virtual bool HasOtherFamilyNames();
616 :
617 65 : nsTArray<RefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; }
618 :
619 107 : void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) {
620 : // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
621 : // of Times New Roman, because of buggy table in those fonts
622 139 : if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
623 32 : Name().EqualsLiteral("Times New Roman"))
624 : {
625 8 : aFontEntry->mIgnoreGDEF = true;
626 : }
627 107 : if (aFontEntry->mFamilyName.IsEmpty()) {
628 107 : aFontEntry->mFamilyName = Name();
629 : } else {
630 0 : MOZ_ASSERT(aFontEntry->mFamilyName.Equals(Name()));
631 : }
632 107 : aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
633 107 : mAvailableFonts.AppendElement(aFontEntry);
634 107 : }
635 :
636 : // note that the styles for this family have been added
637 65 : bool HasStyles() { return mHasStyles; }
638 16 : void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
639 :
640 : // choose a specific face to match a style using CSS font matching
641 : // rules (weight matching occurs here). may return a face that doesn't
642 : // precisely match (e.g. normal face when no italic face exists).
643 : // aNeedsSyntheticBold is set to true when synthetic bolding is
644 : // needed, false otherwise
645 : gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
646 : bool& aNeedsSyntheticBold);
647 :
648 : virtual void
649 : FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
650 : nsTArray<gfxFontEntry*>& aFontEntryList,
651 : bool& aNeedsSyntheticBold);
652 :
653 : // checks for a matching font within the family
654 : // used as part of the font fallback process
655 : void FindFontForChar(GlobalFontMatch *aMatchData);
656 :
657 : // checks all fonts for a matching font within the family
658 : void SearchAllFontsForChar(GlobalFontMatch *aMatchData);
659 :
660 : // read in other family names, if any, and use functor to add each into cache
661 : virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList);
662 :
663 : // helper method for reading localized family names from the name table
664 : // of a single face
665 : static void ReadOtherFamilyNamesForFace(const nsAString& aFamilyName,
666 : const char *aNameData,
667 : uint32_t aDataLength,
668 : nsTArray<nsString>& aOtherFamilyNames,
669 : bool useFullName);
670 :
671 : // set when other family names have been read in
672 : void SetOtherFamilyNamesInitialized() {
673 : mOtherFamilyNamesInitialized = true;
674 : }
675 :
676 : // read in other localized family names, fullnames and Postscript names
677 : // for all faces and append to lookup tables
678 : virtual void ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
679 : bool aNeedFullnamePostscriptNames,
680 : FontInfoData *aFontInfoData = nullptr);
681 :
682 : // find faces belonging to this family (platform implementations override this;
683 : // should be made pure virtual once all subclasses have been updated)
684 0 : virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) { }
685 :
686 : // search for a specific face using the Postscript name
687 : gfxFontEntry* FindFont(const nsAString& aPostscriptName);
688 :
689 : // read in cmaps for all the faces
690 : void ReadAllCMAPs(FontInfoData *aFontInfoData = nullptr);
691 :
692 0 : bool TestCharacterMap(uint32_t aCh) {
693 0 : if (!mFamilyCharacterMapInitialized) {
694 0 : ReadAllCMAPs();
695 : }
696 0 : return mFamilyCharacterMap.test(aCh);
697 : }
698 :
699 0 : void ResetCharacterMap() {
700 0 : mFamilyCharacterMap.reset();
701 0 : mFamilyCharacterMapInitialized = false;
702 0 : }
703 :
704 : // mark this family as being in the "bad" underline offset blacklist
705 0 : void SetBadUnderlineFamily() {
706 0 : mIsBadUnderlineFamily = true;
707 0 : if (mHasStyles) {
708 0 : SetBadUnderlineFonts();
709 : }
710 0 : }
711 :
712 13 : bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
713 16 : bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
714 :
715 : // sort available fonts to put preferred (standard) faces towards the end
716 : void SortAvailableFonts();
717 :
718 : // check whether the family fits into the simple 4-face model,
719 : // so we can use simplified style-matching;
720 : // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
721 : void CheckForSimpleFamily();
722 :
723 : // For memory reporter
724 : virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
725 : FontListSizes* aSizes) const;
726 : virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
727 : FontListSizes* aSizes) const;
728 :
729 : #ifdef DEBUG
730 : // Only used for debugging checks - does a linear search
731 : bool ContainsFace(gfxFontEntry* aFontEntry);
732 : #endif
733 :
734 : void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
735 : mSkipDefaultFeatureSpaceCheck = aSkipCheck;
736 : }
737 :
738 : protected:
739 : // Protected destructor, to discourage deletion outside of Release():
740 : virtual ~gfxFontFamily();
741 :
742 : bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
743 : hb_blob_t *aNameTable,
744 : bool useFullName = false);
745 :
746 : // set whether this font family is in "bad" underline offset blacklist.
747 0 : void SetBadUnderlineFonts() {
748 0 : uint32_t i, numFonts = mAvailableFonts.Length();
749 0 : for (i = 0; i < numFonts; i++) {
750 0 : if (mAvailableFonts[i]) {
751 0 : mAvailableFonts[i]->mIsBadUnderlineFont = true;
752 : }
753 : }
754 0 : }
755 :
756 : nsString mName;
757 : nsTArray<RefPtr<gfxFontEntry> > mAvailableFonts;
758 : gfxSparseBitSet mFamilyCharacterMap;
759 : bool mOtherFamilyNamesInitialized : 1;
760 : bool mHasOtherFamilyNames : 1;
761 : bool mFaceNamesInitialized : 1;
762 : bool mHasStyles : 1;
763 : bool mIsSimpleFamily : 1;
764 : bool mIsBadUnderlineFamily : 1;
765 : bool mFamilyCharacterMapInitialized : 1;
766 : bool mSkipDefaultFeatureSpaceCheck : 1;
767 : bool mCheckForFallbackFaces : 1; // check other faces for character
768 :
769 : enum {
770 : // for "simple" families, the faces are stored in mAvailableFonts
771 : // with fixed positions:
772 : kRegularFaceIndex = 0,
773 : kBoldFaceIndex = 1,
774 : kItalicFaceIndex = 2,
775 : kBoldItalicFaceIndex = 3,
776 : // mask values for selecting face with bold and/or italic attributes
777 : kBoldMask = 0x01,
778 : kItalicMask = 0x02
779 : };
780 : };
781 :
782 : #endif
|