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

@ -47,9 +47,9 @@ use webrender_api::units::{
};
use webrender_api::{
self, BuiltDisplayList, DirtyRect, DisplayListPayload, DocumentId, Epoch as WebRenderEpoch,
ExternalScrollId, HitTestFlags, PipelineId as WebRenderPipelineId, PropertyBinding,
ReferenceFrameKind, RenderReasons, SampledScrollOffset, ScrollLocation, SpaceAndClipInfo,
SpatialId, SpatialTreeItemKey, TransformStyle,
ExternalScrollId, FontInstanceOptions, HitTestFlags, PipelineId as WebRenderPipelineId,
PropertyBinding, ReferenceFrameKind, RenderReasons, SampledScrollOffset, ScrollLocation,
SpaceAndClipInfo, SpatialId, SpatialTreeItemKey, TransformStyle,
};
use crate::gl::RenderTargetInfo;
@ -871,13 +871,25 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
ForwardedToCompositorMsg::Font(FontToCompositorMsg::AddFontInstance(
font_key,
size,
flags,
sender,
)) => {
let key = self.webrender_api.generate_font_instance_key();
let mut txn = Transaction::new();
txn.add_font_instance(key, font_key, size, None, None, Vec::new());
let mut transaction = Transaction::new();
let mut font_instance_options = FontInstanceOptions::default();
font_instance_options.flags = flags;
transaction.add_font_instance(
key,
font_key,
size,
Some(font_instance_options),
None,
Vec::new(),
);
self.webrender_api
.send_transaction(self.webrender_document, txn);
.send_transaction(self.webrender_document, transaction);
let _ = sender.send(key);
},
@ -951,7 +963,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
let _ = sender.send(());
},
CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
FontToCompositorMsg::AddFontInstance(_, _, sender),
FontToCompositorMsg::AddFontInstance(_, _, _, sender),
)) => {
let _ = sender.send(self.webrender_api.generate_font_instance_key());
},

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)
}

View file

@ -90,7 +90,8 @@ use surfman::{GLApi, GLVersion};
use surfman::{NativeConnection, NativeContext};
use webrender::{RenderApiSender, ShaderPrecacheFlags};
use webrender_api::{
ColorF, DocumentId, FontInstanceKey, FontKey, FramePublishId, ImageKey, NativeFontHandle,
ColorF, DocumentId, FontInstanceFlags, FontInstanceKey, FontKey, FramePublishId, ImageKey,
NativeFontHandle,
};
use webrender_traits::{
WebrenderExternalImageHandlers, WebrenderExternalImageRegistry, WebrenderImageHandlerType,
@ -1043,12 +1044,17 @@ fn create_constellation(
struct FontCacheWR(CompositorProxy);
impl gfx_traits::WebrenderApi for FontCacheWR {
fn add_font_instance(&self, font_key: FontKey, size: f32) -> FontInstanceKey {
fn add_font_instance(
&self,
font_key: FontKey,
size: f32,
flags: FontInstanceFlags,
) -> FontInstanceKey {
let (sender, receiver) = unbounded();
let _ = self
.0
.send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
FontToCompositorMsg::AddFontInstance(font_key, size, sender),
FontToCompositorMsg::AddFontInstance(font_key, size, flags, sender),
)));
receiver.recv().unwrap()
}

View file

@ -25,7 +25,9 @@ use script_traits::{
};
use style_traits::CSSPixel;
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, DeviceRect};
use webrender_api::{self, FontInstanceKey, FontKey, ImageKey, NativeFontHandle};
use webrender_api::{
self, FontInstanceFlags, FontInstanceKey, FontKey, ImageKey, NativeFontHandle,
};
/// Sends messages to the compositor.
pub struct CompositorProxy {
@ -139,7 +141,7 @@ pub struct CompositionPipeline {
}
pub enum FontToCompositorMsg {
AddFontInstance(FontKey, f32, Sender<FontInstanceKey>),
AddFontInstance(FontKey, f32, FontInstanceFlags, Sender<FontInstanceKey>),
AddFont(Sender<FontKey>, u32, ipc_channel::ipc::IpcBytesReceiver),
AddSystemFont(Sender<FontKey>, NativeFontHandle),
}

View file

@ -14,7 +14,9 @@ use std::sync::Arc;
use malloc_size_of_derive::MallocSizeOf;
use range::{int_range_index, RangeIndex};
use serde::{Deserialize, Serialize};
use webrender_api::{Epoch as WebRenderEpoch, FontInstanceKey, FontKey, NativeFontHandle};
use webrender_api::{
Epoch as WebRenderEpoch, FontInstanceFlags, FontInstanceKey, FontKey, NativeFontHandle,
};
/// A newtype struct for denoting the age of messages; prevents race conditions.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
@ -121,7 +123,12 @@ pub fn node_id_from_scroll_id(id: usize) -> Option<usize> {
}
pub trait WebrenderApi {
fn add_font_instance(&self, font_key: FontKey, size: f32) -> FontInstanceKey;
fn add_font_instance(
&self,
font_key: FontKey,
size: f32,
flags: FontInstanceFlags,
) -> FontInstanceKey;
fn add_font(&self, data: Arc<Vec<u8>>, index: u32) -> FontKey;
fn add_system_font(&self, handle: NativeFontHandle) -> FontKey;
}

343
tests/html/emoji-list.html Normal file

File diff suppressed because one or more lines are too long