summaryrefslogtreecommitdiff
path: root/gfx/thebes/gfxFcPlatformFontList.h
blob: 1bc35021e50ecdb4caa9be5a415c942a1fb7e7e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef GFXFCPLATFORMFONTLIST_H_
#define GFXFCPLATFORMFONTLIST_H_

#include "gfxFont.h"
#include "gfxFontEntry.h"
#include "gfxFT2FontBase.h"
#include "gfxPlatformFontList.h"
#include "mozilla/mozalloc.h"
#include "nsClassHashtable.h"

#include <fontconfig/fontconfig.h>
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_TRUETYPE_TABLES_H
#include <cairo.h>
#include <cairo-ft.h>

#include "gfxFontconfigUtils.h" // xxx - only for nsAutoRefTraits<FcPattern>, etc.

template <>
class nsAutoRefTraits<FcObjectSet> : public nsPointerRefTraits<FcObjectSet>
{
public:
    static void Release(FcObjectSet *ptr) { FcObjectSetDestroy(ptr); }
};

template <>
class nsAutoRefTraits<FcConfig> : public nsPointerRefTraits<FcConfig>
{
public:
    static void Release(FcConfig *ptr) { FcConfigDestroy(ptr); }
    static void AddRef(FcConfig *ptr) { FcConfigReference(ptr); }
};

// Helper classes used for clearning out user font data when cairo font
// face is destroyed. Since multiple faces may use the same data, be
// careful to assure that the data is only cleared out when all uses
// expire. The font entry object contains a refptr to FTUserFontData and
// each cairo font created from that font entry contains a
// FTUserFontDataRef with a refptr to that same FTUserFontData object.

class FTUserFontData {
public:
    NS_INLINE_DECL_REFCOUNTING(FTUserFontData)

    explicit FTUserFontData(FT_Face aFace, const uint8_t* aData)
        : mFace(aFace), mFontData(aData)
    {
    }

    const uint8_t *FontData() const { return mFontData; }

private:
    ~FTUserFontData()
    {
        FT_Done_Face(mFace);
        if (mFontData) {
            NS_Free((void*)mFontData);
        }
    }

    FT_Face        mFace;
    const uint8_t *mFontData;
};

class FTUserFontDataRef {
public:
    explicit FTUserFontDataRef(FTUserFontData *aUserFontData)
        : mUserFontData(aUserFontData)
    {
    }

    static void Destroy(void* aData) {
        FTUserFontDataRef* aUserFontDataRef =
            static_cast<FTUserFontDataRef*>(aData);
        delete aUserFontDataRef;
    }

private:
    RefPtr<FTUserFontData> mUserFontData;
};

// The names for the font entry and font classes should really
// the common 'Fc' abbreviation but the gfxPangoFontGroup code already
// defines versions of these, so use the verbose name for now.

class gfxFontconfigFontEntry : public gfxFontEntry {
public:
    // used for system fonts with explicit patterns
    explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
                                    FcPattern* aFontPattern,
                                    bool aIgnoreFcCharmap);

    // used for data fonts where the fontentry takes ownership
    // of the font data and the FT_Face
    explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
                                    uint16_t aWeight,
                                    int16_t aStretch,
                                    uint8_t aStyle,
                                    const uint8_t *aData,
                                    FT_Face aFace);

    // used for @font-face local system fonts with explicit patterns
    explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
                                    FcPattern* aFontPattern,
                                    uint16_t aWeight,
                                    int16_t aStretch,
                                    uint8_t aStyle);

    FcPattern* GetPattern() { return mFontPattern; }

    bool SupportsLangGroup(nsIAtom *aLangGroup) const override;

    nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override;
    bool TestCharacterMap(uint32_t aCh) override;

    hb_blob_t* GetFontTable(uint32_t aTableTag) override;

    void ForgetHBFace() override;
    void ReleaseGrFace(gr_face* aFace) override;

    double GetAspect();

protected:
    virtual ~gfxFontconfigFontEntry();

    gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
                                bool aNeedsBold) override;

    // helper method for creating cairo font from pattern
    cairo_scaled_font_t*
    CreateScaledFont(FcPattern* aRenderPattern,
                     gfxFloat aAdjustedSize,
                     const gfxFontStyle *aStyle,
                     bool aNeedsBold);

    // override to pull data from FTFace
    virtual nsresult
    CopyFontTable(uint32_t aTableTag,
                  nsTArray<uint8_t>& aBuffer) override;

    // if HB or GR faces are gone, close down the FT_Face
    void MaybeReleaseFTFace();

    // pattern for a single face of a family
    nsCountedRef<FcPattern> mFontPattern;

    // user font data, when needed
    RefPtr<FTUserFontData> mUserFontData;

    // FTFace - initialized when needed
    FT_Face   mFTFace;
    bool      mFTFaceInitialized;

    // Whether TestCharacterMap should check the actual cmap rather than asking
    // fontconfig about character coverage.
    // We do this for app-bundled (rather than system) fonts, as they may
    // include color glyphs that fontconfig would overlook, and for fonts
    // loaded via @font-face.
    bool      mIgnoreFcCharmap;

    double    mAspect;

    // data font
    const uint8_t* mFontData;
};

class gfxFontconfigFontFamily : public gfxFontFamily {
public:
    explicit gfxFontconfigFontFamily(const nsAString& aName) :
        gfxFontFamily(aName),
        mContainsAppFonts(false),
        mHasNonScalableFaces(false)
    { }

