fonts: Use FontInstanceFlags::EMBEDDED_BITMAPS for color fonts on MacOS (#32203)

This flag ensures that these fonts are rendered full color in WebRender,
allowing for full color emoji.
This commit is contained in:
Martin Robinson 2024-05-02 08:50:59 +02:00 committed by GitHub
parent 60613e77c5
commit 928214518c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 471 additions and 38 deletions

View file

@ -23,7 +23,7 @@ use style::properties::style_structs::Font as FontStyleStruct;
use style::values::computed::font::{GenericFontFamily, SingleFontFamily};
use style::values::computed::{FontStretch, FontStyle, FontWeight};
use unicode_script::Script;
use webrender_api::FontInstanceKey;
use webrender_api::{FontInstanceFlags, FontInstanceKey};
use crate::font_cache_thread::FontIdentifier;
use crate::font_context::{FontContext, FontSource};
@ -44,6 +44,10 @@ macro_rules! ot_tag {
pub const GPOS: u32 = ot_tag!('G', 'P', 'O', 'S');
pub const GSUB: u32 = ot_tag!('G', 'S', 'U', 'B');
pub const KERN: u32 = ot_tag!('k', 'e', 'r', 'n');
pub const SBIX: u32 = ot_tag!('s', 'b', 'i', 'x');
pub const CBDT: u32 = ot_tag!('C', 'B', 'D', 'T');
pub const COLR: u32 = ot_tag!('C', 'O', 'L', 'R');
pub const LAST_RESORT_GLYPH_ADVANCE: FractionalPixel = 10.0;
static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = AtomicUsize::new(0);
@ -83,6 +87,9 @@ pub trait PlatformFontMethods: Sized {
fn can_do_fast_shaping(&self) -> bool;
fn metrics(&self) -> FontMetrics;
fn table_for_tag(&self, _: FontTableTag) -> Option<FontTable>;
/// Get the necessary [`FontInstanceFlags`]` for this font.
fn webrender_font_instance_flags(&self) -> FontInstanceFlags;
}
// Used to abstract over the shaper's choice of fixed int representation.
@ -195,7 +202,6 @@ impl Font {
pub fn new(
template: FontTemplateRef,
descriptor: FontDescriptor,
font_key: FontInstanceKey,
synthesized_small_caps: Option<FontRef>,
) -> Result<Font, &'static str> {
let handle = PlatformFont::new_from_template(template.clone(), Some(descriptor.pt_size))?;
@ -209,7 +215,7 @@ impl Font {
metrics,
shape_cache: RefCell::new(HashMap::new()),
glyph_advance_cache: RefCell::new(HashMap::new()),
font_key,
font_key: FontInstanceKey::default(),
synthesized_small_caps,
})
}
@ -218,6 +224,10 @@ impl Font {
pub fn identifier(&self) -> FontIdentifier {
self.template.identifier()
}
pub fn webrender_font_instance_flags(&self) -> FontInstanceFlags {
self.handle.webrender_font_instance_flags()
}
}
bitflags! {

View file

@ -29,7 +29,7 @@ use style::stylesheets::{Stylesheet, StylesheetInDocument};
use style::values::computed::font::{FixedPoint, FontStyleFixedPoint};
use style::values::computed::{FontStretch, FontWeight};
use style::values::specified::FontStretch as SpecifiedFontStretch;
use webrender_api::{FontInstanceKey, FontKey};
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey};
use crate::font::{FontDescriptor, FontFamilyDescriptor, FontFamilyName, FontSearchScope};
use crate::font_context::FontSource;
@ -137,7 +137,12 @@ pub enum Command {
FontFamilyDescriptor,
IpcSender<Vec<SerializedFontTemplate>>,
),
GetFontInstance(FontIdentifier, Au, IpcSender<FontInstanceKey>),
GetFontInstance(
FontIdentifier,
Au,
FontInstanceFlags,
IpcSender<FontInstanceKey>,
),
AddWebFont(CSSFontFaceDescriptors, Vec<Source>, IpcSender<()>),
AddDownloadedWebFont(CSSFontFaceDescriptors, ServoUrl, Vec<u8>, IpcSender<()>),
Exit(IpcSender<()>),
@ -229,8 +234,8 @@ impl FontCache {
let _ = bytes_sender.send(&data);
}
},
Command::GetFontInstance(identifier, pt_size, result) => {
let _ = result.send(self.get_font_instance(identifier, pt_size));
Command::GetFontInstance(identifier, pt_size, flags, result) => {
let _ = result.send(self.get_font_instance(identifier, pt_size, flags));
},
Command::AddWebFont(css_font_face_descriptors, sources, result) => {
self.handle_add_web_font(css_font_face_descriptors, sources, result);
@ -436,7 +441,12 @@ impl FontCache {
self.find_templates_in_local_family(descriptor_to_match, &family_descriptor.name)
}
fn get_font_instance(&mut self, identifier: FontIdentifier, pt_size: Au) -> FontInstanceKey {
fn get_font_instance(
&mut self,
identifier: FontIdentifier,
pt_size: Au,
flags: FontInstanceFlags,
) -> FontInstanceKey {
let webrender_api = &self.webrender_api;
let webrender_fonts = &mut self.webrender_fonts;
let font_data = self
@ -465,7 +475,9 @@ impl FontCache {
*self
.font_instances
.entry((font_key, pt_size))
.or_insert_with(|| webrender_api.add_font_instance(font_key, pt_size.to_f32_px()))
.or_insert_with(|| {
webrender_api.add_font_instance(font_key, pt_size.to_f32_px(), flags)
})
}
}
@ -661,10 +673,20 @@ impl FontCacheThread {
}
impl FontSource for FontCacheThread {
fn get_font_instance(&mut self, identifier: FontIdentifier, size: Au) -> FontInstanceKey {
fn get_font_instance(
&mut self,
identifier: FontIdentifier,
size: Au,
flags: FontInstanceFlags,
) -> FontInstanceKey {
let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel");
self.chan
.send(Command::GetFontInstance(identifier, size, response_chan))
.send(Command::GetFontInstance(
identifier,
size,
flags,
response_chan,
))
.expect("failed to send message to font cache thread");
let instance_key = response_port.recv();

View file

@ -15,7 +15,7 @@ use log::debug;
use servo_arc::Arc;
use style::computed_values::font_variant_caps::T as FontVariantCaps;
use style::properties::style_structs::Font as FontStyleStruct;
use webrender_api::FontInstanceKey;
use webrender_api::{FontInstanceFlags, FontInstanceKey};
use crate::font::{Font, FontDescriptor, FontFamilyDescriptor, FontGroup, FontRef};
use crate::font_cache_thread::FontIdentifier;
@ -30,7 +30,12 @@ static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h)
static FONT_CACHE_EPOCH: AtomicUsize = AtomicUsize::new(0);
pub trait FontSource {
fn get_font_instance(&mut self, font_identifier: FontIdentifier, size: Au) -> FontInstanceKey;
fn get_font_instance(
&mut self,
font_identifier: FontIdentifier,
size: Au,
flags: FontInstanceFlags,
) -> FontInstanceKey;
fn find_matching_font_templates(
&mut self,
descriptor_to_match: &FontDescriptor,
@ -206,16 +211,18 @@ impl<S: FontSource> FontContext<S> {
font_descriptor: FontDescriptor,
synthesized_small_caps: Option<FontRef>,
) -> Result<FontRef, &'static str> {
let font_instance_key = self
.font_source
.get_font_instance(font_template.identifier(), font_descriptor.pt_size);
Ok(Rc::new(RefCell::new(Font::new(
font_template,
font_descriptor,
font_instance_key,
let mut font = Font::new(
font_template.clone(),
font_descriptor.clone(),
synthesized_small_caps,
)?)))
)?;
font.font_key = self.font_source.get_font_instance(
font_template.identifier(),
font_descriptor.pt_size,
font.webrender_font_instance_flags(),
);
Ok(Rc::new(RefCell::new(font)))
}
}

View file

@ -20,6 +20,7 @@ use log::debug;
use style::computed_values::font_stretch::T as FontStretch;
use style::computed_values::font_weight::T as FontWeight;
use style::values::computed::font::FontStyle;
use webrender_api::FontInstanceFlags;
use super::library_handle::FreeTypeLibraryHandle;
use crate::font::{
@ -313,6 +314,10 @@ impl PlatformFontMethods for PlatformFont {
Some(FontTable { buffer: buf })
}
}
fn webrender_font_instance_flags(&self) -> FontInstanceFlags {
FontInstanceFlags::empty()
}
}
impl<'a> PlatformFont {

View file

@ -19,11 +19,12 @@ use core_text::font_descriptor::{
};
use log::debug;
use style::values::computed::font::{FontStretch, FontStyle, FontWeight};
use webrender_api::FontInstanceFlags;
use super::core_text_font_cache::CoreTextFontCache;
use crate::font::{
map_platform_values_to_style_values, FontMetrics, FontTableMethods, FontTableTag,
FractionalPixel, PlatformFontMethods, GPOS, GSUB, KERN,
FractionalPixel, PlatformFontMethods, CBDT, COLR, GPOS, GSUB, KERN, SBIX,
};
use crate::font_cache_thread::FontIdentifier;
use crate::font_template::FontTemplateDescriptor;
@ -298,6 +299,18 @@ impl PlatformFontMethods for PlatformFont {
let result: Option<CFData> = self.ctfont.get_font_table(tag);
result.map(FontTable::wrap)
}
/// Get the necessary [`FontInstanceFlags`]` for this font.
fn webrender_font_instance_flags(&self) -> FontInstanceFlags {
// TODO: Should this also validate these tables?
if self.table_for_tag(COLR).is_some() ||
self.table_for_tag(CBDT).is_some() ||
self.table_for_tag(SBIX).is_some()
{
return FontInstanceFlags::EMBEDDED_BITMAPS;
}
FontInstanceFlags::empty()
}
}
pub(super) trait CoreTextFontTraitsMapping {

View file

@ -20,6 +20,7 @@ use style::computed_values::font_weight::T as StyleFontWeight;
use style::values::computed::font::FontStyle as StyleFontStyle;
use truetype::tables::WindowsMetrics;
use truetype::value::Read;
use webrender_api::FontInstanceFlags;
use crate::font::{
FontMetrics, FontTableMethods, FontTableTag, FractionalPixel, PlatformFontMethods,
@ -254,4 +255,8 @@ impl PlatformFontMethods for PlatformFont {
.get_font_table(tag)
.map(|bytes| FontTable { data: bytes })
}
fn webrender_font_instance_flags(&self) -> FontInstanceFlags {
FontInstanceFlags::empty()
}
}

View file

@ -27,7 +27,7 @@ use style::values::computed::font::{
};
use style::values::computed::{FontLanguageOverride, XLang};
use style::values::generics::font::LineHeight;
use webrender_api::{FontInstanceKey, IdNamespace};
use webrender_api::{FontInstanceFlags, FontInstanceKey, IdNamespace};
struct TestFontSource {
families: HashMap<String, FontTemplates>,
@ -92,6 +92,7 @@ impl FontSource for TestFontSource {
&mut self,
_font_identifier: FontIdentifier,
_size: Au,
_flags: FontInstanceFlags,
) -> FontInstanceKey {
FontInstanceKey(IdNamespace(0), 0)
}