зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1798036 - Attach a SharedFTFaceData (recording the filename) when instantiating SharedFTFace for an installed variation font. r=lsalzman
This is needed so that UnscaledFontFreeType::CreateScaledFont can later call CloneFace if it needs to apply variation settings. Tested locally with an emulator running Android 13; not testable in CI as the older Android versions we have there don't use the new variable-font version of Roboto. Differential Revision: https://phabricator.services.mozilla.com/D161762
This commit is contained in:
Родитель
1563f74dd5
Коммит
c9e98f8fad
36
gfx/2d/2D.h
36
gfx/2d/2D.h
|
@ -1067,6 +1067,40 @@ class SharedFTFaceRefCountedData : public SharedFTFaceData {
|
|||
void ReleaseData() { static_cast<T*>(this)->Release(); }
|
||||
};
|
||||
|
||||
// Helper class used for clearing out user font data when FT 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 FT face created from that font entry contains a refptr to that
|
||||
// same FTUserFontData object.
|
||||
// This is also attached to FT faces for installed fonts (recording the
|
||||
// filename, rather than storing the font data) if variations are present.
|
||||
class FTUserFontData final
|
||||
: public mozilla::gfx::SharedFTFaceRefCountedData<FTUserFontData> {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData)
|
||||
|
||||
FTUserFontData(const uint8_t* aData, uint32_t aLength)
|
||||
: mFontData(aData), mLength(aLength) {}
|
||||
explicit FTUserFontData(const char* aFilename) : mFilename(aFilename) {}
|
||||
|
||||
const uint8_t* FontData() const { return mFontData; }
|
||||
|
||||
already_AddRefed<mozilla::gfx::SharedFTFace> CloneFace(
|
||||
int aFaceIndex = 0) override;
|
||||
|
||||
private:
|
||||
~FTUserFontData() {
|
||||
if (mFontData) {
|
||||
free((void*)mFontData);
|
||||
}
|
||||
}
|
||||
|
||||
std::string mFilename;
|
||||
const uint8_t* mFontData = nullptr;
|
||||
uint32_t mLength = 0;
|
||||
};
|
||||
|
||||
/** SharedFTFace is a shared wrapper around an FT_Face. It is ref-counted,
|
||||
* unlike FT_Face itself, so that it may be shared among many users with
|
||||
* RefPtr. Users should take care to lock SharedFTFace before accessing any
|
||||
|
@ -1078,7 +1112,7 @@ class SharedFTFace : public external::AtomicRefCounted<SharedFTFace> {
|
|||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SharedFTFace)
|
||||
|
||||
explicit SharedFTFace(FT_Face aFace, SharedFTFaceData* aData = nullptr);
|
||||
explicit SharedFTFace(FT_Face aFace, SharedFTFaceData* aData);
|
||||
virtual ~SharedFTFace();
|
||||
|
||||
FT_Face GetFace() const { return mFace; }
|
||||
|
|
|
@ -200,6 +200,25 @@ namespace mozilla::gfx {
|
|||
#ifdef MOZ_ENABLE_FREETYPE
|
||||
FT_Library Factory::mFTLibrary = nullptr;
|
||||
StaticMutex Factory::mFTLock;
|
||||
|
||||
already_AddRefed<SharedFTFace> FTUserFontData::CloneFace(int aFaceIndex) {
|
||||
if (mFontData) {
|
||||
RefPtr<SharedFTFace> face = Factory::NewSharedFTFaceFromData(
|
||||
nullptr, mFontData, mLength, aFaceIndex, this);
|
||||
if (!face ||
|
||||
(FT_Select_Charmap(face->GetFace(), FT_ENCODING_UNICODE) != FT_Err_Ok &&
|
||||
FT_Select_Charmap(face->GetFace(), FT_ENCODING_MS_SYMBOL) !=
|
||||
FT_Err_Ok)) {
|
||||
return nullptr;
|
||||
}
|
||||
return face.forget();
|
||||
}
|
||||
FT_Face face = Factory::NewFTFace(nullptr, mFilename.c_str(), aFaceIndex);
|
||||
if (face) {
|
||||
return MakeAndAddRef<SharedFTFace>(face, this);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -649,11 +668,19 @@ FT_Face Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName,
|
|||
already_AddRefed<SharedFTFace> Factory::NewSharedFTFace(FT_Library aFTLibrary,
|
||||
const char* aFilename,
|
||||
int aFaceIndex) {
|
||||
if (FT_Face face = NewFTFace(aFTLibrary, aFilename, aFaceIndex)) {
|
||||
return MakeAndAddRef<SharedFTFace>(face);
|
||||
} else {
|
||||
FT_Face face = NewFTFace(aFTLibrary, aFilename, aFaceIndex);
|
||||
if (!face) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If the font has variations, we may later need to "clone" it in
|
||||
// UnscaledFontFreeType::CreateScaledFont. To support this, we attach an
|
||||
// FTUserFontData that records the filename used to instantiate the face.
|
||||
RefPtr<FTUserFontData> data;
|
||||
if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
data = new FTUserFontData(aFilename);
|
||||
}
|
||||
return MakeAndAddRef<SharedFTFace>(face, data);
|
||||
}
|
||||
|
||||
FT_Face Factory::NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData,
|
||||
|
|
|
@ -127,50 +127,6 @@ ScaledFontFreeType::InstanceData::InstanceData(
|
|||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFont(
|
||||
Float aGlyphSize, const uint8_t* aInstanceData,
|
||||
uint32_t aInstanceDataLength, const FontVariation* aVariations,
|
||||
uint32_t aNumVariations) {
|
||||
if (aInstanceDataLength < sizeof(ScaledFontFreeType::InstanceData)) {
|
||||
gfxWarning() << "FreeType scaled font instance data is truncated.";
|
||||
return nullptr;
|
||||
}
|
||||
const ScaledFontFreeType::InstanceData& instanceData =
|
||||
*reinterpret_cast<const ScaledFontFreeType::InstanceData*>(aInstanceData);
|
||||
|
||||
RefPtr<SharedFTFace> face(InitFace());
|
||||
if (!face) {
|
||||
gfxWarning() << "Attempted to deserialize FreeType scaled font without "
|
||||
"FreeType face";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aNumVariations > 0 && face->GetData()) {
|
||||
if (RefPtr<SharedFTFace> varFace = face->GetData()->CloneFace()) {
|
||||
face = varFace;
|
||||
}
|
||||
}
|
||||
|
||||
// Only apply variations if we have an explicitly cloned face.
|
||||
if (aNumVariations > 0 && face != GetFace()) {
|
||||
ApplyVariationsToFace(aVariations, aNumVariations, face->GetFace());
|
||||
}
|
||||
|
||||
RefPtr<ScaledFontFreeType> scaledFont = new ScaledFontFreeType(
|
||||
std::move(face), this, aGlyphSize, instanceData.mApplySyntheticBold);
|
||||
|
||||
return scaledFont.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFontFromWRFont(
|
||||
Float aGlyphSize, const wr::FontInstanceOptions* aOptions,
|
||||
const wr::FontInstancePlatformOptions* aPlatformOptions,
|
||||
const FontVariation* aVariations, uint32_t aNumVariations) {
|
||||
ScaledFontFreeType::InstanceData instanceData(aOptions, aPlatformOptions);
|
||||
return CreateScaledFont(aGlyphSize, reinterpret_cast<uint8_t*>(&instanceData),
|
||||
sizeof(instanceData), aVariations, aNumVariations);
|
||||
}
|
||||
|
||||
bool ScaledFontFreeType::HasVariationSettings() {
|
||||
// Check if the FT face has been cloned.
|
||||
return mFace &&
|
||||
|
@ -179,17 +135,5 @@ bool ScaledFontFreeType::HasVariationSettings() {
|
|||
static_cast<UnscaledFontFreeType*>(mUnscaledFont.get())->GetFace();
|
||||
}
|
||||
|
||||
already_AddRefed<UnscaledFont> UnscaledFontFreeType::CreateFromFontDescriptor(
|
||||
const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex) {
|
||||
if (aDataLength == 0) {
|
||||
gfxWarning() << "FreeType font descriptor is truncated.";
|
||||
return nullptr;
|
||||
}
|
||||
const char* path = reinterpret_cast<const char*>(aData);
|
||||
RefPtr<UnscaledFont> unscaledFont =
|
||||
new UnscaledFontFreeType(std::string(path, aDataLength), aIndex);
|
||||
return unscaledFont.forget();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -179,4 +179,64 @@ void UnscaledFontFreeType::ApplyVariationsToFace(
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFont(
|
||||
Float aGlyphSize, const uint8_t* aInstanceData,
|
||||
uint32_t aInstanceDataLength, const FontVariation* aVariations,
|
||||
uint32_t aNumVariations) {
|
||||
if (aInstanceDataLength < sizeof(ScaledFontFreeType::InstanceData)) {
|
||||
gfxWarning() << "FreeType scaled font instance data is truncated.";
|
||||
return nullptr;
|
||||
}
|
||||
const ScaledFontFreeType::InstanceData& instanceData =
|
||||
*reinterpret_cast<const ScaledFontFreeType::InstanceData*>(aInstanceData);
|
||||
|
||||
RefPtr<SharedFTFace> face(InitFace());
|
||||
if (!face) {
|
||||
gfxWarning() << "Attempted to deserialize FreeType scaled font without "
|
||||
"FreeType face";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aNumVariations > 0 && face->GetData()) {
|
||||
if (RefPtr<SharedFTFace> varFace = face->GetData()->CloneFace()) {
|
||||
face = varFace;
|
||||
}
|
||||
}
|
||||
|
||||
// Only apply variations if we have an explicitly cloned face.
|
||||
if (aNumVariations > 0 && face != GetFace()) {
|
||||
ApplyVariationsToFace(aVariations, aNumVariations, face->GetFace());
|
||||
}
|
||||
|
||||
RefPtr<ScaledFontFreeType> scaledFont = new ScaledFontFreeType(
|
||||
std::move(face), this, aGlyphSize, instanceData.mApplySyntheticBold);
|
||||
|
||||
return scaledFont.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFontFromWRFont(
|
||||
Float aGlyphSize, const wr::FontInstanceOptions* aOptions,
|
||||
const wr::FontInstancePlatformOptions* aPlatformOptions,
|
||||
const FontVariation* aVariations, uint32_t aNumVariations) {
|
||||
ScaledFontFreeType::InstanceData instanceData(aOptions, aPlatformOptions);
|
||||
return CreateScaledFont(aGlyphSize, reinterpret_cast<uint8_t*>(&instanceData),
|
||||
sizeof(instanceData), aVariations, aNumVariations);
|
||||
}
|
||||
|
||||
already_AddRefed<UnscaledFont> UnscaledFontFreeType::CreateFromFontDescriptor(
|
||||
const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex) {
|
||||
if (aDataLength == 0) {
|
||||
gfxWarning() << "FreeType font descriptor is truncated.";
|
||||
return nullptr;
|
||||
}
|
||||
const char* path = reinterpret_cast<const char*>(aData);
|
||||
RefPtr<UnscaledFont> unscaledFont =
|
||||
new UnscaledFontFreeType(std::string(path, aDataLength), aIndex);
|
||||
return unscaledFont.forget();
|
||||
}
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
} // namespace mozilla::gfx
|
||||
|
|
|
@ -822,15 +822,3 @@ void gfxFT2FontBase::SetupVarCoords(
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<SharedFTFace> FTUserFontData::CloneFace(int aFaceIndex) {
|
||||
RefPtr<SharedFTFace> face = Factory::NewSharedFTFaceFromData(
|
||||
nullptr, mFontData, mLength, aFaceIndex, this);
|
||||
if (!face ||
|
||||
(FT_Select_Charmap(face->GetFace(), FT_ENCODING_UNICODE) != FT_Err_Ok &&
|
||||
FT_Select_Charmap(face->GetFace(), FT_ENCODING_MS_SYMBOL) !=
|
||||
FT_Err_Ok)) {
|
||||
return nullptr;
|
||||
}
|
||||
return face.forget();
|
||||
}
|
||||
|
|
|
@ -150,35 +150,4 @@ class gfxFT2FontBase : public gfxFont {
|
|||
mGlyphMetrics MOZ_GUARDED_BY(mLock);
|
||||
};
|
||||
|
||||
// Helper classes used for clearing out user font data when FT 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 FT face created from that font entry contains a refptr to that
|
||||
// same FTUserFontData object.
|
||||
|
||||
class FTUserFontData final
|
||||
: public mozilla::gfx::SharedFTFaceRefCountedData<FTUserFontData> {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData)
|
||||
|
||||
FTUserFontData(const uint8_t* aData, uint32_t aLength)
|
||||
: mFontData(aData), mLength(aLength) {}
|
||||
|
||||
const uint8_t* FontData() const { return mFontData; }
|
||||
|
||||
already_AddRefed<mozilla::gfx::SharedFTFace> CloneFace(
|
||||
int aFaceIndex = 0) override;
|
||||
|
||||
private:
|
||||
~FTUserFontData() {
|
||||
if (mFontData) {
|
||||
free((void*)mFontData);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* mFontData;
|
||||
uint32_t mLength;
|
||||
};
|
||||
|
||||
#endif /* GFX_FT2FONTBASE_H */
|
||||
|
|
|
@ -114,7 +114,8 @@ already_AddRefed<SharedFTFace> FT2FontEntry::GetFTFace(bool aCommit) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
face = Factory::NewSharedFTFace(nullptr, mFilename.get(), mFTFontIndex);
|
||||
RefPtr<FTUserFontData> fd = new FTUserFontData(mFilename.get());
|
||||
face = fd->CloneFace(mFTFontIndex);
|
||||
if (!face) {
|
||||
NS_WARNING("failed to create freetype face");
|
||||
return nullptr;
|
||||
|
|
|
@ -15,18 +15,21 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
class SystemFontListEntry;
|
||||
};
|
||||
namespace gfx {
|
||||
class FTUserFontData;
|
||||
};
|
||||
}; // namespace mozilla
|
||||
|
||||
class FontNameCache;
|
||||
typedef struct FT_FaceRec_* FT_Face;
|
||||
class nsZipArchive;
|
||||
class WillShutdownObserver;
|
||||
class FTUserFontData;
|
||||
|
||||
class FT2FontEntry final : public gfxFT2FontEntryBase {
|
||||
friend class gfxFT2FontList;
|
||||
|
||||
using FontListEntry = mozilla::dom::SystemFontListEntry;
|
||||
using FTUserFontData = mozilla::gfx::FTUserFontData;
|
||||
|
||||
public:
|
||||
explicit FT2FontEntry(const nsACString& aFaceName)
|
||||
|
|
|
@ -503,7 +503,9 @@ bool gfxFontconfigFontEntry::TestCharacterMap(uint32_t aCh) {
|
|||
|
||||
bool gfxFontconfigFontEntry::HasFontTable(uint32_t aTableTag) {
|
||||
if (FTUserFontData* ufd = GetUserFontData()) {
|
||||
return !!gfxFontUtils::FindTableDirEntry(ufd->FontData(), aTableTag);
|
||||
if (ufd->FontData()) {
|
||||
return !!gfxFontUtils::FindTableDirEntry(ufd->FontData(), aTableTag);
|
||||
}
|
||||
}
|
||||
return gfxFT2FontEntryBase::FaceHasTable(GetFTFace(), aTableTag);
|
||||
}
|
||||
|
@ -511,7 +513,9 @@ bool gfxFontconfigFontEntry::HasFontTable(uint32_t aTableTag) {
|
|||
hb_blob_t* gfxFontconfigFontEntry::GetFontTable(uint32_t aTableTag) {
|
||||
// for data fonts, read directly from the font data
|
||||
if (FTUserFontData* ufd = GetUserFontData()) {
|
||||
return gfxFontUtils::GetTableFromFontData(ufd->FontData(), aTableTag);
|
||||
if (ufd->FontData()) {
|
||||
return gfxFontUtils::GetTableFromFontData(ufd->FontData(), aTableTag);
|
||||
}
|
||||
}
|
||||
|
||||
return gfxFontEntry::GetFontTable(aTableTag);
|
||||
|
|
|
@ -66,6 +66,7 @@ class DefaultDelete<FcObjectSet> {
|
|||
|
||||
class gfxFontconfigFontEntry final : public gfxFT2FontEntryBase {
|
||||
friend class gfxFcPlatformFontList;
|
||||
using FTUserFontData = mozilla::gfx::FTUserFontData;
|
||||
|
||||
public:
|
||||
// used for system fonts with explicit patterns
|
||||
|
|
Загрузка…
Ссылка в новой задаче