Bug 1885489 - Part 9: Add SnapshotIterator::readObject(). r=iain
[gecko.git] / gfx / thebes / SharedFontList.h
blob59ac223efee719a8eaa6de94e9a521213d4057ec
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef SharedFontList_h
6 #define SharedFontList_h
8 #include "gfxFontEntry.h"
9 #include <atomic>
11 class gfxCharacterMap;
12 struct gfxFontStyle;
13 struct GlobalFontMatch;
15 namespace mozilla {
16 namespace fontlist {
18 class FontList; // See the separate SharedFontList-impl.h header
20 /**
21 * A Pointer in the shared font list contains a packed index/offset pair,
22 * with a 12-bit index into the array of shared-memory blocks, and a 20-bit
23 * offset into the block.
24 * The maximum size of each block is therefore 2^20 bytes (1 MB) if sub-parts
25 * of the block are to be allocated; however, a larger block (up to 2^32 bytes)
26 * can be created and used as a single allocation if necessary.
28 struct Pointer {
29 private:
30 friend class FontList;
31 static const uint32_t kIndexBits = 12u;
32 static const uint32_t kBlockShift = 20u;
33 static_assert(kIndexBits + kBlockShift == 32u, "bad Pointer bit count");
35 static const uint32_t kNullValue = 0xffffffffu;
36 static const uint32_t kOffsetMask = (1u << kBlockShift) - 1;
38 public:
39 static Pointer Null() { return Pointer(); }
41 Pointer() : mBlockAndOffset(kNullValue) {}
43 Pointer(uint32_t aBlock, uint32_t aOffset)
44 : mBlockAndOffset((aBlock << kBlockShift) | aOffset) {
45 MOZ_ASSERT(aBlock < (1u << kIndexBits) && aOffset < (1u << kBlockShift));
48 Pointer(const Pointer& aOther) {
49 mBlockAndOffset.store(aOther.mBlockAndOffset);
52 Pointer(Pointer&& aOther) { mBlockAndOffset.store(aOther.mBlockAndOffset); }
54 /**
55 * Check if a Pointer has the null value.
57 * NOTE!
58 * In a child process, it is possible that conversion to a "real" pointer
59 * using ToPtr() will fail even when IsNull() is false, so calling code
60 * that may run in child processes must be prepared to handle this.
62 bool IsNull() const { return mBlockAndOffset == kNullValue; }
64 uint32_t Block() const { return mBlockAndOffset >> kBlockShift; }
66 uint32_t Offset() const { return mBlockAndOffset & kOffsetMask; }
68 /**
69 * Convert a fontlist::Pointer to a standard C++ pointer. This requires the
70 * FontList, which will know where the shared memory block is mapped in
71 * the current process's address space.
73 * aSize is the expected size of the pointed-to object, for bounds checking.
75 * NOTE!
76 * In child processes this may fail and return nullptr, even if IsNull() is
77 * false, in cases where the font list is in the process of being rebuilt.
79 void* ToPtr(FontList* aFontList, size_t aSize) const;
81 template <typename T>
82 T* ToPtr(FontList* aFontList) const {
83 return static_cast<T*>(ToPtr(aFontList, sizeof(T)));
86 template <typename T>
87 T* ToArray(FontList* aFontList, size_t aCount) const {
88 return static_cast<T*>(ToPtr(aFontList, sizeof(T) * aCount));
91 Pointer& operator=(const Pointer& aOther) {
92 mBlockAndOffset.store(aOther.mBlockAndOffset);
93 return *this;
96 Pointer& operator=(Pointer&& aOther) {
97 mBlockAndOffset.store(aOther.mBlockAndOffset);
98 return *this;
101 // We store the block index and the offset within the block as a single
102 // atomic 32-bit value so we can safely modify a Pointer without other
103 // processes seeing a broken (partially-updated) value.
104 std::atomic<uint32_t> mBlockAndOffset;
108 * Family and face names are stored as String records, which hold a length
109 * (in utf-8 code units) and a Pointer to the string's UTF-8 characters.
111 struct String {
112 String() : mPointer(Pointer::Null()), mLength(0) {}
114 String(FontList* aList, const nsACString& aString)
115 : mPointer(Pointer::Null()) {
116 Assign(aString, aList);
119 const nsCString AsString(FontList* aList) const {
120 MOZ_ASSERT(!mPointer.IsNull());
121 // It's tempting to use AssignLiteral here so that we get an nsCString that
122 // simply wraps the character data in the shmem block without needing to
123 // allocate or copy. But that's unsafe because in the event of font-list
124 // reinitalization, that shared memory will be unmapped; then any copy of
125 // the nsCString that may still be around will crash if accessed.
126 return nsCString(mPointer.ToArray<const char>(aList, mLength), mLength);
129 void Assign(const nsACString& aString, FontList* aList);
131 const char* BeginReading(FontList* aList) const {
132 MOZ_ASSERT(!mPointer.IsNull());
133 auto* str = mPointer.ToArray<const char>(aList, mLength);
134 return str ? str : "";
137 uint32_t Length() const { return mLength; }
140 * Return whether the String has been set to a value.
142 * NOTE!
143 * In a child process, accessing the value could fail even if IsNull()
144 * returned false. In this case, the nsCString constructor used by AsString()
145 * will be passed a null pointer, and return an empty string despite the
146 * non-zero Length() recorded here.
148 bool IsNull() const { return mPointer.IsNull(); }
150 private:
151 Pointer mPointer;
152 uint32_t mLength;
156 * A Face record represents an individual font resource; it has the style
157 * properties needed for font matching, as well as a pointer to a character
158 * map that records the supported character set. This may be Null if we have
159 * not yet loaded the data.
160 * The mDescriptor and mIndex fields provide the information needed to
161 * instantiate a (platform-specific) font reference that can be used with
162 * platform font APIs; their content depends on the requirements of the
163 * platform APIs (e.g. font PostScript name, file pathname, serialized
164 * fontconfig pattern, etc).
166 struct Face {
167 // Data required to initialize a Face
168 struct InitData {
169 nsCString mDescriptor; // descriptor that can be used to instantiate a
170 // platform font reference
171 uint16_t mIndex; // an index used with descriptor (on some platforms)
172 #ifdef MOZ_WIDGET_GTK
173 uint16_t mSize; // pixel size if bitmap; zero indicates scalable
174 #endif
175 bool mFixedPitch; // is the face fixed-pitch (monospaced)?
176 mozilla::WeightRange mWeight; // CSS font-weight value
177 mozilla::StretchRange mStretch; // CSS font-stretch value
178 mozilla::SlantStyleRange mStyle; // CSS font-style value
179 RefPtr<gfxCharacterMap> mCharMap; // character map, or null if not loaded
182 // Note that mCharacterMap is not set from the InitData by this constructor;
183 // the caller must use SetCharacterMap to handle that separately if required.
184 Face(FontList* aList, const InitData& aData)
185 : mDescriptor(aList, aData.mDescriptor),
186 mIndex(aData.mIndex),
187 #ifdef MOZ_WIDGET_GTK
188 mSize(aData.mSize),
189 #endif
190 mFixedPitch(aData.mFixedPitch),
191 mWeight(aData.mWeight),
192 mStretch(aData.mStretch),
193 mStyle(aData.mStyle),
194 mCharacterMap(Pointer::Null()) {
197 bool HasValidDescriptor() const {
198 return !mDescriptor.IsNull() && mIndex != uint16_t(-1);
201 void SetCharacterMap(FontList* aList, gfxCharacterMap* aCharMap,
202 const Family* aFamily);
204 String mDescriptor;
205 uint16_t mIndex;
206 #ifdef MOZ_WIDGET_GTK
207 uint16_t mSize;
208 #endif
209 bool mFixedPitch;
210 mozilla::WeightRange mWeight;
211 mozilla::StretchRange mStretch;
212 mozilla::SlantStyleRange mStyle;
213 Pointer mCharacterMap;
217 * A Family record represents an available (installed) font family; it has
218 * a name (for display purposes) and a key (lowercased, for case-insensitive
219 * lookups), as well as a pointer to an array of Faces. Depending on the
220 * platform, the array of faces may be lazily initialized the first time we
221 * want to use the family.
223 struct Family {
224 static constexpr uint32_t kNoIndex = uint32_t(-1);
226 // Data required to initialize a Family
227 struct InitData {
228 InitData(const nsACString& aKey, // lookup key (lowercased)
229 const nsACString& aName, // display name
230 uint32_t aIndex = kNoIndex, // [win] system collection index
231 FontVisibility aVisibility = FontVisibility::Unknown,
232 bool aBundled = false, // [win] font was bundled with the app
233 // rather than system-installed
234 bool aBadUnderline = false, // underline-position in font is bad
235 bool aForceClassic = false, // [win] use "GDI classic" rendering
236 bool aAltLocale = false // font is alternate localized family
238 : mKey(aKey),
239 mName(aName),
240 mIndex(aIndex),
241 mVisibility(aVisibility),
242 mBundled(aBundled),
243 mBadUnderline(aBadUnderline),
244 mForceClassic(aForceClassic),
245 mAltLocale(aAltLocale) {}
246 bool operator<(const InitData& aRHS) const { return mKey < aRHS.mKey; }
247 bool operator==(const InitData& aRHS) const {
248 return mKey == aRHS.mKey && mName == aRHS.mName &&
249 mVisibility == aRHS.mVisibility && mBundled == aRHS.mBundled &&
250 mBadUnderline == aRHS.mBadUnderline;
252 nsCString mKey;
253 nsCString mName;
254 uint32_t mIndex;
255 FontVisibility mVisibility;
256 bool mBundled;
257 bool mBadUnderline;
258 bool mForceClassic;
259 bool mAltLocale;
263 * Font families are considered "simple" if they contain only 4 faces with
264 * style attributes corresponding to Regular, Bold, Italic, and BoldItalic
265 * respectively, or a subset of these (e.g. only Regular and Bold). In this
266 * case, the faces are stored at predefined positions in the mFaces array,
267 * and a simplified (faster) style-matching algorithm can be used.
269 enum {
270 // Indexes into mFaces for families where mIsSimple is true
271 kRegularFaceIndex = 0,
272 kBoldFaceIndex = 1,
273 kItalicFaceIndex = 2,
274 kBoldItalicFaceIndex = 3,
275 // mask values for selecting face with bold and/or italic attributes
276 kBoldMask = 0x01,
277 kItalicMask = 0x02
280 Family(FontList* aList, const InitData& aData);
282 void AddFaces(FontList* aList, const nsTArray<Face::InitData>& aFaces);
284 void SetFacePtrs(FontList* aList, nsTArray<Pointer>& aFaces);
286 const String& Key() const { return mKey; }
288 const String& DisplayName() const { return mName; }
290 uint32_t Index() const { return mIndex; }
291 bool IsBundled() const { return mIsBundled; }
293 uint32_t NumFaces() const {
294 MOZ_ASSERT(IsInitialized());
295 return mFaceCount;
298 Pointer* Faces(FontList* aList) const {
299 MOZ_ASSERT(IsInitialized());
300 return mFaces.ToArray<Pointer>(aList, mFaceCount);
303 FontVisibility Visibility() const { return mVisibility; }
304 bool IsHidden() const { return Visibility() == FontVisibility::Hidden; }
306 bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
307 bool IsForceClassic() const { return mIsForceClassic; }
308 bool IsSimple() const { return mIsSimple; }
309 bool IsAltLocaleFamily() const { return mIsAltLocale; }
311 // IsInitialized indicates whether the family has been populated with faces,
312 // and is therefore ready to use.
313 // It is possible that character maps have not yet been loaded.
314 bool IsInitialized() const { return !mFaces.IsNull(); }
316 // IsFullyInitialized indicates that not only faces but also character maps
317 // have been set up, so the family can be searched without the possibility
318 // that IPC messaging will be triggered.
319 bool IsFullyInitialized() const {
320 return IsInitialized() && !mCharacterMap.IsNull();
323 void FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
324 nsTArray<Face*>& aFaceList,
325 bool aIgnoreSizeTolerance = false) const;
327 Face* FindFaceForStyle(FontList* aList, const gfxFontStyle& aStyle,
328 bool aIgnoreSizeTolerance = false) const;
330 void SearchAllFontsForChar(FontList* aList, GlobalFontMatch* aMatchData);
332 void SetupFamilyCharMap(FontList* aList);
334 // Return the index of this family in the font-list's Families() or
335 // AliasFamilies() list, and which of those it belongs to.
336 // Returns Nothing if the family cannot be found.
337 mozilla::Maybe<std::pair<uint32_t, bool>> FindIndex(FontList* aList) const;
339 private:
340 // Returns true if there are specifically-sized bitmap faces in the list,
341 // so size selection still needs to be done. (Currently only on Linux.)
342 bool FindAllFacesForStyleInternal(FontList* aList, const gfxFontStyle& aStyle,
343 nsTArray<Face*>& aFaceList) const;
345 std::atomic<uint32_t> mFaceCount;
346 String mKey;
347 String mName;
348 Pointer mCharacterMap; // If non-null, union of character coverage of all
349 // faces in the family
350 Pointer mFaces; // Pointer to array of |mFaceCount| face pointers
351 uint32_t mIndex; // [win] Top bit set indicates app-bundled font family
352 FontVisibility mVisibility;
353 bool mIsSimple; // family allows simplified style matching: mFaces contains
354 // exactly 4 entries [Regular, Bold, Italic, BoldItalic].
355 bool mIsBundled : 1;
356 bool mIsBadUnderlineFamily : 1;
357 bool mIsForceClassic : 1;
358 bool mIsAltLocale : 1;
362 * For platforms where we build an index of local font face names (PS-name
363 * and fullname of the font) to support @font-face{src:local(...)}, we map
364 * each face name to an index into the family list, and an index into the
365 * family's list of faces.
367 struct LocalFaceRec {
369 * The InitData struct needs to record the family name rather than index,
370 * as we may be collecting these records at the same time as building the
371 * family list, so we don't yet know the final family index.
372 * Likewise, in some cases we don't know the final face index because the
373 * faces may be re-sorted to fit into predefined positions in a "simple"
374 * family (if we're reading names before the family has been fully set up).
375 * In that case, we'll store uint32_t(-1) as mFaceIndex, and record the
376 * string descriptor instead.
377 * When actually recorded in the FontList's mLocalFaces array, the family
378 * will be stored as a simple index into the mFamilies array, and the face
379 * as an index into the family's mFaces.
381 struct InitData {
382 nsCString mFamilyName;
383 nsCString mFaceDescriptor;
384 uint32_t mFaceIndex = uint32_t(-1);
385 InitData(const nsACString& aFamily, const nsACString& aFace)
386 : mFamilyName(aFamily), mFaceDescriptor(aFace) {}
387 InitData(const nsACString& aFamily, uint32_t aFaceIndex)
388 : mFamilyName(aFamily), mFaceIndex(aFaceIndex) {}
389 InitData() = default;
391 String mKey;
392 uint32_t mFamilyIndex; // Index into the font list's Families array
393 uint32_t mFaceIndex; // Index into the family's Faces array
396 } // namespace fontlist
397 } // namespace mozilla
399 #undef ERROR // This is defined via Windows.h, but conflicts with some bindings
400 // code when this gets included in the same compilation unit.
402 #endif /* SharedFontList_h */