зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1455569 - Handle variation settings of system-installed variation fonts when creating CTFont from CGFont on High Sierra. r=lsalzman
This commit is contained in:
Родитель
21bd76217a
Коммит
4b2b2d4c9f
|
@ -75,7 +75,8 @@ bool ScaledFontMac::sSymbolLookupDone = false;
|
|||
// Helper to create a CTFont from a CGFont, copying any variations that were
|
||||
// set on the original CGFont.
|
||||
static CTFontRef
|
||||
CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize)
|
||||
CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize,
|
||||
bool aInstalledFont)
|
||||
{
|
||||
// Avoid calling potentially buggy variation APIs on pre-Sierra macOS
|
||||
// versions (see bug 1331683).
|
||||
|
@ -85,30 +86,50 @@ CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize)
|
|||
// the extra work here -- and this seems to avoid Core Text crashiness
|
||||
// seen in bug 1454094.
|
||||
//
|
||||
// So we only need to do this "the hard way" on Sierra; on other releases,
|
||||
// just let the standard CTFont function do its thing.
|
||||
if (!nsCocoaFeatures::OnSierraExactly()) {
|
||||
return CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, nullptr);
|
||||
}
|
||||
// However, for installed fonts it seems we DO need to copy the variations
|
||||
// explicitly even on 10.13, otherwise fonts fail to render (as in bug
|
||||
// 1455494) when non-default values are used. Fortunately, the crash
|
||||
// mentioned above occurs with data fonts, not (AFAICT) with system-
|
||||
// installed fonts.
|
||||
//
|
||||
// So we only need to do this "the hard way" on Sierra, and for installed
|
||||
// fonts on HighSierra+; otherwise, just let the standard CTFont function
|
||||
// do its thing.
|
||||
//
|
||||
// NOTE in case this ever needs further adjustment: there is similar logic
|
||||
// in four places in the tree (sadly):
|
||||
// CreateCTFontFromCGFontWithVariations in gfxMacFont.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in ScaledFontMac.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in cairo-quartz-font.c
|
||||
// ctfont_create_exact_copy in SkFontHost_mac.cpp
|
||||
|
||||
CFDictionaryRef vars = CGFontCopyVariations(aCGFont);
|
||||
CTFontRef ctFont;
|
||||
if (vars) {
|
||||
CFDictionaryRef varAttr =
|
||||
CFDictionaryCreate(nullptr,
|
||||
(const void**)&kCTFontVariationAttribute,
|
||||
(const void**)&vars, 1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease(vars);
|
||||
if (nsCocoaFeatures::OnSierraExactly() ||
|
||||
(aInstalledFont && nsCocoaFeatures::OnHighSierraOrLater())) {
|
||||
CFDictionaryRef vars = CGFontCopyVariations(aCGFont);
|
||||
if (vars) {
|
||||
CFDictionaryRef varAttr =
|
||||
CFDictionaryCreate(nullptr,
|
||||
(const void**)&kCTFontVariationAttribute,
|
||||
(const void**)&vars, 1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease(vars);
|
||||
|
||||
CTFontDescriptorRef varDesc = CTFontDescriptorCreateWithAttributes(varAttr);
|
||||
CFRelease(varAttr);
|
||||
CTFontDescriptorRef varDesc =
|
||||
CTFontDescriptorCreateWithAttributes(varAttr);
|
||||
CFRelease(varAttr);
|
||||
|
||||
ctFont = CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, varDesc);
|
||||
CFRelease(varDesc);
|
||||
ctFont = CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr,
|
||||
varDesc);
|
||||
CFRelease(varDesc);
|
||||
} else {
|
||||
ctFont = CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
} else {
|
||||
ctFont = CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, nullptr);
|
||||
ctFont = CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
return ctFont;
|
||||
}
|
||||
|
@ -139,7 +160,9 @@ ScaledFontMac::ScaledFontMac(CGFontRef aFont,
|
|||
|
||||
if (CTFontDrawGlyphsPtr != nullptr) {
|
||||
// only create mCTFont if we're going to be using the CTFontDrawGlyphs API
|
||||
mCTFont = CreateCTFontFromCGFontWithVariations(aFont, aSize);
|
||||
auto unscaledMac = static_cast<UnscaledFontMac*>(aUnscaledFont.get());
|
||||
bool dataFont = unscaledMac->IsDataFont();
|
||||
mCTFont = CreateCTFontFromCGFontWithVariations(aFont, aSize, !dataFont);
|
||||
} else {
|
||||
mCTFont = nullptr;
|
||||
}
|
||||
|
@ -160,7 +183,10 @@ SkTypeface* ScaledFontMac::GetSkTypeface()
|
|||
if (mCTFont) {
|
||||
mTypeface = SkCreateTypefaceFromCTFont(mCTFont);
|
||||
} else {
|
||||
CTFontRef fontFace = CreateCTFontFromCGFontWithVariations(mFont, mSize);
|
||||
auto unscaledMac = static_cast<UnscaledFontMac*>(GetUnscaledFont().get());
|
||||
bool dataFont = unscaledMac->IsDataFont();
|
||||
CTFontRef fontFace =
|
||||
CreateCTFontFromCGFontWithVariations(mFont, mSize, !dataFont);
|
||||
mTypeface = SkCreateTypefaceFromCTFont(fontFace);
|
||||
CFRelease(fontFace);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ public:
|
|||
|
||||
bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
|
||||
|
||||
bool IsDataFont() const { return mIsDataFont; }
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(Float aGlyphSize,
|
||||
const uint8_t* aInstanceData,
|
||||
|
|
|
@ -353,6 +353,17 @@ CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize)
|
|||
//
|
||||
// So we only need to do this "the hard way" on Sierra; on other releases,
|
||||
// just let the standard CTFont function do its thing.
|
||||
//
|
||||
// NOTE in case this ever needs further adjustment: there is similar logic
|
||||
// in four places in the tree (sadly):
|
||||
// CreateCTFontFromCGFontWithVariations in gfxMacFont.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in ScaledFontMac.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in cairo-quartz-font.c
|
||||
// ctfont_create_exact_copy in SkFontHost_mac.cpp
|
||||
//
|
||||
// XXX Does this need to behave differently for installed fonts on High
|
||||
// Sierra, as in other similar places (bug 1455569)?
|
||||
|
||||
if (!Gecko_OnSierraExactly()) {
|
||||
return CTFontCreateWithGraphicsFont(aCGFont, aSize, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -757,6 +757,7 @@ private:
|
|||
// CGFont.
|
||||
#ifdef MOZ_SKIA
|
||||
extern "C" bool Gecko_OnSierraExactly();
|
||||
extern "C" bool Gecko_OnHighSierraOrLater();
|
||||
#endif
|
||||
static UniqueCFRef<CTFontRef> ctfont_create_exact_copy(CTFontRef baseFont, CGFloat textSize,
|
||||
const CGAffineTransform* transform)
|
||||
|
@ -781,9 +782,41 @@ static UniqueCFRef<CTFontRef> ctfont_create_exact_copy(CTFontRef baseFont, CGFlo
|
|||
// the extra work here -- and this seems to avoid Core Text crashiness
|
||||
// seen in bug 1454094.
|
||||
//
|
||||
// So we only need to do this "the hard way" on Sierra; on other releases,
|
||||
// just let the standard CTFont function do its thing.
|
||||
if (Gecko_OnSierraExactly())
|
||||
// However, for installed fonts it seems we DO need to copy the variations
|
||||
// explicitly even on 10.13, otherwise fonts fail to render (as in bug
|
||||
// 1455494) when non-default values are used. Fortunately, the crash
|
||||
// mentioned above occurs with data fonts, not (AFAICT) with system-
|
||||
// installed fonts.
|
||||
//
|
||||
// So we only need to do this "the hard way" on Sierra, and for installed
|
||||
// fonts on HighSierra+; otherwise, just let the standard CTFont function
|
||||
// do its thing.
|
||||
//
|
||||
// NOTE in case this ever needs further adjustment: there is similar logic
|
||||
// in four places in the tree (sadly):
|
||||
// CreateCTFontFromCGFontWithVariations in gfxMacFont.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in ScaledFontMac.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in cairo-quartz-font.c
|
||||
// ctfont_create_exact_copy in SkFontHost_mac.cpp
|
||||
|
||||
// To figure out if a font is installed locally or used from a @font-face
|
||||
// resource, we check whether its descriptor can provide a URL. This will
|
||||
// be present for installed fonts, but not for those activated from an
|
||||
// in-memory resource.
|
||||
auto IsInstalledFont = [](CTFontRef aFont) {
|
||||
CTFontDescriptorRef desc = CTFontCopyFontDescriptor(aFont);
|
||||
CFTypeRef attr = CTFontDescriptorCopyAttribute(desc, kCTFontURLAttribute);
|
||||
CFRelease(desc);
|
||||
bool result = false;
|
||||
if (attr) {
|
||||
result = true;
|
||||
CFRelease(attr);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
if (Gecko_OnSierraExactly() ||
|
||||
(Gecko_OnHighSierraOrLater() && IsInstalledFont(baseFont)))
|
||||
#endif
|
||||
{
|
||||
// Not UniqueCFRef<> because CGFontCopyVariations can return null!
|
||||
|
|
|
@ -666,8 +666,11 @@ CTFontRef
|
|||
gfxCoreTextShaper::CreateCTFontWithFeatures(CGFloat aSize,
|
||||
CTFontDescriptorRef aDescriptor)
|
||||
{
|
||||
const gfxFontEntry* fe = mFont->GetFontEntry();
|
||||
bool isInstalledFont = !fe->IsUserFont() || fe->IsLocalUserFont();
|
||||
CGFontRef cgFont = static_cast<gfxMacFont*>(mFont)->GetCGFontRef();
|
||||
return gfxMacFont::CreateCTFontFromCGFontWithVariations(cgFont, aSize,
|
||||
isInstalledFont,
|
||||
aDescriptor);
|
||||
}
|
||||
|
||||
|
|
|
@ -421,6 +421,7 @@ gfxMacFont::GetCharWidth(CFDataRef aCmap, char16_t aUniChar,
|
|||
CTFontRef
|
||||
gfxMacFont::CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont,
|
||||
CGFloat aSize,
|
||||
bool aInstalledFont,
|
||||
CTFontDescriptorRef aFontDesc)
|
||||
{
|
||||
// Avoid calling potentially buggy variation APIs on pre-Sierra macOS
|
||||
|
@ -431,34 +432,53 @@ gfxMacFont::CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont,
|
|||
// the extra work here -- and this seems to avoid Core Text crashiness
|
||||
// seen in bug 1454094.
|
||||
//
|
||||
// So we only need to do this "the hard way" on Sierra; on other releases,
|
||||
// just let the standard CTFont function do its thing.
|
||||
if (!nsCocoaFeatures::OnSierraExactly()) {
|
||||
return CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, aFontDesc);
|
||||
}
|
||||
// However, for installed fonts it seems we DO need to copy the variations
|
||||
// explicitly even on 10.13, otherwise fonts fail to render (as in bug
|
||||
// 1455494) when non-default values are used. Fortunately, the crash
|
||||
// mentioned above occurs with data fonts, not (AFAICT) with system-
|
||||
// installed fonts.
|
||||
//
|
||||
// So we only need to do this "the hard way" on Sierra, and on HighSierra
|
||||
// for system-installed fonts; in other cases just let the standard CTFont
|
||||
// function do its thing.
|
||||
//
|
||||
// NOTE in case this ever needs further adjustment: there is similar logic
|
||||
// in four places in the tree (sadly):
|
||||
// CreateCTFontFromCGFontWithVariations in gfxMacFont.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in ScaledFontMac.cpp
|
||||
// CreateCTFontFromCGFontWithVariations in cairo-quartz-font.c
|
||||
// ctfont_create_exact_copy in SkFontHost_mac.cpp
|
||||
|
||||
CFDictionaryRef variations = ::CGFontCopyVariations(aCGFont);
|
||||
CTFontRef ctFont;
|
||||
if (variations) {
|
||||
CFDictionaryRef varAttr =
|
||||
::CFDictionaryCreate(nullptr,
|
||||
(const void**)&kCTFontVariationAttribute,
|
||||
(const void**)&variations, 1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
::CFRelease(variations);
|
||||
if (nsCocoaFeatures::OnSierraExactly() ||
|
||||
(aInstalledFont && nsCocoaFeatures::OnHighSierraOrLater())) {
|
||||
CFDictionaryRef variations = ::CGFontCopyVariations(aCGFont);
|
||||
if (variations) {
|
||||
CFDictionaryRef varAttr =
|
||||
::CFDictionaryCreate(nullptr,
|
||||
(const void**)&kCTFontVariationAttribute,
|
||||
(const void**)&variations, 1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
::CFRelease(variations);
|
||||
|
||||
CTFontDescriptorRef varDesc = aFontDesc
|
||||
? ::CTFontDescriptorCreateCopyWithAttributes(aFontDesc, varAttr)
|
||||
: ::CTFontDescriptorCreateWithAttributes(varAttr);
|
||||
::CFRelease(varAttr);
|
||||
CTFontDescriptorRef varDesc = aFontDesc
|
||||
? ::CTFontDescriptorCreateCopyWithAttributes(aFontDesc, varAttr)
|
||||
: ::CTFontDescriptorCreateWithAttributes(varAttr);
|
||||
::CFRelease(varAttr);
|
||||
|
||||
ctFont = ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, varDesc);
|
||||
::CFRelease(varDesc);
|
||||
ctFont = ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr,
|
||||
varDesc);
|
||||
::CFRelease(varDesc);
|
||||
} else {
|
||||
ctFont = ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr,
|
||||
aFontDesc);
|
||||
}
|
||||
} else {
|
||||
ctFont = ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr,
|
||||
aFontDesc);
|
||||
}
|
||||
|
||||
return ctFont;
|
||||
}
|
||||
|
||||
|
@ -476,7 +496,10 @@ gfxMacFont::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID)
|
|||
}
|
||||
|
||||
if (!mCTFont) {
|
||||
mCTFont = CreateCTFontFromCGFontWithVariations(mCGFont, mAdjustedSize);
|
||||
bool isInstalledFont =
|
||||
!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont();
|
||||
mCTFont = CreateCTFontFromCGFontWithVariations(mCGFont, mAdjustedSize,
|
||||
isInstalledFont);
|
||||
if (!mCTFont) { // shouldn't happen, but let's be safe
|
||||
NS_WARNING("failed to create CTFontRef to measure glyph width");
|
||||
return 0;
|
||||
|
|
|
@ -68,6 +68,7 @@ public:
|
|||
static CTFontRef
|
||||
CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont,
|
||||
CGFloat aSize,
|
||||
bool aInstalledFont,
|
||||
CTFontDescriptorRef aFontDesc = nullptr);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -45,6 +45,7 @@ private:
|
|||
// C-callable helper for cairo-quartz-font.c and SkFontHost_mac.cpp
|
||||
extern "C" {
|
||||
bool Gecko_OnSierraExactly();
|
||||
bool Gecko_OnHighSierraOrLater();
|
||||
}
|
||||
|
||||
#endif // nsCocoaFeatures_h_
|
||||
|
|
|
@ -188,6 +188,12 @@ Gecko_OnSierraExactly()
|
|||
return nsCocoaFeatures::OnSierraExactly();
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_OnHighSierraOrLater()
|
||||
{
|
||||
return nsCocoaFeatures::OnHighSierraOrLater();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsCocoaFeatures::IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче