Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/thebes/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
#define NO_FONT_LANGUAGE_OVERRIDE      0
51
52
class gfxCharacterMap : public gfxSparseBitSet {
53
public:
54
0
    nsrefcnt AddRef() {
55
0
        MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
56
0
        ++mRefCnt;
57
0
        NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this));
58
0
        return mRefCnt;
59
0
    }
60
61
0
    nsrefcnt Release() {
62
0
        MOZ_ASSERT(0 != mRefCnt, "dup release");
63
0
        --mRefCnt;
64
0
        NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap");
65
0
        if (mRefCnt == 0) {
66
0
            NotifyReleased();
67
0
            // |this| has been deleted.
68
0
            return 0;
69
0
        }
70
0
        return mRefCnt;
71
0
    }
72
73
    gfxCharacterMap() :
74
        mHash(0), mBuildOnTheFly(false), mShared(false)
75
0
    { }
76
77
    explicit gfxCharacterMap(const gfxSparseBitSet& aOther) :
78
        gfxSparseBitSet(aOther),
79
        mHash(0), mBuildOnTheFly(false), mShared(false)
80
    { }
81
82
0
    void CalcHash() { mHash = GetChecksum(); }
83
84
    size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
85
        return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
86
    }
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
0
    const nsCString& Name() const { return mName; }
140
141
    // family name
142
0
    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
0
    WeightRange Weight() const { return mWeightRange; }
154
0
    StretchRange Stretch() const { return mStretchRange; }
155
0
    SlantStyleRange SlantStyle() const { return mStyleRange; }
156
157
0
    bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; }
158
0
    bool IsLocalUserFont() const { return mIsLocalUserFont; }
159
0
    bool IsFixedPitch() const { return mFixedPitch; }
160
0
    bool IsItalic() const { return SlantStyle().Min().IsItalic(); }
161
0
    bool IsOblique() const { return SlantStyle().Min().IsOblique(); }
162
0
    bool IsUpright() const { return SlantStyle().Min().IsNormal(); }
163
    inline bool SupportsItalic();
164
    inline bool SupportsBold(); // defined below, because of RangeFlags use
165
0
    bool IgnoreGDEF() const { return mIgnoreGDEF; }
166
0
    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
0
    {
176
0
        return IsUpright() &&
177
0
               Weight().Min() <= FontWeight::Normal() &&
178
0
               Weight().Max() >= FontWeight::Normal() &&
179
0
               Stretch().Min() <= FontStretch::Normal() &&
180
0
               Stretch().Max() >= FontStretch::Normal();
181
0
    }
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
0
    inline bool HasGraphiteTables() {
195
0
        if (!mCheckedForGraphiteTables) {
196
0
            CheckForGraphiteTables();
197
0
            mCheckedForGraphiteTables = true;
198
0
        }
199
0
        return mHasGraphiteTables;
200
0
    }
201
202
    inline bool HasCmapTable() {
203
        if (!mCharacterMap) {
204
            ReadCMAP();
205
            NS_ASSERTION(mCharacterMap, "failed to initialize character map");
206
        }
207
        return mHasCmapTable;
208
    }
209
210
0
    inline bool HasCharacter(uint32_t ch) {
211
0
        if (mCharacterMap && mCharacterMap->test(ch)) {
212
0
            return true;
213
0
        }
214
0
        return TestCharacterMap(ch);
215
0
    }
216
217
0
    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
0
        {
271
0
            mBlob = aFontEntry->GetFontTable(aTag);
272
0
        }
273
0
        ~AutoTable() {
274
0
            if (mBlob) {
275
0
                hb_blob_destroy(mBlob);
276
0
            }
277
0
        }
278
0
        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
0
    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
0
                                   nsTArray<uint8_t>& aBuffer) {
513
0
        MOZ_ASSERT_UNREACHABLE("forgot to override either GetFontTable or "
514
0
                               "CopyFontTable?");
515
0
        return NS_ERROR_FAILURE;
516
0
    }
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
0
        { }
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
        {
633
            toMove.mSharedBlobData = nullptr;
634
            toMove.mBlob = nullptr;
635
        }
636
637
0
        ~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
