зеркало из https://github.com/mozilla/gecko-dev.git
339 строки
12 KiB
C++
339 строки
12 KiB
C++
/* 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 SharedFontList_h
|
|
#define SharedFontList_h
|
|
|
|
#include "gfxFontEntry.h"
|
|
#include <atomic>
|
|
|
|
class gfxCharacterMap;
|
|
struct gfxFontStyle;
|
|
struct GlobalFontMatch;
|
|
|
|
namespace mozilla {
|
|
namespace fontlist {
|
|
|
|
class FontList; // See the separate SharedFontList-impl.h header
|
|
|
|
/**
|
|
* A Pointer in the shared font list contains a packed index/offset pair,
|
|
* with a 12-bit index into the array of shared-memory blocks, and a 20-bit
|
|
* offset into the block.
|
|
* The maximum size of each block is therefore 2^20 bytes (1048576).
|
|
*/
|
|
struct Pointer {
|
|
private:
|
|
friend class FontList;
|
|
static const uint32_t kIndexBits = 12u;
|
|
static const uint32_t kBlockShift = 20u;
|
|
static_assert(kIndexBits + kBlockShift == 32u, "bad Pointer bit count");
|
|
|
|
static const uint32_t kNullValue = 0xffffffffu;
|
|
static const uint32_t kOffsetMask = (1u << kBlockShift) - 1;
|
|
|
|
public:
|
|
static Pointer Null() { return Pointer(); }
|
|
|
|
Pointer() : mBlockAndOffset(kNullValue) {}
|
|
|
|
Pointer(uint32_t aBlock, uint32_t aOffset)
|
|
: mBlockAndOffset((aBlock << kBlockShift) | aOffset) {
|
|
MOZ_ASSERT(aBlock < (1u << kIndexBits) && aOffset < (1u << kBlockShift));
|
|
}
|
|
|
|
Pointer(const Pointer& aOther) {
|
|
mBlockAndOffset.store(aOther.mBlockAndOffset);
|
|
}
|
|
|
|
Pointer(Pointer&& aOther) { mBlockAndOffset.store(aOther.mBlockAndOffset); }
|
|
|
|
bool IsNull() const { return mBlockAndOffset == kNullValue; }
|
|
|
|
uint32_t Block() const { return mBlockAndOffset >> kBlockShift; }
|
|
|
|
uint32_t Offset() const { return mBlockAndOffset & kOffsetMask; }
|
|
|
|
/**
|
|
* Convert a fontlist::Pointer to a standard C++ pointer. This requires the
|
|
* FontList, which will know where the shared memory block is mapped in
|
|
* the current process's address space.
|
|
*/
|
|
void* ToPtr(FontList* aFontList) const;
|
|
|
|
Pointer& operator=(const Pointer& aOther) {
|
|
mBlockAndOffset.store(aOther.mBlockAndOffset);
|
|
return *this;
|
|
}
|
|
|
|
Pointer& operator=(Pointer&& aOther) {
|
|
mBlockAndOffset.store(aOther.mBlockAndOffset);
|
|
return *this;
|
|
}
|
|
|
|
// We store the block index and the offset within the block as a single
|
|
// atomic 32-bit value so we can safely modify a Pointer without other
|
|
// processes seeing a broken (partially-updated) value.
|
|
std::atomic<uint32_t> mBlockAndOffset;
|
|
};
|
|
|
|
/**
|
|
* Family and face names are stored as String records, which hold a length
|
|
* (in utf-8 code units) and a Pointer to the string's UTF-8 characters.
|
|
*/
|
|
struct String {
|
|
String() : mPointer(Pointer::Null()), mLength(0) {}
|
|
|
|
String(FontList* aList, const nsACString& aString)
|
|
: mPointer(Pointer::Null()) {
|
|
Assign(aString, aList);
|
|
}
|
|
|
|
const nsCString AsString(FontList* aList) const {
|
|
MOZ_ASSERT(!mPointer.IsNull());
|
|
// It's tempting to use AssignLiteral here so that we get an nsCString that
|
|
// simply wraps the character data in the shmem block without needing to
|
|
// allocate or copy. But that's unsafe because in the event of font-list
|
|
// reinitalization, that shared memory will be unmapped; then any copy of
|
|
// the nsCString that may still be around will crash if accessed.
|
|
return nsCString(static_cast<const char*>(mPointer.ToPtr(aList)), mLength);
|
|
}
|
|
|
|
void Assign(const nsACString& aString, FontList* aList);
|
|
|
|
const char* BeginReading(FontList* aList) const {
|
|
MOZ_ASSERT(!mPointer.IsNull());
|
|
return static_cast<const char*>(mPointer.ToPtr(aList));
|
|
}
|
|
|
|
uint32_t Length() const { return mLength; }
|
|
|
|
bool IsNull() const { return mPointer.IsNull(); }
|
|
|
|
private:
|
|
Pointer mPointer;
|
|
uint32_t mLength;
|
|
};
|
|
|
|
/**
|
|
* A Face record represents an individual font resource; it has the style
|
|
* properties needed for font matching, as well as a pointer to a character
|
|
* map that records the supported character set. This may be Null if we have
|
|
* not yet loaded the data.
|
|
* The mDescriptor and mIndex fields provide the information needed to
|
|
* instantiate a (platform-specific) font reference that can be used with
|
|
* platform font APIs; their content depends on the requirements of the
|
|
* platform APIs (e.g. font PostScript name, file pathname, serialized
|
|
* fontconfig pattern, etc).
|
|
*/
|
|
struct Face {
|
|
// Data required to initialize a Face
|
|
struct InitData {
|
|
nsCString mDescriptor; // descriptor that can be used to instantiate a
|
|
// platform font reference
|
|
uint16_t mIndex; // an index used with descriptor (on some platforms)
|
|
bool mFixedPitch; // is the face fixed-pitch (monospaced)?
|
|
mozilla::WeightRange mWeight; // CSS font-weight value
|
|
mozilla::StretchRange mStretch; // CSS font-stretch value
|
|
mozilla::SlantStyleRange mStyle; // CSS font-style value
|
|
};
|
|
|
|
Face(FontList* aList, const InitData& aData)
|
|
: mDescriptor(aList, aData.mDescriptor),
|
|
mIndex(aData.mIndex),
|
|
mFixedPitch(aData.mFixedPitch),
|
|
mWeight(aData.mWeight),
|
|
mStretch(aData.mStretch),
|
|
mStyle(aData.mStyle),
|
|
mCharacterMap(Pointer::Null()) {}
|
|
|
|
bool HasValidDescriptor() const {
|
|
return !mDescriptor.IsNull() && mIndex != uint16_t(-1);
|
|
}
|
|
|
|
void SetCharacterMap(FontList* aList, gfxCharacterMap* aCharMap);
|
|
|
|
String mDescriptor;
|
|
uint16_t mIndex;
|
|
bool mFixedPitch;
|
|
mozilla::WeightRange mWeight;
|
|
mozilla::StretchRange mStretch;
|
|
mozilla::SlantStyleRange mStyle;
|
|
Pointer mCharacterMap;
|
|
};
|
|
|
|
/**
|
|
* A Family record represents an available (installed) font family; it has
|
|
* a name (for display purposes) and a key (lowercased, for case-insensitive
|
|
* lookups), as well as a pointer to an array of Faces. Depending on the
|
|
* platform, the array of faces may be lazily initialized the first time we
|
|
* want to use the family.
|
|
*/
|
|
struct Family {
|
|
// Data required to initialize a Family
|
|
struct InitData {
|
|
InitData(const nsACString& aKey, // lookup key (lowercased)
|
|
const nsACString& aName, // display name
|
|
uint32_t aIndex = 0, // [win] index in the system font collection
|
|
FontVisibility aVisibility = FontVisibility::Unknown,
|
|
bool aBundled = false, // [win] font was bundled with the app
|
|
// rather than system-installed
|
|
bool aBadUnderline = false, // underline-position in font is bad
|
|
bool aForceClassic = false // [win] use "GDI classic" rendering
|
|
)
|
|
: mKey(aKey),
|
|
mName(aName),
|
|
mIndex(aIndex),
|
|
mVisibility(aVisibility),
|
|
mBundled(aBundled),
|
|
mBadUnderline(aBadUnderline),
|
|
mForceClassic(aForceClassic) {}
|
|
bool operator<(const InitData& aRHS) const { return mKey < aRHS.mKey; }
|
|
bool operator==(const InitData& aRHS) const {
|
|
return mKey == aRHS.mKey && mName == aRHS.mName &&
|
|
mVisibility == aRHS.mVisibility && mBundled == aRHS.mBundled &&
|
|
mBadUnderline == aRHS.mBadUnderline;
|
|
}
|
|
const nsCString mKey;
|
|
const nsCString mName;
|
|
uint32_t mIndex;
|
|
FontVisibility mVisibility;
|
|
bool mBundled;
|
|
bool mBadUnderline;
|
|
bool mForceClassic;
|
|
};
|
|
|
|
/**
|
|
* Font families are considered "simple" if they contain only 4 faces with
|
|
* style attributes corresponding to Regular, Bold, Italic, and BoldItalic
|
|
* respectively, or a subset of these (e.g. only Regular and Bold). In this
|
|
* case, the faces are stored at predefined positions in the mFaces array,
|
|
* and a simplified (faster) style-matching algorithm can be used.
|
|
*/
|
|
enum {
|
|
// Indexes into mFaces for families where mIsSimple is true
|
|
kRegularFaceIndex = 0,
|
|
kBoldFaceIndex = 1,
|
|
kItalicFaceIndex = 2,
|
|
kBoldItalicFaceIndex = 3,
|
|
// mask values for selecting face with bold and/or italic attributes
|
|
kBoldMask = 0x01,
|
|
kItalicMask = 0x02
|
|
};
|
|
|
|
Family(FontList* aList, const InitData& aData);
|
|
|
|
void AddFaces(FontList* aList, const nsTArray<Face::InitData>& aFaces);
|
|
|
|
void SetFacePtrs(FontList* aList, nsTArray<Pointer>& aFaces);
|
|
|
|
const String& Key() const { return mKey; }
|
|
|
|
const String& DisplayName() const { return mName; }
|
|
|
|
uint32_t Index() const { return mIndex & 0x7fffffffu; }
|
|
bool IsBundled() const { return mIndex & 0x80000000u; }
|
|
|
|
uint32_t NumFaces() const {
|
|
MOZ_ASSERT(IsInitialized());
|
|
return mFaceCount;
|
|
}
|
|
|
|
Pointer* Faces(FontList* aList) const {
|
|
MOZ_ASSERT(IsInitialized());
|
|
return static_cast<Pointer*>(mFaces.ToPtr(aList));
|
|
}
|
|
|
|
FontVisibility Visibility() const { return mVisibility; }
|
|
bool IsHidden() const { return Visibility() == FontVisibility::Hidden; }
|
|
|
|
bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
|
|
bool IsForceClassic() const { return mIsForceClassic; }
|
|
|
|
bool IsInitialized() const { return !mFaces.IsNull(); }
|
|
|
|
void FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
|
nsTArray<Face*>& aFaceList,
|
|
bool aIgnoreSizeTolerance = false) const;
|
|
|
|
Face* FindFaceForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
|
bool aIgnoreSizeTolerance = false) const;
|
|
|
|
void SearchAllFontsForChar(FontList* aList, GlobalFontMatch* aMatchData);
|
|
|
|
void SetupFamilyCharMap(FontList* aList);
|
|
|
|
private:
|
|
std::atomic<uint32_t> mFaceCount;
|
|
String mKey;
|
|
String mName;
|
|
Pointer mCharacterMap; // If non-null, union of character coverage of all
|
|
// faces in the family
|
|
Pointer mFaces; // Pointer to array of |mFaceCount| face pointers
|
|
uint32_t mIndex; // [win] Top bit set indicates app-bundled font family
|
|
FontVisibility mVisibility;
|
|
bool mIsBadUnderlineFamily;
|
|
bool mIsForceClassic;
|
|
bool mIsSimple; // family allows simplified style matching: mFaces contains
|
|
// exactly 4 entries [Regular, Bold, Italic, BoldItalic].
|
|
};
|
|
|
|
/**
|
|
* For platforms where we build an index of local font face names (PS-name
|
|
* and fullname of the font) to support @font-face{src:local(...)}, we map
|
|
* each face name to an index into the family list, and an index into the
|
|
* family's list of faces.
|
|
*/
|
|
struct LocalFaceRec {
|
|
/**
|
|
* The InitData struct needs to record the family name rather than index,
|
|
* as we may be collecting these records at the same time as building the
|
|
* family list, so we don't yet know the final family index.
|
|
* When actually recorded in the FontList's mLocalFaces array, the family
|
|
* will be stored as a simple index into the mFamilies array.
|
|
*/
|
|
struct InitData {
|
|
nsCString mFamilyName;
|
|
uint32_t mFaceIndex;
|
|
InitData(const nsACString& aFamily, uint32_t aFace)
|
|
: mFamilyName(aFamily), mFaceIndex(aFace) {}
|
|
InitData() = default;
|
|
};
|
|
String mKey;
|
|
uint32_t mFamilyIndex; // Index into the font list's Families array
|
|
uint32_t mFaceIndex; // Index into the family's Faces array
|
|
};
|
|
|
|
} // namespace fontlist
|
|
} // namespace mozilla
|
|
|
|
#include "ipc/IPCMessageUtils.h"
|
|
|
|
namespace IPC {
|
|
|
|
template <>
|
|
struct ParamTraits<mozilla::fontlist::Pointer> {
|
|
typedef mozilla::fontlist::Pointer paramType;
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
uint32_t v = aParam.mBlockAndOffset;
|
|
WriteParam(aMsg, v);
|
|
}
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
paramType* aResult) {
|
|
uint32_t v;
|
|
if (ReadParam(aMsg, aIter, &v)) {
|
|
aResult->mBlockAndOffset.store(v);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
} // namespace IPC
|
|
|
|
#undef ERROR // This is defined via Windows.h, but conflicts with some bindings
|
|
// code when this gets included in the same compilation unit.
|
|
|
|
#endif /* SharedFontList_h */
|