1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef GFX_FT2FONTLIST_H
7 #define GFX_FT2FONTLIST_H
8 
9 #include "mozilla/MemoryReporting.h"
10 #include "gfxFT2FontBase.h"
11 #include "gfxPlatformFontList.h"
12 
13 namespace mozilla {
14 namespace dom {
15 class SystemFontListEntry;
16 };
17 };  // namespace mozilla
18 
19 class FontNameCache;
20 typedef struct FT_FaceRec_* FT_Face;
21 class nsZipArchive;
22 class WillShutdownObserver;
23 class FTUserFontData;
24 
25 class FT2FontEntry final : public gfxFT2FontEntryBase {
26   using FontListEntry = mozilla::dom::SystemFontListEntry;
27 
28  public:
FT2FontEntry(const nsACString & aFaceName)29   explicit FT2FontEntry(const nsACString& aFaceName)
30       : gfxFT2FontEntryBase(aFaceName), mFTFontIndex(0) {}
31 
32   ~FT2FontEntry();
33 
34   gfxFontEntry* Clone() const override;
35 
GetName()36   const nsCString& GetName() const { return Name(); }
37 
38   // create a font entry for a downloaded font
39   static FT2FontEntry* CreateFontEntry(
40       const nsACString& aFontName, WeightRange aWeight, StretchRange aStretch,
41       SlantStyleRange aStyle, const uint8_t* aFontData, uint32_t aLength);
42 
43   // create a font entry representing an installed font, identified by
44   // a FontListEntry; the freetype and cairo faces will not be instantiated
45   // until actually needed
46   static FT2FontEntry* CreateFontEntry(const FontListEntry& aFLE);
47 
48   // Create a font entry with the given name; if it is an installed font,
49   // also record the filename and index.
50   // If a non-null harfbuzz face is passed, also set style/weight/stretch
51   // properties of the entry from the values in the face.
52   static FT2FontEntry* CreateFontEntry(const nsACString& aName,
53                                        const char* aFilename, uint8_t aIndex,
54                                        const hb_face_t* aFace);
55 
56   gfxFont* CreateFontInstance(const gfxFontStyle* aStyle) override;
57 
58   nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override;
59 
60   hb_blob_t* GetFontTable(uint32_t aTableTag) override;
61 
62   nsresult CopyFontTable(uint32_t aTableTag,
63                          nsTArray<uint8_t>& aBuffer) override;
64 
65   bool HasVariations() override;
66   void GetVariationAxes(
67       nsTArray<gfxFontVariationAxis>& aVariationAxes) override;
68   void GetVariationInstances(
69       nsTArray<gfxFontVariationInstance>& aInstances) override;
70 
71   // Check for various kinds of brokenness, and set flags on the entry
72   // accordingly so that we avoid using bad font tables
73   void CheckForBrokenFont(gfxFontFamily* aFamily);
74   void CheckForBrokenFont(const nsACString& aFamilyKey);
75 
76   already_AddRefed<mozilla::gfx::SharedFTFace> GetFTFace(bool aCommit = false);
77   FTUserFontData* GetUserFontData();
78 
79   FT_MM_Var* GetMMVar() override;
80 
81   /**
82    * Append this face's metadata to aFaceList for storage in the FontNameCache
83    * (for faster startup).
84    * The aPSName and aFullName parameters here can in principle be empty,
85    * but if they are missing for a given face then src:local() lookups will
86    * not be able to find it when the shared font list is in use.
87    */
88   void AppendToFaceList(nsCString& aFaceList, const nsACString& aFamilyName,
89                         const nsACString& aPSName, const nsACString& aFullName,
90                         FontVisibility aVisibility);
91 
92   void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
93                               FontListSizes* aSizes) const override;
94   void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
95                               FontListSizes* aSizes) const override;
96 
97   RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
98 
99   FT_MM_Var* mMMVar = nullptr;
100 
101   nsCString mFilename;
102   uint8_t mFTFontIndex;
103 
104   mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontFreeType> mUnscaledFont;
105 
106   bool mHasVariations = false;
107   bool mHasVariationsInitialized = false;
108   bool mMMVarInitialized = false;
109 };
110 
111 class FT2FontFamily final : public gfxFontFamily {
112   using FontListEntry = mozilla::dom::SystemFontListEntry;
113 
114  public:
FT2FontFamily(const nsACString & aName,FontVisibility aVisibility)115   explicit FT2FontFamily(const nsACString& aName, FontVisibility aVisibility)
116       : gfxFontFamily(aName, aVisibility) {}
117 
118   // Append this family's faces to the IPC fontlist
119   void AddFacesToFontList(nsTArray<FontListEntry>* aFontList);
120 };
121 
122 class gfxFT2FontList final : public gfxPlatformFontList {
123   using FontListEntry = mozilla::dom::SystemFontListEntry;
124 
125  public:
126   gfxFT2FontList();
127   virtual ~gfxFT2FontList();
128 
129   gfxFontEntry* CreateFontEntry(
130       mozilla::fontlist::Face* aFace,
131       const mozilla::fontlist::Family* aFamily) override;
132 
133   gfxFontEntry* LookupLocalFont(const nsACString& aFontName,
134                                 WeightRange aWeightForEntry,
135                                 StretchRange aStretchForEntry,
136                                 SlantStyleRange aStyleForEntry) override;
137 
138   gfxFontEntry* MakePlatformFont(const nsACString& aFontName,
139                                  WeightRange aWeightForEntry,
140                                  StretchRange aStretchForEntry,
141                                  SlantStyleRange aStyleForEntry,
142                                  const uint8_t* aFontData,
143                                  uint32_t aLength) override;
144 
145   void WriteCache();
146 
147   void ReadSystemFontList(nsTArray<FontListEntry>* aList);
148 
PlatformFontList()149   static gfxFT2FontList* PlatformFontList() {
150     return static_cast<gfxFT2FontList*>(
151         gfxPlatformFontList::PlatformFontList());
152   }
153 
154   gfxFontFamily* CreateFontFamily(const nsACString& aName,
155                                   FontVisibility aVisibility) const override;
156 
157   void WillShutdown();
158 
159  protected:
160   typedef enum { kUnknown, kStandard } StandardFile;
161 
162   // initialize font lists
163   nsresult InitFontListForPlatform() override;
164 
165   void AppendFaceFromFontListEntry(const FontListEntry& aFLE,
166                                    StandardFile aStdFile);
167 
168   void AppendFacesFromBlob(const nsCString& aFileName, StandardFile aStdFile,
169                            hb_blob_t* aBlob, FontNameCache* aCache,
170                            uint32_t aTimestamp, uint32_t aFilesize);
171 
172   void AppendFacesFromFontFile(const nsCString& aFileName,
173                                FontNameCache* aCache, StandardFile aStdFile);
174 
175   void AppendFacesFromOmnijarEntry(nsZipArchive* aReader,
176                                    const nsCString& aEntryName,
177                                    FontNameCache* aCache, bool aJarChanged);
178 
179   void InitSharedFontListForPlatform() override;
180   void CollectInitData(const FontListEntry& aFLE, const nsCString& aPSName,
181                        const nsCString& aFullName, StandardFile aStdFile);
182 
183   /**
184    * Callback passed to AppendFacesFromCachedFaceList to collect family/face
185    * information in either the unshared or shared list we're building.
186    */
187   typedef void (*CollectFunc)(const FontListEntry& aFLE,
188                               const nsCString& aPSName,
189                               const nsCString& aFullName,
190                               StandardFile aStdFile);
191 
192   /**
193    * Append faces from the face-list record for a specific file.
194    * aCollectFace is a callback that will store the face(s) in either the
195    * unshared mFontFamilies list or the mFamilyInitData/mFaceInitData tables
196    * that will be used to initialize the shared list.
197    * Returns true if it is able to read at least one face entry; false if no
198    * usable face entry was found.
199    */
200   bool AppendFacesFromCachedFaceList(CollectFunc aCollectFace,
201                                      const nsCString& aFileName,
202                                      const nsCString& aFaceList,
203                                      StandardFile aStdFile);
204 
205   void AddFaceToList(const nsCString& aEntryName, uint32_t aIndex,
206                      StandardFile aStdFile, hb_face_t* aFace,
207                      nsCString& aFaceList);
208 
209   void FindFonts();
210 
211   void FindFontsInOmnijar(FontNameCache* aCache);
212 
213   void FindFontsInDir(const nsCString& aDir, FontNameCache* aFNC);
214 
215   FontFamily GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override;
216 
217   nsTHashtable<nsCStringHashKey> mSkipSpaceLookupCheckFamilies;
218 
219  private:
220   mozilla::UniquePtr<FontNameCache> mFontNameCache;
221   int64_t mJarModifiedTime;
222   RefPtr<WillShutdownObserver> mObserver;
223 
224   nsTArray<mozilla::fontlist::Family::InitData> mFamilyInitData;
225   nsClassHashtable<nsCStringHashKey,
226                    nsTArray<mozilla::fontlist::Face::InitData>>
227       mFaceInitData;
228 };
229 
230 #endif /* GFX_FT2FONTLIST_H */
231