0
{
677
0
    return SlantStyle().Max().IsItalic() ||
678
0
           ((mRangeFlags & RangeFlags::eAutoSlantStyle) ==
679
0
               RangeFlags::eAutoSlantStyle &&
680
0
            HasItalicVariation());
681
0
}
682
683
inline bool
684
gfxFontEntry::SupportsBold()
685
0
{
686
0
    // bold == weights 600 and above
687
0
    // We return true if the face has a max weight descriptor >= 600,
688
0
    // OR if it's a user font with auto-weight (no descriptor) and has
689
0
    // a weight axis that supports values >= 600
690
0
    return Weight().Max().IsBold() ||
691
0
           ((mRangeFlags & RangeFlags::eAutoWeight) ==
692
0
               RangeFlags::eAutoWeight &&
693
0
            HasBoldVariableWeight());
694
0
}
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
0
        {
703
0
        }
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
0
        { }
732
733
0
    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
0
    nsTArray<RefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; }
747
    
748
0
    void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) {
749
0
        // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
750
0
        // of Times New Roman, because of buggy table in those fonts
751
0
        if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
752
0
            Name().EqualsLiteral("Times New Roman"))
753
0
        {
754
0
            aFontEntry->mIgnoreGDEF = true;
755
0
        }
756
0
        if (aFontEntry->mFamilyName.IsEmpty()) {
757
0
            aFontEntry->mFamilyName = Name();
758
0
        } else {
759
0
            MOZ_ASSERT(aFontEntry->mFamilyName.Equals(Name()));
760
0
        }
761
0
        aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
762
0
        mAvailableFonts.AppendElement(aFontEntry);
763
0
764
0
        // If we're adding a face to a family that has been marked as "simple",
765
0
        // we need to ensure any null entries are removed, as well as clearing
766
0
        // the flag (which may be set again later).
767
0
        if (mIsSimpleFamily) {
768
0
            for (size_t i = mAvailableFonts.Length() - 1; i-- > 0; ) {
769
0
                if (!mAvailableFonts[i]) {
770
0
                    mAvailableFonts.RemoveElementAt(i);
771
0
                }
772
0
            }
773
0
            mIsSimpleFamily = false;
774
0
        }
775
0
    }
776
777
    // note that the styles for this family have been added
778
0
    bool HasStyles() { return mHasStyles; }
779
0
    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
    void SetOtherFamilyNamesInitialized() {
812
        mOtherFamilyNamesInitialized = true;
813
    }
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
0
    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
0
    bool TestCharacterMap(uint32_t aCh) {
832
0
        if (!mFamilyCharacterMapInitialized) {
833
0
            ReadAllCMAPs();
834
0
        }
835
0
        return mFamilyCharacterMap.test(aCh);
836
0
    }
837
838
0
    void ResetCharacterMap() {
839
0
        mFamilyCharacterMap.reset();
840
0
        mFamilyCharacterMapInitialized = false;
841
0
    }
842
843
    // mark this family as being in the "bad" underline offset blacklist
844
0
    void SetBadUnderlineFamily() {
845
0
        mIsBadUnderlineFamily = true;
846
0
        if (mHasStyles) {
847
0
            SetBadUnderlineFonts();
848
0
        }
849
0
    }
850
851
0
    bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
852
0
    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
    void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
874
        mSkipDefaultFeatureSpaceCheck = aSkipCheck;
875
    }
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
0
                                   const nsACString& aGeneric) const {
885
0
        return true;
886
0
    }
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
0
    void SetBadUnderlineFonts() {
898
0
        uint32_t i, numFonts = mAvailableFonts.Length();
899
0
        for (i = 0; i < numFonts; i++) {
900
0
            if (mAvailableFonts[i]) {
901
0
                mAvailableFonts[i]->mIsBadUnderlineFont = true;
902
0
            }
903
0
        }
904
0
    }
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
    {
941
    }
942
    FamilyAndGeneric(const FamilyAndGeneric& aOther)
943
        : mFamily(aOther.mFamily)
944
        , mGeneric(aOther.mGeneric)
945
0
    {
946
0
    }
947
    explicit FamilyAndGeneric(gfxFontFamily* aFamily,
948
                              mozilla::FontFamilyType aGeneric =
949
                                  mozilla::FontFamilyType::eFamily_none)
950
        : mFamily(aFamily)
951
        , mGeneric(aGeneric)
952
0
    {
953
0
    }
954
    gfxFontFamily* mFamily;
955
    mozilla::FontFamilyType mGeneric;
956
};
957
958
#endif