    void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) override;

    // Families are constructed initially with just references to patterns.
    // When necessary, these are enumerated within FindStyleVariations.
    void AddFontPattern(FcPattern* aFontPattern);

    void SetFamilyContainsAppFonts(bool aContainsAppFonts)
    {
        mContainsAppFonts = aContainsAppFonts;
    }

    void
    FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
                         nsTArray<gfxFontEntry*>& aFontEntryList,
                         bool& aNeedsSyntheticBold) override;

protected:
    virtual ~gfxFontconfigFontFamily() { }

    nsTArray<nsCountedRef<FcPattern> > mFontPatterns;

    bool      mContainsAppFonts;
    bool      mHasNonScalableFaces;
};

class gfxFontconfigFont : public gfxFontconfigFontBase {
public:
    gfxFontconfigFont(cairo_scaled_font_t *aScaledFont,
                      FcPattern *aPattern,
                      gfxFloat aAdjustedSize,
                      gfxFontEntry *aFontEntry,
                      const gfxFontStyle *aFontStyle,
                      bool aNeedsBold);

protected:
    virtual ~gfxFontconfigFont();
};

class nsILanguageAtomService;

class gfxFcPlatformFontList : public gfxPlatformFontList {
public:
    gfxFcPlatformFontList();

    static gfxFcPlatformFontList* PlatformFontList() {
        return static_cast<gfxFcPlatformFontList*>(sPlatformFontList);
    }

    // initialize font lists
    virtual nsresult InitFontListForPlatform() override;

    void GetFontList(nsIAtom *aLangGroup,
                     const nsACString& aGenericFamily,
                     nsTArray<nsString>& aListOfFonts) override;


    gfxFontEntry*
    LookupLocalFont(const nsAString& aFontName, uint16_t aWeight,
                    int16_t aStretch, uint8_t aStyle) override;

    gfxFontEntry*
    MakePlatformFont(const nsAString& aFontName, uint16_t aWeight,
                     int16_t aStretch,
                     uint8_t aStyle,
                     const uint8_t* aFontData,
                     uint32_t aLength) override;

    bool FindAndAddFamilies(const nsAString& aFamily,
                            nsTArray<gfxFontFamily*>* aOutput,
                            gfxFontStyle* aStyle = nullptr,
                            gfxFloat aDevToCssSize = 1.0) override;

    bool GetStandardFamilyName(const nsAString& aFontName,
                               nsAString& aFamilyName) override;

    FcConfig* GetLastConfig() const { return mLastConfig; }

    // override to use fontconfig lookup for generics
    void AddGenericFonts(mozilla::FontFamilyType aGenericType,
                         nsIAtom* aLanguage,
                         nsTArray<gfxFontFamily*>& aFamilyList) override;

    void ClearLangGroupPrefFonts() override;

    // clear out cached generic-lang ==> family-list mappings
    void ClearGenericMappings() {
        mGenericMappings.Clear();
    }

    static FT_Library GetFTLibrary();

protected:
    virtual ~gfxFcPlatformFontList();

    // Add all the font families found in a font set.
    // aAppFonts indicates whether this is the system or application fontset.
    void AddFontSetFamilies(FcFontSet* aFontSet, bool aAppFonts);

    // figure out which families fontconfig maps a generic to
    // (aGeneric assumed already lowercase)
    PrefFontList* FindGenericFamilies(const nsAString& aGeneric,
                                      nsIAtom* aLanguage);

    // are all pref font settings set to use fontconfig generics?
    bool PrefFontListsUseOnlyGenerics();

    static void CheckFontUpdates(nsITimer *aTimer, void *aThis);

    virtual gfxFontFamily*
    GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override;

#ifdef MOZ_BUNDLED_FONTS
    void ActivateBundledFonts();
    nsCString mBundledFontsPath;
    bool mBundledFontsInitialized;
#endif

    // to avoid enumerating all fonts, maintain a mapping of local font
    // names to family
    nsBaseHashtable<nsStringHashKey,
                    nsCountedRef<FcPattern>,
                    FcPattern*> mLocalNames;

    // caching generic/lang ==> font family list
    nsClassHashtable<nsCStringHashKey,
                     PrefFontList> mGenericMappings;

    // Caching family lookups as found by FindAndAddFamilies after resolving
    // substitutions. The gfxFontFamily objects cached here are owned by the
    // gfxFcPlatformFontList via its mFamilies table; note that if the main
    // font list is rebuilt (e.g. due to a fontconfig configuration change),
    // these pointers will be invalidated. InitFontList() flushes the cache
    // in this case.
    nsDataHashtable<nsCStringHashKey,
                    nsTArray<gfxFontFamily*>> mFcSubstituteCache;

    nsCOMPtr<nsITimer> mCheckFontUpdatesTimer;
    nsCountedRef<FcConfig> mLastConfig;

    // By default, font prefs under Linux are set to simply lookup
    // via fontconfig the appropriate font for serif/sans-serif/monospace.
    // Rather than check each time a font pref is used, check them all at startup
    // and set a boolean to flag the case that non-default user font prefs exist
    // Note: langGroup == x-math is handled separately
    bool mAlwaysUseFontconfigGenerics;

    static FT_Library sCairoFTLibrary;
};

#endif /* GFXPLATFORMFONTLIST_H_ */