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"
11 class gfxCharacterMap
;
13 struct GlobalFontMatch
;
18 class FontList
; // See the separate SharedFontList-impl.h header
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.
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;
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
); }
55 * Check if a Pointer has the null value.
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
; }
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.
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;
82 T
* ToPtr(FontList
* aFontList
) const {
83 return static_cast<T
*>(ToPtr(aFontList
, sizeof(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
);
96 Pointer
& operator=(Pointer
&& aOther
) {
97 mBlockAndOffset
.store(aOther
.mBlockAndOffset
);
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.
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.
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(); }
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).
167 // Data required to initialize a Face
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
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
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
);
206 #ifdef MOZ_WIDGET_GTK
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.
224 static constexpr uint32_t kNoIndex
= uint32_t(-1);
226 // Data required to initialize a Family
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
241 mVisibility(aVisibility
),
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
;
255 FontVisibility mVisibility
;
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.
270 // Indexes into mFaces for families where mIsSimple is true
271 kRegularFaceIndex
= 0,
273 kItalicFaceIndex
= 2,
274 kBoldItalicFaceIndex
= 3,
275 // mask values for selecting face with bold and/or italic attributes
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());
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;
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
;
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].
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.
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;
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 */