Bug 1971053 - patch 2 - Prefer to use the specified font from CSS for potentially-emoji characters unless a specific presentation is explicitly requested. a=dmeehan
Original Revision: https://phabricator.services.mozilla.com/D253740 Differential Revision: https://phabricator.services.mozilla.com/D253939
This commit is contained in:
committed by
dmeehan@mozilla.com
parent
38ca6718c3
commit
753cdf7af0
@@ -2348,6 +2348,12 @@ bool gfxFcPlatformFontList::FindAndAddFamiliesLocked(
|
|||||||
cacheKey.Append(':');
|
cacheKey.Append(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include the generic family in the cache key, to maintain the distinction
|
||||||
|
// between fonts explicitly requested by name and the results of resolving
|
||||||
|
// CSS generics.
|
||||||
|
cacheKey.AppendInt(int(aGeneric));
|
||||||
|
cacheKey.Append(':');
|
||||||
|
|
||||||
cacheKey.Append(familyName);
|
cacheKey.Append(familyName);
|
||||||
auto vis =
|
auto vis =
|
||||||
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
|
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ inline bool PrefersColor(FontPresentation aPresentation) {
|
|||||||
return aPresentation >= FontPresentation::EmojiDefault;
|
return aPresentation >= FontPresentation::EmojiDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsExplicitPresentation(FontPresentation aPresentation) {
|
||||||
|
return aPresentation == FontPresentation::TextExplicit ||
|
||||||
|
aPresentation == FontPresentation::EmojiExplicit;
|
||||||
|
}
|
||||||
|
|
||||||
// when searching through pref langs, max number of pref langs
|
// when searching through pref langs, max number of pref langs
|
||||||
const uint32_t kMaxLenPrefLangList = 32;
|
const uint32_t kMaxLenPrefLangList = 32;
|
||||||
|
|
||||||
|
|||||||
@@ -1856,18 +1856,8 @@ gfxFontGroup::gfxFontGroup(nsPresContext* aPresContext,
|
|||||||
mUserFontSet(aUserFontSet),
|
mUserFontSet(aUserFontSet),
|
||||||
mTextPerf(aTextPerf),
|
mTextPerf(aTextPerf),
|
||||||
mPageLang(gfxPlatformFontList::GetFontPrefLangFor(aLanguage)),
|
mPageLang(gfxPlatformFontList::GetFontPrefLangFor(aLanguage)),
|
||||||
mExplicitLanguage(aExplicitLanguage) {
|
mExplicitLanguage(aExplicitLanguage),
|
||||||
switch (aVariantEmoji) {
|
mFontVariantEmoji(aVariantEmoji) {
|
||||||
case StyleFontVariantEmoji::Normal:
|
|
||||||
case StyleFontVariantEmoji::Unicode:
|
|
||||||
break;
|
|
||||||
case StyleFontVariantEmoji::Text:
|
|
||||||
mEmojiPresentation = FontPresentation::TextExplicit;
|
|
||||||
break;
|
|
||||||
case StyleFontVariantEmoji::Emoji:
|
|
||||||
mEmojiPresentation = FontPresentation::EmojiExplicit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// We don't use SetUserFontSet() here, as we want to unconditionally call
|
// We don't use SetUserFontSet() here, as we want to unconditionally call
|
||||||
// EnsureFontList() rather than only do UpdateUserFonts() if it changed.
|
// EnsureFontList() rather than only do UpdateUserFonts() if it changed.
|
||||||
}
|
}
|
||||||
@@ -3209,7 +3199,11 @@ already_AddRefed<gfxFont> gfxFontGroup::FindFontForChar(
|
|||||||
if (EmojiPresentation emojiPresentation = GetEmojiPresentation(aCh);
|
if (EmojiPresentation emojiPresentation = GetEmojiPresentation(aCh);
|
||||||
emojiPresentation != TextOnly) {
|
emojiPresentation != TextOnly) {
|
||||||
// Default presentation from the font-variant-emoji property.
|
// Default presentation from the font-variant-emoji property.
|
||||||
presentation = mEmojiPresentation;
|
if (mFontVariantEmoji == StyleFontVariantEmoji::Emoji) {
|
||||||
|
presentation = FontPresentation::EmojiExplicit;
|
||||||
|
} else if (mFontVariantEmoji == StyleFontVariantEmoji::Text) {
|
||||||
|
presentation = FontPresentation::TextExplicit;
|
||||||
|
}
|
||||||
// If there wasn't an explicit font-variant-emoji setting, default to
|
// If there wasn't an explicit font-variant-emoji setting, default to
|
||||||
// what Unicode prefers for this character.
|
// what Unicode prefers for this character.
|
||||||
if (presentation == FontPresentation::Any) {
|
if (presentation == FontPresentation::Any) {
|
||||||
@@ -3225,8 +3219,7 @@ already_AddRefed<gfxFont> gfxFontGroup::FindFontForChar(
|
|||||||
// glyph.
|
// glyph.
|
||||||
// If the prefer-text selector is present, we specifically look for a
|
// If the prefer-text selector is present, we specifically look for a
|
||||||
// font that will provide a monochrome glyph.
|
// font that will provide a monochrome glyph.
|
||||||
if (aNextCh == kVariationSelector16 ||
|
if (aNextCh == kVariationSelector16 || IsEmojiSkinToneModifier(aNextCh) ||
|
||||||
(aNextCh >= kEmojiSkinToneFirst && aNextCh <= kEmojiSkinToneLast) ||
|
|
||||||
gfxFontUtils::IsEmojiFlagAndTag(aCh, aNextCh)) {
|
gfxFontUtils::IsEmojiFlagAndTag(aCh, aNextCh)) {
|
||||||
// Emoji presentation is explicitly requested by a variation selector
|
// Emoji presentation is explicitly requested by a variation selector
|
||||||
// or the presence of a skin-tone codepoint.
|
// or the presence of a skin-tone codepoint.
|
||||||
@@ -3305,8 +3298,14 @@ already_AddRefed<gfxFont> gfxFontGroup::FindFontForChar(
|
|||||||
// Handle a candidate font that could support the character, returning true
|
// Handle a candidate font that could support the character, returning true
|
||||||
// if we should go ahead and return |f|, false to continue searching.
|
// if we should go ahead and return |f|, false to continue searching.
|
||||||
auto CheckCandidate = [&](gfxFont* f, FontMatchType t) -> bool {
|
auto CheckCandidate = [&](gfxFont* f, FontMatchType t) -> bool {
|
||||||
// If no preference, then just accept the font.
|
// If no preference, or if it's an explicitly-named family in the fontgroup
|
||||||
if (presentation == FontPresentation::Any) {
|
// and font-variant-emoji is 'normal', then we accept the font.
|
||||||
|
if (presentation == FontPresentation::Any ||
|
||||||
|
(!IsExplicitPresentation(presentation) &&
|
||||||
|
t.kind == FontMatchType::Kind::kFontGroup &&
|
||||||
|
t.generic == StyleGenericFontFamily::None &&
|
||||||
|
mFontVariantEmoji == StyleFontVariantEmoji::Normal &&
|
||||||
|
!gfxFontUtils::IsRegionalIndicator(aCh))) {
|
||||||
*aMatchType = t;
|
*aMatchType = t;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3447,21 +3446,6 @@ already_AddRefed<gfxFont> gfxFontGroup::FindFontForChar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's an emoji codepoint and we found a named-family candidate (not a
|
|
||||||
// generic) in the font list, we accept it even if it doesn't match the
|
|
||||||
// presentation (so authors can deliberately request fonts that do not match
|
|
||||||
// the Unicode emoji default presentation style for a given character). But
|
|
||||||
// don't do this if a particular presentation was explicitly requested in the
|
|
||||||
// text, or for Regional Indicator chars (because of Segoe UI Emoji).
|
|
||||||
if (candidateFont &&
|
|
||||||
candidateMatchType.generic == StyleGenericFontFamily::None &&
|
|
||||||
presentation != FontPresentation::EmojiExplicit &&
|
|
||||||
presentation != FontPresentation::TextExplicit &&
|
|
||||||
!gfxFontUtils::IsRegionalIndicator(aCh)) {
|
|
||||||
*aMatchType = candidateMatchType;
|
|
||||||
return candidateFont.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fontListLength == 0) {
|
if (fontListLength == 0) {
|
||||||
RefPtr<gfxFont> defaultFont = GetDefaultFont();
|
RefPtr<gfxFont> defaultFont = GetDefaultFont();
|
||||||
if (defaultFont->HasCharacter(aCh) ||
|
if (defaultFont->HasCharacter(aCh) ||
|
||||||
@@ -3612,19 +3596,26 @@ void gfxFontGroup::ComputeRanges(nsTArray<TextRange>& aRanges, const T* aString,
|
|||||||
// the font selected for an adjacent character, and does not need to
|
// the font selected for an adjacent character, and does not need to
|
||||||
// consider emoji vs text presentation.
|
// consider emoji vs text presentation.
|
||||||
if ((font = GetFontAt(0, ch)) != nullptr && font->HasCharacter(ch) &&
|
if ((font = GetFontAt(0, ch)) != nullptr && font->HasCharacter(ch) &&
|
||||||
// In 8-bit text, the only time emoji presentation might be needed
|
(
|
||||||
// is if it is explicitly requested with font-variant, as no 8-bit
|
// In 8-bit text, we can unconditionally accept the first font if
|
||||||
// chars are emoji by default.
|
// font-variant-emoji is 'normal', or if the character does not
|
||||||
((sizeof(T) == sizeof(uint8_t) &&
|
// have the emoji property; there cannot be adjacent characters
|
||||||
(mEmojiPresentation != FontPresentation::EmojiExplicit ||
|
// that would affect it.
|
||||||
GetEmojiPresentation(ch) == TextOnly)) ||
|
(sizeof(T) == sizeof(uint8_t) &&
|
||||||
// For 16-bit text, we need to consider cluster extenders etc.
|
(mFontVariantEmoji == StyleFontVariantEmoji::Normal ||
|
||||||
(sizeof(T) == sizeof(char16_t) &&
|
GetEmojiPresentation(ch) == TextOnly)) ||
|
||||||
(!IsClusterExtender(ch) && ch != NARROW_NO_BREAK_SPACE &&
|
// For 16-bit text, we need to consider cluster extenders etc.
|
||||||
!gfxFontUtils::IsJoinControl(ch) &&
|
(sizeof(T) == sizeof(char16_t) &&
|
||||||
!gfxFontUtils::IsJoinCauser(prevCh) &&
|
(!IsClusterExtender(ch) && ch != NARROW_NO_BREAK_SPACE &&
|
||||||
!gfxFontUtils::IsVarSelector(ch) &&
|
!gfxFontUtils::IsJoinControl(ch) &&
|
||||||
GetEmojiPresentation(ch) == TextOnly)))) {
|
!gfxFontUtils::IsJoinCauser(prevCh) &&
|
||||||
|
!gfxFontUtils::IsVarSelector(ch) &&
|
||||||
|
(GetEmojiPresentation(ch) == TextOnly ||
|
||||||
|
(!(IsEmojiPresentationSelector(nextCh) ||
|
||||||
|
IsEmojiSkinToneModifier(nextCh) ||
|
||||||
|
gfxFontUtils::IsEmojiFlagAndTag(ch, nextCh)) &&
|
||||||
|
mFontVariantEmoji == StyleFontVariantEmoji::Normal &&
|
||||||
|
mFonts[0].Generic() == StyleGenericFontFamily::None)))))) {
|
||||||
matchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()};
|
matchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()};
|
||||||
} else {
|
} else {
|
||||||
font =
|
font =
|
||||||
|
|||||||
@@ -1399,7 +1399,7 @@ class gfxFontGroup final : public gfxTextRunFactory {
|
|||||||
|
|
||||||
bool mResolvedFonts = false; // Whether the mFonts array has been set up.
|
bool mResolvedFonts = false; // Whether the mFonts array has been set up.
|
||||||
|
|
||||||
FontPresentation mEmojiPresentation = FontPresentation::Any;
|
StyleFontVariantEmoji mFontVariantEmoji = StyleFontVariantEmoji::Normal;
|
||||||
|
|
||||||
// Generic font family used to select among font prefs during fallback.
|
// Generic font family used to select among font prefs during fallback.
|
||||||
mozilla::StyleGenericFontFamily mFallbackGeneric =
|
mozilla::StyleGenericFontFamily mFallbackGeneric =
|
||||||
|
|||||||
@@ -56,10 +56,16 @@ enum EmojiPresentation { TextOnly = 0, TextDefault = 1, EmojiDefault = 2 };
|
|||||||
|
|
||||||
const uint32_t kVariationSelector15 = 0xFE0E; // text presentation
|
const uint32_t kVariationSelector15 = 0xFE0E; // text presentation
|
||||||
const uint32_t kVariationSelector16 = 0xFE0F; // emoji presentation
|
const uint32_t kVariationSelector16 = 0xFE0F; // emoji presentation
|
||||||
|
static inline bool IsEmojiPresentationSelector(uint32_t aCh) {
|
||||||
|
return aCh >= kVariationSelector15 && aCh <= kVariationSelector16;
|
||||||
|
}
|
||||||
|
|
||||||
// Unicode values for EMOJI MODIFIER FITZPATRICK TYPE-*
|
// Unicode values for EMOJI MODIFIER FITZPATRICK TYPE-*
|
||||||
const uint32_t kEmojiSkinToneFirst = 0x1f3fb;
|
const uint32_t kEmojiSkinToneFirst = 0x1f3fb;
|
||||||
const uint32_t kEmojiSkinToneLast = 0x1f3ff;
|
const uint32_t kEmojiSkinToneLast = 0x1f3ff;
|
||||||
|
static inline bool IsEmojiSkinToneModifier(uint32_t aCh) {
|
||||||
|
return aCh >= kEmojiSkinToneFirst && aCh <= kEmojiSkinToneLast;
|
||||||
|
}
|
||||||
|
|
||||||
extern const hb_unicode_general_category_t sICUtoHBcategory[];
|
extern const hb_unicode_general_category_t sICUtoHBcategory[];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
span.emoji {
|
||||||
|
font-variant-emoji: emoji;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from the emoji font:</p>
|
||||||
|
<div>abc<span class=emoji>123</span>xyz</div>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from the emoji font:</p>
|
||||||
|
<div>abc123xyz</div>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from the emoji font:</p>
|
||||||
|
<div style="font-variant-emoji: emoji">abc123xyz</div>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
span.text {
|
||||||
|
font-family: Ahem;
|
||||||
|
font-variant-emoji: text;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from Ahem:</p>
|
||||||
|
<div style="font-variant-emoji: text">abc<span class=text>123</span>xyz</div>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from Ahem:</p>
|
||||||
|
<div style="font-variant-emoji: text">abc123xyz</div>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from Ahem:</p>
|
||||||
|
<div style="font-variant-emoji: unicode">abc123xyz</div>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- presence of ZWSP should not affect font selection -->
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from the emoji font:</p>
|
||||||
|
<div>abc123xyz​</div>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- presence of ZWSP should not affect font selection -->
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from the emoji font:</p>
|
||||||
|
<div style="font-variant-emoji: emoji">abc123xyz​</div>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- presence of ZWSP should not affect font selection -->
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from Ahem:</p>
|
||||||
|
<div style="font-variant-emoji: text">abc123xyz​</div>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Ahem;
|
||||||
|
src: url(../fonts/Ahem.ttf);
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
font: 25px/2 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", Ahem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- presence of ZWSP should not affect font selection -->
|
||||||
|
|
||||||
|
<p>Expect digits to be rendered from Ahem:</p>
|
||||||
|
<div style="font-variant-emoji: unicode">abc123xyz​</div>
|
||||||
@@ -213,3 +213,12 @@ test-pref(privacy.resistFingerprinting,true) == system-font-rfp.html system-font
|
|||||||
|
|
||||||
# Bug 1970980 - Test for regional-indicator emoji handling with Windows-specific fonts
|
# Bug 1970980 - Test for regional-indicator emoji handling with Windows-specific fonts
|
||||||
skip-if(!winWidget) pref(layout.css.font-variant-emoji.enabled,true) == 1970980-regional-indicators.html 1970980-regional-indicators-ref.html
|
skip-if(!winWidget) pref(layout.css.font-variant-emoji.enabled,true) == 1970980-regional-indicators.html 1970980-regional-indicators-ref.html
|
||||||
|
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-01.html 1971148-digits-color-font-01-ref.html
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-02.html 1971148-digits-color-font-01-ref.html
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-03.html 1971148-digits-color-font-03-ref.html
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-04.html 1971148-digits-color-font-03-ref.html
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-05.html 1971148-digits-color-font-01-ref.html
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-06.html 1971148-digits-color-font-01-ref.html
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-07.html 1971148-digits-color-font-03-ref.html
|
||||||
|
pref(layout.css.font-variant-emoji.enabled,true) == 1971148-digits-color-font-08.html 1971148-digits-color-font-03-ref.html
|
||||||
|
|||||||
Reference in New Issue
Block a user