mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
fonts: Simplify FontContext
in two ways that affect the unit test (#33541)
This is done by no longer forwarding compositor-bound messages through SystemFontService and making `FontContext` non-generic: - Messages from the `FontContext` to the `Compositor` no longer need to be forwarded through the `SystemFontService`. Instead send these messages directly through the script IPC channel to the `Compositor`. - Instead of adding a mock `SystemFontServiceProxy`, simply implement a mock `SystemFontService` on the other side of an IPC channel in the `font_context` unit test. This allows making `FontContext` non-generic, greatly simplifying the code. The extra complexity moves into the unit test. These changes necessitate adding a new kind of `FontIdentifier`, `FontIdentifier::Mock` due to the fact that local fonts have platform-specific identifiers. This avoids having to pretend like the system font service can have web fonts -- which was always a bit of a hack. These two changes are combined into one PR because they both require extensive and similar chages in the font_context unit test which dependended on the details of both of them. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
1daa0b4fc7
commit
ac567645a7
25 changed files with 482 additions and 425 deletions
|
@ -11,7 +11,7 @@ use euclid::default::{Box2D, Point2D, Rect, Size2D, Transform2D, Vector2D};
|
|||
use euclid::point2;
|
||||
use fonts::{
|
||||
ByteIndex, FontBaseline, FontContext, FontGroup, FontMetrics, FontRef, GlyphInfo, GlyphStore,
|
||||
ShapingFlags, ShapingOptions, SystemFontServiceProxy, LAST_RESORT_GLYPH_ADVANCE,
|
||||
ShapingFlags, ShapingOptions, LAST_RESORT_GLYPH_ADVANCE,
|
||||
};
|
||||
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
||||
use log::{debug, warn};
|
||||
|
@ -434,7 +434,7 @@ pub struct CanvasData<'a> {
|
|||
old_image_key: Option<ImageKey>,
|
||||
/// An old webrender image key that can be deleted when the current epoch ends.
|
||||
very_old_image_key: Option<ImageKey>,
|
||||
font_context: Arc<FontContext<SystemFontServiceProxy>>,
|
||||
font_context: Arc<FontContext>,
|
||||
}
|
||||
|
||||
fn create_backend() -> Box<dyn Backend> {
|
||||
|
@ -446,7 +446,7 @@ impl<'a> CanvasData<'a> {
|
|||
size: Size2D<u64>,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
antialias: AntialiasMode,
|
||||
font_context: Arc<FontContext<SystemFontServiceProxy>>,
|
||||
font_context: Arc<FontContext>,
|
||||
) -> CanvasData<'a> {
|
||||
let backend = create_backend();
|
||||
let draw_target = backend.create_drawtarget(size);
|
||||
|
|
|
@ -17,7 +17,7 @@ use ipc_channel::router::ROUTER;
|
|||
use log::warn;
|
||||
use net_traits::ResourceThreads;
|
||||
use webrender_api::ImageKey;
|
||||
use webrender_traits::ImageUpdate;
|
||||
use webrender_traits::{ImageUpdate, WebRenderScriptApi};
|
||||
|
||||
use crate::canvas_data::*;
|
||||
|
||||
|
@ -37,7 +37,7 @@ pub struct CanvasPaintThread<'a> {
|
|||
canvases: HashMap<CanvasId, CanvasData<'a>>,
|
||||
next_canvas_id: CanvasId,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
font_context: Arc<FontContext<SystemFontServiceProxy>>,
|
||||
font_context: Arc<FontContext>,
|
||||
}
|
||||
|
||||
impl<'a> CanvasPaintThread<'a> {
|
||||
|
@ -46,11 +46,18 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
system_font_service: Arc<SystemFontServiceProxy>,
|
||||
resource_threads: ResourceThreads,
|
||||
) -> CanvasPaintThread<'a> {
|
||||
// This is only used for web fonts and currently canvas never uses web fonts.
|
||||
let webrender_script_api = WebRenderScriptApi::dummy();
|
||||
|
||||
CanvasPaintThread {
|
||||
canvases: HashMap::new(),
|
||||
next_canvas_id: CanvasId(0),
|
||||
webrender_api,
|
||||
font_context: Arc::new(FontContext::new(system_font_service, resource_threads)),
|
||||
font_context: Arc::new(FontContext::new(
|
||||
system_font_service,
|
||||
webrender_script_api,
|
||||
resource_threads,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::fs::{create_dir_all, File};
|
|||
use std::io::Write;
|
||||
use std::iter::once;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use base::cross_process_instant::CrossProcessInstant;
|
||||
|
@ -23,7 +24,7 @@ use embedder_traits::Cursor;
|
|||
use euclid::{Point2D, Rect, Scale, Transform3D, Vector2D};
|
||||
use fnv::{FnvHashMap, FnvHashSet};
|
||||
use image::{DynamicImage, ImageFormat};
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
||||
use libc::c_void;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use pixels::{CorsStatus, Image, PixelFormat};
|
||||
|
@ -43,9 +44,10 @@ use webrender_api::units::{
|
|||
};
|
||||
use webrender_api::{
|
||||
self, BuiltDisplayList, DirtyRect, DisplayListPayload, DocumentId, Epoch as WebRenderEpoch,
|
||||
ExternalScrollId, FontInstanceOptions, HitTestFlags, PipelineId as WebRenderPipelineId,
|
||||
PropertyBinding, ReferenceFrameKind, RenderReasons, SampledScrollOffset, ScrollLocation,
|
||||
SpaceAndClipInfo, SpatialId, SpatialTreeItemKey, TransformStyle,
|
||||
ExternalScrollId, FontInstanceFlags, FontInstanceKey, FontInstanceOptions, FontKey,
|
||||
HitTestFlags, PipelineId as WebRenderPipelineId, PropertyBinding, ReferenceFrameKind,
|
||||
RenderReasons, SampledScrollOffset, ScrollLocation, SpaceAndClipInfo, SpatialId,
|
||||
SpatialTreeItemKey, TransformStyle,
|
||||
};
|
||||
use webrender_traits::display_list::{HitTestInfo, ScrollTree};
|
||||
use webrender_traits::{
|
||||
|
@ -841,6 +843,23 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFont(
|
||||
data,
|
||||
index,
|
||||
key_sender,
|
||||
)) => {
|
||||
let _ = key_sender.send(self.add_font(index, data));
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFontInstance(
|
||||
font_key,
|
||||
size,
|
||||
flags,
|
||||
sender,
|
||||
)) => {
|
||||
let _ = sender.send(self.add_font_instance(font_key, size, flags));
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::RemoveFonts(
|
||||
keys,
|
||||
instance_keys,
|
||||
|
@ -865,47 +884,24 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Font(FontToCompositorMsg::AddFontInstance(
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance(
|
||||
font_key,
|
||||
size,
|
||||
flags,
|
||||
sender,
|
||||
)) => {
|
||||
let key = self.webrender_api.generate_font_instance_key();
|
||||
let mut transaction = Transaction::new();
|
||||
|
||||
let font_instance_options = FontInstanceOptions {
|
||||
flags,
|
||||
..Default::default()
|
||||
};
|
||||
transaction.add_font_instance(
|
||||
key,
|
||||
font_key,
|
||||
size,
|
||||
Some(font_instance_options),
|
||||
None,
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
let _ = sender.send(key);
|
||||
let _ = sender.send(self.add_font_instance(font_key, size, flags));
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Font(FontToCompositorMsg::AddFont(
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont(
|
||||
key_sender,
|
||||
index,
|
||||
data,
|
||||
)) => {
|
||||
let font_key = self.webrender_api.generate_font_key();
|
||||
let mut transaction = Transaction::new();
|
||||
transaction.add_raw_font(font_key, (**data).into(), index);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
let _ = key_sender.send(font_key);
|
||||
let _ = key_sender.send(self.add_font(index, data));
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Font(FontToCompositorMsg::AddSystemFont(
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddSystemFont(
|
||||
key_sender,
|
||||
native_handle,
|
||||
)) => {
|
||||
|
@ -960,16 +956,26 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
self.remove_pipeline_root_layer(pipeline_id);
|
||||
let _ = sender.send(());
|
||||
},
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::SystemFontService(
|
||||
FontToCompositorMsg::AddFontInstance(_, _, _, sender),
|
||||
)) => {
|
||||
let _ = sender.send(self.webrender_api.generate_font_instance_key());
|
||||
},
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::Layout(
|
||||
ScriptToCompositorMsg::AddFontInstance(_, _, _, sender),
|
||||
)) => {
|
||||
let _ = sender.send(self.webrender_api.generate_font_instance_key());
|
||||
},
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::SystemFontService(
|
||||
FontToCompositorMsg::AddFont(sender, _, _),
|
||||
)) => {
|
||||
let _ = sender.send(self.webrender_api.generate_font_key());
|
||||
},
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::Layout(
|
||||
ScriptToCompositorMsg::AddFont(_, _, sender),
|
||||
)) => {
|
||||
let _ = sender.send(self.webrender_api.generate_font_key());
|
||||
},
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas(
|
||||
CanvasToCompositorMsg::GenerateKey(sender),
|
||||
)) => {
|
||||
|
@ -2518,4 +2524,40 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
eprintln!("Unable to write servo version for WebRender Capture: {error:?}");
|
||||
}
|
||||
}
|
||||
|
||||
fn add_font_instance(
|
||||
&mut self,
|
||||
font_key: FontKey,
|
||||
size: f32,
|
||||
flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey {
|
||||
let instance_key = self.webrender_api.generate_font_instance_key();
|
||||
let mut transaction = Transaction::new();
|
||||
|
||||
let font_instance_options = FontInstanceOptions {
|
||||
flags,
|
||||
..Default::default()
|
||||
};
|
||||
transaction.add_font_instance(
|
||||
instance_key,
|
||||
font_key,
|
||||
size,
|
||||
Some(font_instance_options),
|
||||
None,
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
instance_key
|
||||
}
|
||||
|
||||
fn add_font(&mut self, index: u32, data: Arc<IpcSharedMemory>) -> FontKey {
|
||||
let font_key = self.webrender_api.generate_font_key();
|
||||
let mut transaction = Transaction::new();
|
||||
transaction.add_raw_font(font_key, (**data).into(), index);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
font_key
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ use crate::font_context::FontContext;
|
|||
use crate::font_template::{FontTemplateDescriptor, FontTemplateRef, FontTemplateRefMethods};
|
||||
use crate::platform::font::{FontTable, PlatformFont};
|
||||
pub use crate::platform::font_list::fallback_font_families;
|
||||
use crate::system_font_service::{FontIdentifier, SystemFontServiceProxyTrait};
|
||||
use crate::system_font_service::FontIdentifier;
|
||||
use crate::{
|
||||
ByteIndex, EmojiPresentationPreference, FallbackFontSelectionOptions, FontData, GlyphData,
|
||||
GlyphId, GlyphStore, Shaper,
|
||||
|
@ -550,9 +550,9 @@ impl FontGroup {
|
|||
/// `codepoint`. If no such font is found, returns the first available font or fallback font
|
||||
/// (which will cause a "glyph not found" character to be rendered). If no font at all can be
|
||||
/// found, returns None.
|
||||
pub fn find_by_codepoint<S: SystemFontServiceProxyTrait>(
|
||||
pub fn find_by_codepoint(
|
||||
&mut self,
|
||||
font_context: &FontContext<S>,
|
||||
font_context: &FontContext,
|
||||
codepoint: char,
|
||||
next_codepoint: Option<char>,
|
||||
) -> Option<FontRef> {
|
||||
|
@ -622,10 +622,7 @@ impl FontGroup {
|
|||
}
|
||||
|
||||
/// Find the first available font in the group, or the first available fallback font.
|
||||
pub fn first<S: SystemFontServiceProxyTrait>(
|
||||
&mut self,
|
||||
font_context: &FontContext<S>,
|
||||
) -> Option<FontRef> {
|
||||
pub fn first(&mut self, font_context: &FontContext) -> Option<FontRef> {
|
||||
// From https://drafts.csswg.org/css-fonts/#first-available-font:
|
||||
// > The first available font, used for example in the definition of font-relative lengths
|
||||
// > such as ex or in the definition of the line-height property, is defined to be the first
|
||||
|
@ -649,14 +646,13 @@ impl FontGroup {
|
|||
/// Attempts to find a font which matches the given `template_predicate` and `font_predicate`.
|
||||
/// This method mutates because we may need to load new font data in the process of finding
|
||||
/// a suitable font.
|
||||
fn find<S, TemplatePredicate, FontPredicate>(
|
||||
fn find<TemplatePredicate, FontPredicate>(
|
||||
&mut self,
|
||||
font_context: &FontContext<S>,
|
||||
font_context: &FontContext,
|
||||
template_predicate: TemplatePredicate,
|
||||
font_predicate: FontPredicate,
|
||||
) -> Option<FontRef>
|
||||
where
|
||||
S: SystemFontServiceProxyTrait,
|
||||
TemplatePredicate: Fn(FontTemplateRef) -> bool,
|
||||
FontPredicate: Fn(&FontRef) -> bool,
|
||||
{
|
||||
|
@ -678,15 +674,14 @@ impl FontGroup {
|
|||
/// `font_predicate`. The default family (i.e. "serif") will be tried first, followed by
|
||||
/// platform-specific family names. If a `codepoint` is provided, then its Unicode block may be
|
||||
/// used to refine the list of family names which will be tried.
|
||||
fn find_fallback<S, TemplatePredicate, FontPredicate>(
|
||||
fn find_fallback<TemplatePredicate, FontPredicate>(
|
||||
&mut self,
|
||||
font_context: &FontContext<S>,
|
||||
font_context: &FontContext,
|
||||
options: FallbackFontSelectionOptions,
|
||||
template_predicate: TemplatePredicate,
|
||||
font_predicate: FontPredicate,
|
||||
) -> Option<FontRef>
|
||||
where
|
||||
S: SystemFontServiceProxyTrait,
|
||||
TemplatePredicate: Fn(FontTemplateRef) -> bool,
|
||||
FontPredicate: Fn(&FontRef) -> bool,
|
||||
{
|
||||
|
@ -750,15 +745,14 @@ impl FontGroupFamily {
|
|||
}
|
||||
}
|
||||
|
||||
fn find<S, TemplatePredicate, FontPredicate>(
|
||||
fn find<TemplatePredicate, FontPredicate>(
|
||||
&mut self,
|
||||
font_descriptor: &FontDescriptor,
|
||||
font_context: &FontContext<S>,
|
||||
font_context: &FontContext,
|
||||
template_predicate: &TemplatePredicate,
|
||||
font_predicate: &FontPredicate,
|
||||
) -> Option<FontRef>
|
||||
where
|
||||
S: SystemFontServiceProxyTrait,
|
||||
TemplatePredicate: Fn(FontTemplateRef) -> bool,
|
||||
FontPredicate: Fn(&FontRef) -> bool,
|
||||
{
|
||||
|
@ -781,10 +775,10 @@ impl FontGroupFamily {
|
|||
.next()
|
||||
}
|
||||
|
||||
fn members<S: SystemFontServiceProxyTrait>(
|
||||
fn members(
|
||||
&mut self,
|
||||
font_descriptor: &FontDescriptor,
|
||||
font_context: &FontContext<S>,
|
||||
font_context: &FontContext,
|
||||
) -> impl Iterator<Item = &mut FontGroupFamilyMember> {
|
||||
let family_descriptor = &self.family_descriptor;
|
||||
let members = self.members.get_or_insert_with(|| {
|
||||
|
|
|
@ -12,6 +12,7 @@ use app_units::Au;
|
|||
use crossbeam_channel::unbounded;
|
||||
use fnv::FnvHasher;
|
||||
use fonts_traits::WebFontLoadFinishedCallback;
|
||||
use ipc_channel::ipc;
|
||||
use log::{debug, trace};
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
|
@ -29,7 +30,8 @@ use style::stylesheets::{CssRule, DocumentStyleSheet, FontFaceRule, StylesheetIn
|
|||
use style::values::computed::font::{FamilyName, FontFamilyNameSyntax, SingleFontFamily};
|
||||
use style::Atom;
|
||||
use url::Url;
|
||||
use webrender_api::{FontInstanceKey, FontKey};
|
||||
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey};
|
||||
use webrender_traits::{ScriptToCompositorMsg, WebRenderScriptApi};
|
||||
|
||||
use crate::font::{
|
||||
Font, FontDescriptor, FontFamilyDescriptor, FontGroup, FontRef, FontSearchScope,
|
||||
|
@ -37,10 +39,8 @@ use crate::font::{
|
|||
use crate::font_store::{CrossThreadFontStore, CrossThreadWebRenderFontStore};
|
||||
use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods};
|
||||
use crate::platform::font::PlatformFont;
|
||||
use crate::system_font_service::{
|
||||
CSSFontFaceDescriptors, FontIdentifier, SystemFontServiceProxyTrait,
|
||||
};
|
||||
use crate::{FontData, LowercaseFontFamilyName, PlatformFontMethods};
|
||||
use crate::system_font_service::{CSSFontFaceDescriptors, FontIdentifier};
|
||||
use crate::{FontData, LowercaseFontFamilyName, PlatformFontMethods, SystemFontServiceProxy};
|
||||
|
||||
static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h)
|
||||
|
||||
|
@ -48,10 +48,13 @@ static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h)
|
|||
/// working with fonts. It is the public API used by the layout and
|
||||
/// paint code. It talks directly to the system font service where
|
||||
/// required.
|
||||
pub struct FontContext<Proxy: SystemFontServiceProxyTrait> {
|
||||
pub(crate) system_font_service_proxy: Arc<Proxy>,
|
||||
pub struct FontContext {
|
||||
pub(crate) system_font_service_proxy: Arc<SystemFontServiceProxy>,
|
||||
resource_threads: ReentrantMutex<CoreResourceThread>,
|
||||
|
||||
/// A sender that can send messages and receive replies from the compositor.
|
||||
webrender_api: ReentrantMutex<WebRenderScriptApi>,
|
||||
|
||||
/// The actual instances of fonts ie a [`FontTemplate`] combined with a size and
|
||||
/// other font properties, along with the font data and a platform font instance.
|
||||
fonts: RwLock<HashMap<FontCacheKey, Option<FontRef>>>,
|
||||
|
@ -67,7 +70,7 @@ pub struct FontContext<Proxy: SystemFontServiceProxyTrait> {
|
|||
have_removed_web_fonts: AtomicBool,
|
||||
}
|
||||
|
||||
impl<S: SystemFontServiceProxyTrait> MallocSizeOf for FontContext<S> {
|
||||
impl MallocSizeOf for FontContext {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let font_cache_size = self
|
||||
.fonts
|
||||
|
@ -87,12 +90,17 @@ impl<S: SystemFontServiceProxyTrait> MallocSizeOf for FontContext<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Proxy: SystemFontServiceProxyTrait> FontContext<Proxy> {
|
||||
pub fn new(system_font_service_proxy: Arc<Proxy>, resource_threads: ResourceThreads) -> Self {
|
||||
impl FontContext {
|
||||
pub fn new(
|
||||
system_font_service_proxy: Arc<SystemFontServiceProxy>,
|
||||
webrender_api: WebRenderScriptApi,
|
||||
resource_threads: ResourceThreads,
|
||||
) -> Self {
|
||||
#[allow(clippy::default_constructed_unit_structs)]
|
||||
Self {
|
||||
system_font_service_proxy,
|
||||
resource_threads: ReentrantMutex::new(resource_threads.core_thread),
|
||||
webrender_api: ReentrantMutex::new(webrender_api),
|
||||
fonts: Default::default(),
|
||||
resolved_font_groups: Default::default(),
|
||||
web_fonts: Arc::new(RwLock::default()),
|
||||
|
@ -106,11 +114,13 @@ impl<Proxy: SystemFontServiceProxyTrait> FontContext<Proxy> {
|
|||
}
|
||||
|
||||
pub(crate) fn get_font_data(&self, identifier: &FontIdentifier) -> Arc<FontData> {
|
||||
self.web_fonts
|
||||
.read()
|
||||
.get_font_data(identifier)
|
||||
.or_else(|| self.system_font_service_proxy.get_font_data(identifier))
|
||||
.expect("Could not find font data")
|
||||
match identifier {
|
||||
FontIdentifier::Web(_) => self.web_fonts.read().get_font_data(identifier),
|
||||
FontIdentifier::Local(_) | FontIdentifier::Mock(_) => {
|
||||
self.system_font_service_proxy.get_font_data(identifier)
|
||||
},
|
||||
}
|
||||
.expect("Could not find font data")
|
||||
}
|
||||
|
||||
/// Handle the situation where a web font finishes loading, specifying if the load suceeded or failed.
|
||||
|
@ -272,11 +282,13 @@ impl<Proxy: SystemFontServiceProxyTrait> FontContext<Proxy> {
|
|||
)?;
|
||||
|
||||
font.font_key = match font_template.identifier() {
|
||||
FontIdentifier::Local(_) => self.system_font_service_proxy.get_system_font_instance(
|
||||
font_template.identifier(),
|
||||
font_descriptor.pt_size,
|
||||
font.webrender_font_instance_flags(),
|
||||
),
|
||||
FontIdentifier::Local(_) | FontIdentifier::Mock(_) => {
|
||||
self.system_font_service_proxy.get_system_font_instance(
|
||||
font_template.identifier(),
|
||||
font_descriptor.pt_size,
|
||||
font.webrender_font_instance_flags(),
|
||||
)
|
||||
},
|
||||
FontIdentifier::Web(_) => self.webrender_font_store.write().get_font_instance(
|
||||
self,
|
||||
font_template.clone(),
|
||||
|
@ -291,6 +303,42 @@ impl<Proxy: SystemFontServiceProxyTrait> FontContext<Proxy> {
|
|||
fn invalidate_font_groups_after_web_font_load(&self) {
|
||||
self.resolved_font_groups.write().clear();
|
||||
}
|
||||
|
||||
pub(crate) fn get_web_font(&self, data: Arc<FontData>, index: u32) -> FontKey {
|
||||
let (result_sender, result_receiver) =
|
||||
ipc::channel().expect("failed to create IPC channel");
|
||||
let _ = self
|
||||
.webrender_api
|
||||
.lock()
|
||||
.sender()
|
||||
.send(ScriptToCompositorMsg::AddFont(
|
||||
data.as_ipc_shared_memory(),
|
||||
index,
|
||||
result_sender,
|
||||
));
|
||||
result_receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn get_web_font_instance(
|
||||
&self,
|
||||
font_key: FontKey,
|
||||
font_size: f32,
|
||||
font_flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey {
|
||||
let (result_sender, result_receiver) =
|
||||
ipc::channel().expect("failed to create IPC channel");
|
||||
let _ = self
|
||||
.webrender_api
|
||||
.lock()
|
||||
.sender()
|
||||
.send(ScriptToCompositorMsg::AddFontInstance(
|
||||
font_key,
|
||||
font_size,
|
||||
font_flags,
|
||||
result_sender,
|
||||
));
|
||||
result_receiver.recv().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -318,7 +366,7 @@ pub trait FontContextWebFontMethods {
|
|||
-> (Vec<FontKey>, Vec<FontInstanceKey>);
|
||||
}
|
||||
|
||||
impl<S: SystemFontServiceProxyTrait + 'static> FontContextWebFontMethods for Arc<FontContext<S>> {
|
||||
impl FontContextWebFontMethods for Arc<FontContext> {
|
||||
fn add_all_web_fonts_from_stylesheet(
|
||||
&self,
|
||||
stylesheet: &DocumentStyleSheet,
|
||||
|
@ -523,8 +571,8 @@ impl<S: SystemFontServiceProxyTrait + 'static> FontContextWebFontMethods for Arc
|
|||
}
|
||||
}
|
||||
|
||||
struct RemoteWebFontDownloader<Proxy: SystemFontServiceProxyTrait> {
|
||||
font_context: Arc<FontContext<Proxy>>,
|
||||
struct RemoteWebFontDownloader {
|
||||
font_context: Arc<FontContext>,
|
||||
url: ServoArc<Url>,
|
||||
web_font_family_name: LowercaseFontFamilyName,
|
||||
response_valid: Mutex<bool>,
|
||||
|
@ -537,10 +585,10 @@ enum DownloaderResponseResult {
|
|||
Failure,
|
||||
}
|
||||
|
||||
impl<Proxy: SystemFontServiceProxyTrait + 'static> RemoteWebFontDownloader<Proxy> {
|
||||
impl RemoteWebFontDownloader {
|
||||
fn download(
|
||||
url_source: UrlSource,
|
||||
font_context: Arc<FontContext<Proxy>>,
|
||||
font_context: Arc<FontContext>,
|
||||
web_font_family_name: LowercaseFontFamilyName,
|
||||
state: WebFontDownloadState,
|
||||
) {
|
||||
|
@ -628,12 +676,11 @@ impl<Proxy: SystemFontServiceProxyTrait + 'static> RemoteWebFontDownloader<Proxy
|
|||
descriptor
|
||||
.override_values_with_css_font_template_descriptors(&state.css_font_face_descriptors);
|
||||
|
||||
let Ok(new_template) =
|
||||
FontTemplate::new_for_remote_web_font(url, descriptor, Some(state.stylesheet.clone()))
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let new_template = FontTemplate::new(
|
||||
FontIdentifier::Web(url),
|
||||
descriptor,
|
||||
Some(state.stylesheet.clone()),
|
||||
);
|
||||
let not_cancelled = self.font_context.web_fonts.write().handle_web_font_loaded(
|
||||
state,
|
||||
new_template,
|
||||
|
|
|
@ -18,9 +18,7 @@ use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey};
|
|||
use crate::font::FontDescriptor;
|
||||
use crate::font_context::WebFontDownloadState;
|
||||
use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods, IsOblique};
|
||||
use crate::system_font_service::{
|
||||
FontIdentifier, LowercaseFontFamilyName, SystemFontServiceProxyTrait,
|
||||
};
|
||||
use crate::system_font_service::{FontIdentifier, LowercaseFontFamilyName};
|
||||
use crate::FontContext;
|
||||
|
||||
/// A data structure to store data for fonts. If sent across IPC channels and only a
|
||||
|
@ -171,7 +169,7 @@ impl FontStore {
|
|||
FontIdentifier::Local(local_identifier) => {
|
||||
Arc::new(FontData::from_bytes(local_identifier.read_data_from_file()))
|
||||
},
|
||||
FontIdentifier::Web(_) => unreachable!("Web fonts should always have data."),
|
||||
_ => unreachable!("Web and mock fonts should always have data."),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -196,9 +194,9 @@ pub struct WebRenderFontStore {
|
|||
pub(crate) type CrossThreadWebRenderFontStore = Arc<RwLock<WebRenderFontStore>>;
|
||||
|
||||
impl WebRenderFontStore {
|
||||
pub(crate) fn get_font_instance<Proxy: SystemFontServiceProxyTrait>(
|
||||
pub(crate) fn get_font_instance(
|
||||
&mut self,
|
||||
font_context: &FontContext<Proxy>,
|
||||
font_context: &FontContext,
|
||||
font_template: FontTemplateRef,
|
||||
pt_size: Au,
|
||||
flags: FontInstanceFlags,
|
||||
|
@ -210,18 +208,14 @@ impl WebRenderFontStore {
|
|||
.entry(identifier.clone())
|
||||
.or_insert_with(|| {
|
||||
let data = font_context.get_font_data(&identifier);
|
||||
font_context
|
||||
.system_font_service_proxy
|
||||
.get_web_font(data, identifier.index())
|
||||
font_context.get_web_font(data, identifier.index())
|
||||
});
|
||||
|
||||
*self
|
||||
.webrender_font_instance_map
|
||||
.entry((font_key, pt_size))
|
||||
.or_insert_with(|| {
|
||||
font_context
|
||||
.system_font_service_proxy
|
||||
.get_web_font_instance(font_key, pt_size.to_f32_px(), flags)
|
||||
font_context.get_web_font_instance(font_key, pt_size.to_f32_px(), flags)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -9,14 +9,12 @@ use std::sync::Arc;
|
|||
use atomic_refcell::AtomicRefCell;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use servo_url::ServoUrl;
|
||||
use style::computed_values::font_stretch::T as FontStretch;
|
||||
use style::computed_values::font_style::T as FontStyle;
|
||||
use style::stylesheets::DocumentStyleSheet;
|
||||
use style::values::computed::font::FontWeight;
|
||||
|
||||
use crate::font::FontDescriptor;
|
||||
use crate::platform::font_list::LocalFontIdentifier;
|
||||
use crate::system_font_service::{
|
||||
CSSFontFaceDescriptors, ComputedFontStyleDescriptor, FontIdentifier,
|
||||
};
|
||||
|
@ -160,29 +158,17 @@ impl Debug for FontTemplate {
|
|||
/// is common, regardless of the number of instances of
|
||||
/// this font handle per thread.
|
||||
impl FontTemplate {
|
||||
/// Create a new [`FontTemplate`] for a system font installed locally.
|
||||
pub fn new_for_local_font(
|
||||
identifier: LocalFontIdentifier,
|
||||
descriptor: FontTemplateDescriptor,
|
||||
) -> FontTemplate {
|
||||
FontTemplate {
|
||||
identifier: FontIdentifier::Local(identifier),
|
||||
descriptor,
|
||||
stylesheet: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`FontTemplate`] for a `@font-family` with a `url(...)` `src` font.
|
||||
pub fn new_for_remote_web_font(
|
||||
url: ServoUrl,
|
||||
/// Create a new [`FontTemplate`].
|
||||
pub fn new(
|
||||
identifier: FontIdentifier,
|
||||
descriptor: FontTemplateDescriptor,
|
||||
stylesheet: Option<DocumentStyleSheet>,
|
||||
) -> Result<FontTemplate, &'static str> {
|
||||
Ok(FontTemplate {
|
||||
identifier: FontIdentifier::Web(url),
|
||||
) -> FontTemplate {
|
||||
FontTemplate {
|
||||
identifier,
|
||||
descriptor,
|
||||
stylesheet,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`FontTemplate`] for a `@font-family` with a `local(...)` `src`. This takes in
|
||||
|
|
|
@ -19,7 +19,8 @@ use style::Atom;
|
|||
|
||||
use super::xml::{Attribute, Node};
|
||||
use crate::{
|
||||
FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
FallbackFontSelectionOptions, FontIdentifier, FontTemplate, FontTemplateDescriptor,
|
||||
LowercaseFontFamilyName,
|
||||
};
|
||||
|
||||
static FONT_LIST: LazyLock<FontList> = LazyLock::new(|| FontList::new());
|
||||
|
@ -491,9 +492,10 @@ where
|
|||
None => StyleFontStyle::NORMAL,
|
||||
};
|
||||
let descriptor = FontTemplateDescriptor::new(weight, stretch, style);
|
||||
callback(FontTemplate::new_for_local_font(
|
||||
local_font_identifier,
|
||||
callback(FontTemplate::new(
|
||||
FontIdentifier::Local(local_font_identifier),
|
||||
descriptor,
|
||||
None,
|
||||
));
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,10 @@ use super::c_str_to_string;
|
|||
use crate::font::map_platform_values_to_style_values;
|
||||
use crate::font_template::{FontTemplate, FontTemplateDescriptor};
|
||||
use crate::platform::add_noto_fallback_families;
|
||||
use crate::{EmojiPresentationPreference, FallbackFontSelectionOptions, LowercaseFontFamilyName};
|
||||
use crate::{
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier,
|
||||
LowercaseFontFamilyName,
|
||||
};
|
||||
|
||||
/// An identifier for a local font on systems using Freetype.
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
|
@ -155,9 +158,10 @@ where
|
|||
};
|
||||
let descriptor = FontTemplateDescriptor::new(weight, stretch, style);
|
||||
|
||||
callback(FontTemplate::new_for_local_font(
|
||||
local_font_identifier,
|
||||
callback(FontTemplate::new(
|
||||
FontIdentifier::Local(local_font_identifier),
|
||||
descriptor,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ use style::Atom;
|
|||
use unicode_script::Script;
|
||||
|
||||
use crate::{
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate,
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
|
||||
FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
};
|
||||
|
||||
|
@ -492,9 +492,10 @@ where
|
|||
None => StyleFontStyle::NORMAL,
|
||||
};
|
||||
let descriptor = FontTemplateDescriptor::new(weight, stretch, style);
|
||||
callback(FontTemplate::new_for_local_font(
|
||||
local_font_identifier,
|
||||
callback(FontTemplate::new(
|
||||
FontIdentifier::Local(local_font_identifier),
|
||||
descriptor,
|
||||
None,
|
||||
));
|
||||
};
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ impl CoreTextFontCache {
|
|||
|
||||
core_text::font::new_from_descriptor(&descriptor, clamped_pt_size)
|
||||
},
|
||||
FontIdentifier::Web(_) => {
|
||||
FontIdentifier::Web(_) | FontIdentifier::Mock(_) => {
|
||||
let provider = CGDataProvider::from_buffer(data);
|
||||
let cgfont = CGFont::from_data_provider(provider).ok()?;
|
||||
core_text::font::new_from_CGFont(&cgfont, clamped_pt_size)
|
||||
|
|
|
@ -18,7 +18,7 @@ use webrender_api::NativeFontHandle;
|
|||
use crate::platform::add_noto_fallback_families;
|
||||
use crate::platform::font::CoreTextFontTraitsMapping;
|
||||
use crate::{
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate,
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
|
||||
FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
};
|
||||
|
||||
|
@ -85,7 +85,11 @@ where
|
|||
postscript_name: Atom::from(family_descriptor.font_name()),
|
||||
path: Atom::from(path),
|
||||
};
|
||||
callback(FontTemplate::new_for_local_font(identifier, descriptor));
|
||||
callback(FontTemplate::new(
|
||||
FontIdentifier::Local(identifier),
|
||||
descriptor,
|
||||
None,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use style::values::computed::{FontStyle as StyleFontStyle, FontWeight as StyleFo
|
|||
use style::values::specified::font::FontStretchKeyword;
|
||||
|
||||
use crate::{
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate,
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
|
||||
FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
};
|
||||
|
||||
|
@ -78,9 +78,10 @@ where
|
|||
let local_font_identifier = LocalFontIdentifier {
|
||||
font_descriptor: Arc::new(font.to_descriptor()),
|
||||
};
|
||||
callback(FontTemplate::new_for_local_font(
|
||||
local_font_identifier,
|
||||
callback(FontTemplate::new(
|
||||
FontIdentifier::Local(local_font_identifier),
|
||||
template_descriptor,
|
||||
None,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ use style::values::computed::font::{
|
|||
};
|
||||
use style::values::computed::{FontStretch, FontWeight};
|
||||
use style::values::specified::FontStretch as SpecifiedFontStretch;
|
||||
use style::Atom;
|
||||
use tracing::{span, Level};
|
||||
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey};
|
||||
use webrender_traits::WebRenderFontApi;
|
||||
|
@ -41,26 +42,27 @@ use crate::FontData;
|
|||
pub enum FontIdentifier {
|
||||
Local(LocalFontIdentifier),
|
||||
Web(ServoUrl),
|
||||
Mock(Atom),
|
||||
}
|
||||
|
||||
impl FontIdentifier {
|
||||
pub fn index(&self) -> u32 {
|
||||
match *self {
|
||||
Self::Local(ref local_font_identifier) => local_font_identifier.index(),
|
||||
Self::Web(_) => 0,
|
||||
Self::Web(_) | Self::Mock(_) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct FontTemplateRequestResult {
|
||||
templates: Vec<FontTemplate>,
|
||||
template_data: Vec<(FontIdentifier, Arc<FontData>)>,
|
||||
pub templates: Vec<FontTemplate>,
|
||||
pub template_data: Vec<(FontIdentifier, Arc<FontData>)>,
|
||||
}
|
||||
|
||||
/// Commands that the `FontContext` sends to the `SystemFontService`.
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum Command {
|
||||
pub enum SystemFontServiceMessage {
|
||||
GetFontTemplates(
|
||||
Option<FontDescriptor>,
|
||||
SingleFontFamily,
|
||||
|
@ -72,8 +74,6 @@ pub enum Command {
|
|||
FontInstanceFlags,
|
||||
IpcSender<FontInstanceKey>,
|
||||
),
|
||||
GetWebFont(Arc<FontData>, u32, IpcSender<FontKey>),
|
||||
GetWebFontInstance(FontKey, f32, FontInstanceFlags, IpcSender<FontInstanceKey>),
|
||||
Exit(IpcSender<()>),
|
||||
Ping,
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ struct ResolvedGenericFontFamilies {
|
|||
/// responsible for reading the list of system fonts, handling requests to match against
|
||||
/// them, and ensuring that only one copy of system font data is loaded at a time.
|
||||
pub struct SystemFontService {
|
||||
port: IpcReceiver<Command>,
|
||||
port: IpcReceiver<SystemFontServiceMessage>,
|
||||
local_families: FontStore,
|
||||
webrender_api: Box<dyn WebRenderFontApi>,
|
||||
webrender_fonts: HashMap<FontIdentifier, FontKey>,
|
||||
|
@ -102,7 +102,7 @@ pub struct SystemFontService {
|
|||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct SystemFontServiceProxySender(IpcSender<Command>);
|
||||
pub struct SystemFontServiceProxySender(pub IpcSender<SystemFontServiceMessage>);
|
||||
|
||||
impl SystemFontServiceProxySender {
|
||||
pub fn to_proxy(&self) -> SystemFontServiceProxy {
|
||||
|
@ -145,37 +145,21 @@ impl SystemFontService {
|
|||
let msg = self.port.recv().unwrap();
|
||||
|
||||
match msg {
|
||||
Command::GetFontTemplates(font_descriptor, font_family, result_sender) => {
|
||||
SystemFontServiceMessage::GetFontTemplates(
|
||||
font_descriptor,
|
||||
font_family,
|
||||
result_sender,
|
||||
) => {
|
||||
let span = span!(Level::TRACE, "GetFontTemplates", servo_profiling = true);
|
||||
let _span = span.enter();
|
||||
let _ =
|
||||
result_sender.send(self.get_font_templates(font_descriptor, font_family));
|
||||
},
|
||||
Command::GetFontInstance(identifier, pt_size, flags, result) => {
|
||||
SystemFontServiceMessage::GetFontInstance(identifier, pt_size, flags, result) => {
|
||||
let _ = result.send(self.get_font_instance(identifier, pt_size, flags));
|
||||
},
|
||||
Command::GetWebFont(data, font_index, result_sender) => {
|
||||
self.webrender_api.forward_add_font_message(
|
||||
data.as_ipc_shared_memory(),
|
||||
font_index,
|
||||
result_sender,
|
||||
);
|
||||
},
|
||||
Command::GetWebFontInstance(
|
||||
font_key,
|
||||
font_size,
|
||||
font_instance_flags,
|
||||
result_sender,
|
||||
) => {
|
||||
self.webrender_api.forward_add_font_instance_message(
|
||||
font_key,
|
||||
font_size,
|
||||
font_instance_flags,
|
||||
result_sender,
|
||||
);
|
||||
},
|
||||
Command::Ping => (),
|
||||
Command::Exit(result) => {
|
||||
SystemFontServiceMessage::Ping => (),
|
||||
SystemFontServiceMessage::Exit(result) => {
|
||||
let _ = result.send(());
|
||||
break;
|
||||
},
|
||||
|
@ -325,40 +309,17 @@ impl SystemFontService {
|
|||
}
|
||||
}
|
||||
|
||||
/// A trait for accessing the [`SystemFontServiceProxy`] necessary for unit testing.
|
||||
pub trait SystemFontServiceProxyTrait: Send + Sync {
|
||||
fn find_matching_font_templates(
|
||||
&self,
|
||||
descriptor_to_match: Option<&FontDescriptor>,
|
||||
font_family_name: &SingleFontFamily,
|
||||
) -> Vec<FontTemplateRef>;
|
||||
fn get_system_font_instance(
|
||||
&self,
|
||||
font_identifier: FontIdentifier,
|
||||
size: Au,
|
||||
flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey;
|
||||
fn get_web_font(&self, data: Arc<FontData>, index: u32) -> FontKey;
|
||||
fn get_web_font_instance(
|
||||
&self,
|
||||
font_key: FontKey,
|
||||
size: f32,
|
||||
flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey;
|
||||
fn get_font_data(&self, identifier: &FontIdentifier) -> Option<Arc<FontData>>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
||||
struct FontTemplateCacheKey {
|
||||
font_descriptor: Option<FontDescriptor>,
|
||||
family_descriptor: SingleFontFamily,
|
||||
}
|
||||
|
||||
/// The public interface to the [`SystemFontService`], used by per-Document `FontContext`
|
||||
/// instances (via [`SystemFontServiceProxyTrait`]).
|
||||
/// The public interface to the [`SystemFontService`], used by per-Document
|
||||
/// `FontContext` instances.
|
||||
#[derive(Debug)]
|
||||
pub struct SystemFontServiceProxy {
|
||||
sender: ReentrantMutex<IpcSender<Command>>,
|
||||
sender: ReentrantMutex<IpcSender<SystemFontServiceMessage>>,
|
||||
templates: RwLock<HashMap<FontTemplateCacheKey, Vec<FontTemplateRef>>>,
|
||||
data_cache: RwLock<HashMap<FontIdentifier, Arc<FontData>>>,
|
||||
}
|
||||
|
@ -453,7 +414,7 @@ impl SystemFontServiceProxy {
|
|||
let (response_chan, response_port) = ipc::channel().unwrap();
|
||||
self.sender
|
||||
.lock()
|
||||
.send(Command::Exit(response_chan))
|
||||
.send(SystemFontServiceMessage::Exit(response_chan))
|
||||
.expect("Couldn't send SystemFontService exit message");
|
||||
response_port
|
||||
.recv()
|
||||
|
@ -463,10 +424,8 @@ impl SystemFontServiceProxy {
|
|||
pub fn to_sender(&self) -> SystemFontServiceProxySender {
|
||||
SystemFontServiceProxySender(self.sender.lock().clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl SystemFontServiceProxyTrait for SystemFontServiceProxy {
|
||||
fn get_system_font_instance(
|
||||
pub(crate) fn get_system_font_instance(
|
||||
&self,
|
||||
identifier: FontIdentifier,
|
||||
size: Au,
|
||||
|
@ -475,7 +434,7 @@ impl SystemFontServiceProxyTrait for SystemFontServiceProxy {
|
|||
let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel");
|
||||
self.sender
|
||||
.lock()
|
||||
.send(Command::GetFontInstance(
|
||||
.send(SystemFontServiceMessage::GetFontInstance(
|
||||
identifier,
|
||||
size,
|
||||
flags,
|
||||
|
@ -485,7 +444,11 @@ impl SystemFontServiceProxyTrait for SystemFontServiceProxy {
|
|||
|
||||
let instance_key = response_port.recv();
|
||||
if instance_key.is_err() {
|
||||
let font_thread_has_closed = self.sender.lock().send(Command::Ping).is_err();
|
||||
let font_thread_has_closed = self
|
||||
.sender
|
||||
.lock()
|
||||
.send(SystemFontServiceMessage::Ping)
|
||||
.is_err();
|
||||
assert!(
|
||||
font_thread_has_closed,
|
||||
"Failed to receive a response from live font cache"
|
||||
|
@ -495,7 +458,7 @@ impl SystemFontServiceProxyTrait for SystemFontServiceProxy {
|
|||
instance_key.unwrap()
|
||||
}
|
||||
|
||||
fn find_matching_font_templates(
|
||||
pub(crate) fn find_matching_font_templates(
|
||||
&self,
|
||||
descriptor_to_match: Option<&FontDescriptor>,
|
||||
family_descriptor: &SingleFontFamily,
|
||||
|
@ -516,7 +479,7 @@ impl SystemFontServiceProxyTrait for SystemFontServiceProxy {
|
|||
let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel");
|
||||
self.sender
|
||||
.lock()
|
||||
.send(Command::GetFontTemplates(
|
||||
.send(SystemFontServiceMessage::GetFontTemplates(
|
||||
descriptor_to_match.cloned(),
|
||||
family_descriptor.clone(),
|
||||
response_chan,
|
||||
|
@ -525,7 +488,11 @@ impl SystemFontServiceProxyTrait for SystemFontServiceProxy {
|
|||
|
||||
let reply = response_port.recv();
|
||||
let Ok(reply) = reply else {
|
||||
let font_thread_has_closed = self.sender.lock().send(Command::Ping).is_err();
|
||||
let font_thread_has_closed = self
|
||||
.sender
|
||||
.lock()
|
||||
.send(SystemFontServiceMessage::Ping)
|
||||
.is_err();
|
||||
assert!(
|
||||
font_thread_has_closed,
|
||||
"Failed to receive a response from live font cache"
|
||||
|
@ -544,34 +511,7 @@ impl SystemFontServiceProxyTrait for SystemFontServiceProxy {
|
|||
templates
|
||||
}
|
||||
|
||||
fn get_web_font(&self, data: Arc<FontData>, index: u32) -> FontKey {
|
||||
let (result_sender, result_receiver) =
|
||||
ipc::channel().expect("failed to create IPC channel");
|
||||
let _ = self
|
||||
.sender
|
||||
.lock()
|
||||
.send(Command::GetWebFont(data, index, result_sender));
|
||||
result_receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
fn get_web_font_instance(
|
||||
&self,
|
||||
font_key: FontKey,
|
||||
font_size: f32,
|
||||
font_flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey {
|
||||
let (result_sender, result_receiver) =
|
||||
ipc::channel().expect("failed to create IPC channel");
|
||||
let _ = self.sender.lock().send(Command::GetWebFontInstance(
|
||||
font_key,
|
||||
font_size,
|
||||
font_flags,
|
||||
result_sender,
|
||||
));
|
||||
result_receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
fn get_font_data(&self, identifier: &FontIdentifier) -> Option<Arc<FontData>> {
|
||||
pub(crate) fn get_font_data(&self, identifier: &FontIdentifier) -> Option<Arc<FontData>> {
|
||||
self.data_cache.read().get(identifier).cloned()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,20 +8,21 @@ use std::io::prelude::*;
|
|||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
use app_units::Au;
|
||||
use fonts::platform::font::PlatformFont;
|
||||
use fonts::{
|
||||
fallback_font_families, FallbackFontSelectionOptions, FontContext, FontData, FontDescriptor,
|
||||
FontFamilyDescriptor, FontIdentifier, FontSearchScope, FontTemplate, FontTemplateRef,
|
||||
FontTemplates, PlatformFontMethods, SystemFontServiceProxyTrait,
|
||||
FontFamilyDescriptor, FontIdentifier, FontSearchScope, FontTemplate, FontTemplateRequestResult,
|
||||
FontTemplates, PlatformFontMethods, SystemFontServiceMessage, SystemFontServiceProxy,
|
||||
SystemFontServiceProxySender,
|
||||
};
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::ipc::{self, IpcReceiver};
|
||||
use net_traits::ResourceThreads;
|
||||
use parking_lot::Mutex;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps;
|
||||
use style::properties::style_structs::Font as FontStyleStruct;
|
||||
use style::values::computed::font::{
|
||||
|
@ -31,15 +32,111 @@ use style::values::computed::font::{
|
|||
use style::values::computed::{FontLanguageOverride, XLang};
|
||||
use style::values::generics::font::LineHeight;
|
||||
use style::ArcSlice;
|
||||
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey, IdNamespace};
|
||||
use webrender_api::{FontInstanceKey, IdNamespace};
|
||||
use webrender_traits::WebRenderScriptApi;
|
||||
|
||||
struct MockFontCacheThread {
|
||||
struct TestContext {
|
||||
context: FontContext,
|
||||
system_font_service: Arc<MockSystemFontService>,
|
||||
system_font_service_proxy: SystemFontServiceProxy,
|
||||
}
|
||||
|
||||
impl TestContext {
|
||||
fn new() -> TestContext {
|
||||
let (system_font_service, system_font_service_proxy) = MockSystemFontService::spawn();
|
||||
let (core_sender, _) = ipc::channel().unwrap();
|
||||
let (storage_sender, _) = ipc::channel().unwrap();
|
||||
let mock_resource_threads = ResourceThreads::new(core_sender, storage_sender);
|
||||
let mock_webrender_api = WebRenderScriptApi::dummy();
|
||||
|
||||
let proxy_clone = Arc::new(system_font_service_proxy.to_sender().to_proxy());
|
||||
Self {
|
||||
context: FontContext::new(proxy_clone, mock_webrender_api, mock_resource_threads),
|
||||
system_font_service,
|
||||
system_font_service_proxy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestContext {
|
||||
fn drop(&mut self) {
|
||||
self.system_font_service_proxy.exit();
|
||||
}
|
||||
}
|
||||
|
||||
struct MockSystemFontService {
|
||||
families: Mutex<HashMap<String, FontTemplates>>,
|
||||
data: Mutex<HashMap<FontIdentifier, Arc<FontData>>>,
|
||||
find_font_count: AtomicI32,
|
||||
}
|
||||
|
||||
impl MockFontCacheThread {
|
||||
impl MockSystemFontService {
|
||||
pub fn spawn() -> (Arc<MockSystemFontService>, SystemFontServiceProxy) {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
let system_font_service = Arc::new(Self::new());
|
||||
|
||||
let system_font_service_clone = system_font_service.clone();
|
||||
thread::Builder::new()
|
||||
.name("MockSystemFontService".to_owned())
|
||||
.spawn(move || system_font_service_clone.run(receiver))
|
||||
.expect("Thread spawning failed");
|
||||
(
|
||||
system_font_service,
|
||||
SystemFontServiceProxySender(sender).to_proxy(),
|
||||
)
|
||||
}
|
||||
|
||||
fn run(&self, receiver: IpcReceiver<SystemFontServiceMessage>) {
|
||||
loop {
|
||||
match receiver.recv().unwrap() {
|
||||
SystemFontServiceMessage::GetFontTemplates(
|
||||
descriptor_to_match,
|
||||
font_family,
|
||||
result_sender,
|
||||
) => {
|
||||
self.find_font_count.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
let SingleFontFamily::FamilyName(family_name) = font_family else {
|
||||
let _ = result_sender.send(FontTemplateRequestResult::default());
|
||||
continue;
|
||||
};
|
||||
|
||||
let templates: Vec<_> = self
|
||||
.families
|
||||
.lock()
|
||||
.get_mut(&*family_name.name)
|
||||
.map(|family| family.find_for_descriptor(descriptor_to_match.as_ref()))
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|template| template.borrow().clone())
|
||||
.collect();
|
||||
|
||||
let template_data = templates
|
||||
.iter()
|
||||
.map(|template| {
|
||||
let identifier = template.identifier().clone();
|
||||
let data = self.data.lock().get(&identifier).unwrap().clone();
|
||||
(identifier, data)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let _ = result_sender.send(FontTemplateRequestResult {
|
||||
templates,
|
||||
template_data,
|
||||
});
|
||||
},
|
||||
SystemFontServiceMessage::GetFontInstance(_, _, _, result_sender) => {
|
||||
let _ = result_sender.send(FontInstanceKey(IdNamespace(0), 0));
|
||||
},
|
||||
SystemFontServiceMessage::Exit(result_sender) => {
|
||||
let _ = result_sender.send(());
|
||||
break;
|
||||
},
|
||||
SystemFontServiceMessage::Ping => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
let proxy = Self {
|
||||
families: Default::default(),
|
||||
|
@ -69,18 +166,6 @@ impl MockFontCacheThread {
|
|||
proxy
|
||||
}
|
||||
|
||||
fn identifier_for_font_name(name: &str) -> FontIdentifier {
|
||||
FontIdentifier::Web(Self::url_for_font_name(name))
|
||||
}
|
||||
|
||||
fn url_for_font_name(name: &str) -> ServoUrl {
|
||||
let mut path: PathBuf = [env!("CARGO_MANIFEST_DIR"), "tests", "support", "CSSTest"]
|
||||
.iter()
|
||||
.collect();
|
||||
path.push(format!("{}.ttf", name));
|
||||
ServoUrl::from_file_path(path).unwrap()
|
||||
}
|
||||
|
||||
fn add_face(&self, family: &mut FontTemplates, name: &str) {
|
||||
let mut path: PathBuf = [env!("CARGO_MANIFEST_DIR"), "tests", "support", "CSSTest"]
|
||||
.iter()
|
||||
|
@ -92,65 +177,20 @@ impl MockFontCacheThread {
|
|||
file.bytes().map(|b| b.unwrap()).collect(),
|
||||
));
|
||||
|
||||
let url = Self::url_for_font_name(name);
|
||||
let identifier = FontIdentifier::Web(url.clone());
|
||||
let identifier = FontIdentifier::Mock(name.into());
|
||||
let handle =
|
||||
PlatformFont::new_from_data(identifier.clone(), data.as_arc().clone(), 0, None)
|
||||
.expect("Could not load test font");
|
||||
let template =
|
||||
FontTemplate::new_for_remote_web_font(url, handle.descriptor(), None).unwrap();
|
||||
family.add_template(template);
|
||||
family.add_template(FontTemplate::new(
|
||||
identifier.clone(),
|
||||
handle.descriptor(),
|
||||
None,
|
||||
));
|
||||
|
||||
self.data.lock().insert(identifier, data);
|
||||
}
|
||||
}
|
||||
|
||||
impl SystemFontServiceProxyTrait for MockFontCacheThread {
|
||||
fn find_matching_font_templates(
|
||||
&self,
|
||||
descriptor_to_match: Option<&FontDescriptor>,
|
||||
font_family: &SingleFontFamily,
|
||||
) -> Vec<FontTemplateRef> {
|
||||
self.find_font_count.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
let SingleFontFamily::FamilyName(family_name) = font_family else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
self.families
|
||||
.lock()
|
||||
.get_mut(&*family_name.name)
|
||||
.map(|family| family.find_for_descriptor(descriptor_to_match))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn get_system_font_instance(
|
||||
&self,
|
||||
_font_identifier: FontIdentifier,
|
||||
_size: Au,
|
||||
_flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey {
|
||||
FontInstanceKey(IdNamespace(0), 0)
|
||||
}
|
||||
|
||||
fn get_web_font(&self, _data: Arc<fonts::FontData>, _index: u32) -> FontKey {
|
||||
FontKey(IdNamespace(0), 0)
|
||||
}
|
||||
|
||||
fn get_web_font_instance(
|
||||
&self,
|
||||
_font_key: FontKey,
|
||||
_size: f32,
|
||||
_flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey {
|
||||
FontInstanceKey(IdNamespace(0), 0)
|
||||
}
|
||||
|
||||
fn get_font_data(&self, identifier: &FontIdentifier) -> Option<Arc<fonts::FontData>> {
|
||||
self.data.lock().get(identifier).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
fn style() -> FontStyleStruct {
|
||||
let mut style = FontStyleStruct {
|
||||
font_family: FontFamily::serif(),
|
||||
|
@ -185,16 +225,9 @@ fn font_family(names: Vec<&str>) -> FontFamily {
|
|||
}
|
||||
}
|
||||
|
||||
fn mock_resource_threads() -> ResourceThreads {
|
||||
let (core_sender, _) = ipc::channel().unwrap();
|
||||
let (storage_sender, _) = ipc::channel().unwrap();
|
||||
ResourceThreads::new(core_sender, storage_sender)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_font_group_is_cached_by_style() {
|
||||
let source = Arc::new(MockFontCacheThread::new());
|
||||
let context = FontContext::new(source, mock_resource_threads());
|
||||
let context = TestContext::new();
|
||||
|
||||
let style1 = style();
|
||||
|
||||
|
@ -203,16 +236,28 @@ fn test_font_group_is_cached_by_style() {
|
|||
|
||||
assert!(
|
||||
std::ptr::eq(
|
||||
&*context.font_group(ServoArc::new(style1.clone())).read(),
|
||||
&*context.font_group(ServoArc::new(style1.clone())).read()
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style1.clone()))
|
||||
.read(),
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style1.clone()))
|
||||
.read()
|
||||
),
|
||||
"the same font group should be returned for two styles with the same hash"
|
||||
);
|
||||
|
||||
assert!(
|
||||
!std::ptr::eq(
|
||||
&*context.font_group(ServoArc::new(style1.clone())).read(),
|
||||
&*context.font_group(ServoArc::new(style2.clone())).read()
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style1.clone()))
|
||||
.read(),
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style2.clone()))
|
||||
.read()
|
||||
),
|
||||
"different font groups should be returned for two styles with different hashes"
|
||||
)
|
||||
|
@ -220,52 +265,60 @@ fn test_font_group_is_cached_by_style() {
|
|||
|
||||
#[test]
|
||||
fn test_font_group_find_by_codepoint() {
|
||||
let source = Arc::new(MockFontCacheThread::new());
|
||||
let mut context = FontContext::new(source.clone(), mock_resource_threads());
|
||||
let mut context = TestContext::new();
|
||||
|
||||
let mut style = style();
|
||||
style.set_font_family(font_family(vec!["CSSTest ASCII", "CSSTest Basic"]));
|
||||
|
||||
let group = context.font_group(ServoArc::new(style));
|
||||
let group = context.context.font_group(ServoArc::new(style));
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context, 'a', None)
|
||||
.find_by_codepoint(&mut context.context, 'a', None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.identifier(),
|
||||
MockFontCacheThread::identifier_for_font_name("csstest-ascii")
|
||||
FontIdentifier::Mock("csstest-ascii".into())
|
||||
);
|
||||
assert_eq!(
|
||||
source.find_font_count.fetch_add(0, Ordering::Relaxed),
|
||||
context
|
||||
.system_font_service
|
||||
.find_font_count
|
||||
.fetch_add(0, Ordering::Relaxed),
|
||||
1,
|
||||
"only the first font in the list should have been loaded"
|
||||
);
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context, 'a', None)
|
||||
.find_by_codepoint(&mut context.context, 'a', None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.identifier(),
|
||||
MockFontCacheThread::identifier_for_font_name("csstest-ascii")
|
||||
FontIdentifier::Mock("csstest-ascii".into())
|
||||
);
|
||||
assert_eq!(
|
||||
source.find_font_count.fetch_add(0, Ordering::Relaxed),
|
||||
context
|
||||
.system_font_service
|
||||
.find_font_count
|
||||
.fetch_add(0, Ordering::Relaxed),
|
||||
1,
|
||||
"we shouldn't load the same font a second time"
|
||||
);
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context, 'á', None)
|
||||
.find_by_codepoint(&mut context.context, 'á', None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.identifier(),
|
||||
MockFontCacheThread::identifier_for_font_name("csstest-basic-regular")
|
||||
FontIdentifier::Mock("csstest-basic-regular".into())
|
||||
);
|
||||
assert_eq!(
|
||||
source.find_font_count.fetch_add(0, Ordering::Relaxed),
|
||||
context
|
||||
.system_font_service
|
||||
.find_font_count
|
||||
.fetch_add(0, Ordering::Relaxed),
|
||||
2,
|
||||
"both fonts should now have been loaded"
|
||||
);
|
||||
|
@ -273,39 +326,37 @@ fn test_font_group_find_by_codepoint() {
|
|||
|
||||
#[test]
|
||||
fn test_font_fallback() {
|
||||
let source = Arc::new(MockFontCacheThread::new());
|
||||
let mut context = FontContext::new(source, mock_resource_threads());
|
||||
let mut context = TestContext::new();
|
||||
|
||||
let mut style = style();
|
||||
style.set_font_family(font_family(vec!["CSSTest ASCII"]));
|
||||
|
||||
let group = context.font_group(ServoArc::new(style));
|
||||
let group = context.context.font_group(ServoArc::new(style));
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context, 'a', None)
|
||||
.find_by_codepoint(&mut context.context, 'a', None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.identifier(),
|
||||
MockFontCacheThread::identifier_for_font_name("csstest-ascii"),
|
||||
FontIdentifier::Mock("csstest-ascii".into()),
|
||||
"a family in the group should be used if there is a matching glyph"
|
||||
);
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context, 'á', None)
|
||||
.find_by_codepoint(&mut context.context, 'á', None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.identifier(),
|
||||
MockFontCacheThread::identifier_for_font_name("csstest-basic-regular"),
|
||||
FontIdentifier::Mock("csstest-basic-regular".into()),
|
||||
"a fallback font should be used if there is no matching glyph in the group"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_font_template_is_cached() {
|
||||
let source = Arc::new(MockFontCacheThread::new());
|
||||
let context = FontContext::new(source.clone(), mock_resource_threads());
|
||||
let context = TestContext::new();
|
||||
|
||||
let mut font_descriptor = FontDescriptor {
|
||||
weight: FontWeight::normal(),
|
||||
|
@ -321,14 +372,19 @@ fn test_font_template_is_cached() {
|
|||
});
|
||||
let family_descriptor = FontFamilyDescriptor::new(family, FontSearchScope::Any);
|
||||
|
||||
let font_template = context.matching_templates(&font_descriptor, &family_descriptor)[0].clone();
|
||||
let font_template = context
|
||||
.context
|
||||
.matching_templates(&font_descriptor, &family_descriptor)[0]
|
||||
.clone();
|
||||
|
||||
let font1 = context
|
||||
.context
|
||||
.font(font_template.clone(), &font_descriptor)
|
||||
.unwrap();
|
||||
|
||||
font_descriptor.pt_size = Au(20);
|
||||
let font2 = context
|
||||
.context
|
||||
.font(font_template.clone(), &font_descriptor)
|
||||
.unwrap();
|
||||
|
||||
|
@ -338,7 +394,10 @@ fn test_font_template_is_cached() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
source.find_font_count.fetch_add(0, Ordering::Relaxed),
|
||||
context
|
||||
.system_font_service
|
||||
.find_font_count
|
||||
.fetch_add(0, Ordering::Relaxed),
|
||||
1,
|
||||
"we should only have fetched the template data from the cache thread once"
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::thread;
|
|||
|
||||
use base::id::PipelineId;
|
||||
use fnv::FnvHasher;
|
||||
use fonts::{FontContext, SystemFontServiceProxy};
|
||||
use fonts::FontContext;
|
||||
use net_traits::image_cache::{
|
||||
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, UsePlaceholder,
|
||||
};
|
||||
|
@ -24,8 +24,6 @@ use style::context::{RegisteredSpeculativePainter, SharedStyleContext};
|
|||
|
||||
use crate::display_list::items::{OpaqueNode, WebRenderImageInfo};
|
||||
|
||||
pub type LayoutFontContext = FontContext<SystemFontServiceProxy>;
|
||||
|
||||
type WebrenderImageCache =
|
||||
HashMap<(ServoUrl, UsePlaceholder), WebRenderImageInfo, BuildHasherDefault<FnvHasher>>;
|
||||
|
||||
|
@ -44,7 +42,7 @@ pub struct LayoutContext<'a> {
|
|||
pub image_cache: Arc<dyn ImageCache>,
|
||||
|
||||
/// A FontContext to be used during layout.
|
||||
pub font_context: Arc<FontContext<SystemFontServiceProxy>>,
|
||||
pub font_context: Arc<FontContext>,
|
||||
|
||||
/// A cache of WebRender image info.
|
||||
pub webrender_image_cache: Arc<RwLock<WebrenderImageCache>>,
|
||||
|
|
|
@ -11,7 +11,7 @@ use app_units::{Au, MIN_AU};
|
|||
use base::print_tree::PrintTree;
|
||||
use bitflags::bitflags;
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
use fonts::FontMetrics;
|
||||
use fonts::{FontContext, FontMetrics};
|
||||
use log::debug;
|
||||
use range::{int_range_index, Range, RangeIndex};
|
||||
use script_layout_interface::wrapper_traits::PseudoElementType;
|
||||
|
@ -33,7 +33,7 @@ use style::values::specified::text::TextOverflowSide;
|
|||
use unicode_bidi as bidi;
|
||||
|
||||
use crate::block::AbsoluteAssignBSizesTraversal;
|
||||
use crate::context::{LayoutContext, LayoutFontContext};
|
||||
use crate::context::LayoutContext;
|
||||
use crate::display_list::items::{DisplayListSection, OpaqueNode};
|
||||
use crate::display_list::{
|
||||
BorderPaintingMode, DisplayListBuildState, StackingContextCollectionState,
|
||||
|
@ -1239,7 +1239,7 @@ impl InlineFlow {
|
|||
/// `style` is the style of the block.
|
||||
pub fn minimum_line_metrics(
|
||||
&self,
|
||||
font_context: &LayoutFontContext,
|
||||
font_context: &FontContext,
|
||||
style: &ComputedValues,
|
||||
) -> LineMetrics {
|
||||
InlineFlow::minimum_line_metrics_for_fragments(
|
||||
|
@ -1255,7 +1255,7 @@ impl InlineFlow {
|
|||
/// `style` is the style of the block that these fragments belong to.
|
||||
pub fn minimum_line_metrics_for_fragments(
|
||||
fragments: &[Fragment],
|
||||
font_context: &LayoutFontContext,
|
||||
font_context: &FontContext,
|
||||
style: &ComputedValues,
|
||||
) -> LineMetrics {
|
||||
// As a special case, if this flow contains only hypothetical fragments, then the entire
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::sync::Arc;
|
|||
use app_units::Au;
|
||||
use base::text::is_bidi_control;
|
||||
use fonts::{
|
||||
self, ByteIndex, FontIdentifier, FontMetrics, FontRef, RunMetrics, ShapingFlags,
|
||||
self, ByteIndex, FontContext, FontIdentifier, FontMetrics, FontRef, RunMetrics, ShapingFlags,
|
||||
ShapingOptions, LAST_RESORT_GLYPH_ADVANCE,
|
||||
};
|
||||
use log::{debug, warn};
|
||||
|
@ -28,7 +28,6 @@ use unicode_bidi as bidi;
|
|||
use unicode_script::Script;
|
||||
use xi_unicode::LineBreakLeafIter;
|
||||
|
||||
use crate::context::LayoutFontContext;
|
||||
use crate::fragment::{
|
||||
Fragment, ScannedTextFlags, ScannedTextFragmentInfo, SpecificFragmentInfo,
|
||||
UnscannedTextFragmentInfo,
|
||||
|
@ -71,7 +70,7 @@ impl TextRunScanner {
|
|||
|
||||
pub fn scan_for_runs(
|
||||
&mut self,
|
||||
font_context: &LayoutFontContext,
|
||||
font_context: &FontContext,
|
||||
mut fragments: LinkedList<Fragment>,
|
||||
) -> InlineFragments {
|
||||
debug!(
|
||||
|
@ -151,7 +150,7 @@ impl TextRunScanner {
|
|||
/// be adjusted.
|
||||
fn flush_clump_to_list(
|
||||
&mut self,
|
||||
font_context: &LayoutFontContext,
|
||||
font_context: &FontContext,
|
||||
out_fragments: &mut Vec<Fragment>,
|
||||
paragraph_bytes_processed: &mut usize,
|
||||
bidi_levels: Option<&[bidi::Level]>,
|
||||
|
@ -538,7 +537,7 @@ fn bounding_box_for_run_metrics(
|
|||
/// Panics if no font can be found for the given font style.
|
||||
#[inline]
|
||||
pub fn font_metrics_for_style(
|
||||
font_context: &LayoutFontContext,
|
||||
font_context: &FontContext,
|
||||
style: crate::ServoArc<FontStyleStruct>,
|
||||
) -> FontMetrics {
|
||||
let font_group = font_context.font_group(style);
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
|
||||
use base::id::PipelineId;
|
||||
use fnv::FnvHashMap;
|
||||
use fonts::{FontContext, SystemFontServiceProxy};
|
||||
use fonts::FontContext;
|
||||
use net_traits::image_cache::{
|
||||
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, UsePlaceholder,
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ pub struct LayoutContext<'a> {
|
|||
pub style_context: SharedStyleContext<'a>,
|
||||
|
||||
/// A FontContext to be used during layout.
|
||||
pub font_context: Arc<FontContext<SystemFontServiceProxy>>,
|
||||
pub font_context: Arc<FontContext>,
|
||||
|
||||
/// Reference to the script thread image cache.
|
||||
pub image_cache: Arc<dyn ImageCache>,
|
||||
|
|
|
@ -8,8 +8,7 @@ use std::ops::Range;
|
|||
use app_units::Au;
|
||||
use base::text::is_bidi_control;
|
||||
use fonts::{
|
||||
FontContext, FontRef, GlyphRun, ShapingFlags, ShapingOptions, SystemFontServiceProxy,
|
||||
LAST_RESORT_GLYPH_ADVANCE,
|
||||
FontContext, FontRef, GlyphRun, ShapingFlags, ShapingOptions, LAST_RESORT_GLYPH_ADVANCE,
|
||||
};
|
||||
use fonts_traits::ByteIndex;
|
||||
use log::warn;
|
||||
|
@ -342,7 +341,7 @@ impl TextRun {
|
|||
pub(super) fn segment_and_shape(
|
||||
&mut self,
|
||||
formatting_context_text: &str,
|
||||
font_context: &FontContext<SystemFontServiceProxy>,
|
||||
font_context: &FontContext,
|
||||
linebreaker: &mut LineBreaker,
|
||||
font_cache: &mut Vec<FontKeyAndMetrics>,
|
||||
bidi_info: &BidiInfo,
|
||||
|
@ -410,7 +409,7 @@ impl TextRun {
|
|||
fn segment_text_by_font(
|
||||
&mut self,
|
||||
formatting_context_text: &str,
|
||||
font_context: &FontContext<SystemFontServiceProxy>,
|
||||
font_context: &FontContext,
|
||||
font_cache: &mut Vec<FontKeyAndMetrics>,
|
||||
bidi_info: &BidiInfo,
|
||||
) -> Vec<(TextRunSegment, FontRef)> {
|
||||
|
@ -556,7 +555,7 @@ pub(super) fn add_or_get_font(font: &FontRef, ifc_fonts: &mut Vec<FontKeyAndMetr
|
|||
|
||||
pub(super) fn get_font_for_first_font_for_style(
|
||||
style: &ComputedValues,
|
||||
font_context: &FontContext<SystemFontServiceProxy>,
|
||||
font_context: &FontContext,
|
||||
) -> Option<FontRef> {
|
||||
let font = font_context
|
||||
.font_group(style.clone_font())
|
||||
|
|
|
@ -134,7 +134,7 @@ pub struct LayoutThread {
|
|||
image_cache: Arc<dyn ImageCache>,
|
||||
|
||||
/// A per-layout FontContext managing font access.
|
||||
font_context: Arc<FontContext<SystemFontServiceProxy>>,
|
||||
font_context: Arc<FontContext>,
|
||||
|
||||
/// Is this the first reflow in this layout?
|
||||
first_reflow: Cell<bool>,
|
||||
|
@ -577,7 +577,11 @@ impl LayoutThread {
|
|||
keyword_info: KeywordInfo::medium(),
|
||||
};
|
||||
|
||||
let font_context = Arc::new(FontContext::new(system_font_service, resource_threads));
|
||||
let font_context = Arc::new(FontContext::new(
|
||||
system_font_service,
|
||||
webrender_api.clone(),
|
||||
resource_threads,
|
||||
));
|
||||
let device = Device::new(
|
||||
MediaType::screen(),
|
||||
QuirksMode::NoQuirks,
|
||||
|
|
|
@ -121,7 +121,7 @@ pub struct LayoutThread {
|
|||
image_cache: Arc<dyn ImageCache>,
|
||||
|
||||
/// A FontContext to be used during layout.
|
||||
font_context: Arc<FontContext<SystemFontServiceProxy>>,
|
||||
font_context: Arc<FontContext>,
|
||||
|
||||
/// Is this the first reflow in this LayoutThread?
|
||||
first_reflow: Cell<bool>,
|
||||
|
@ -521,7 +521,11 @@ impl LayoutThread {
|
|||
|
||||
// The device pixel ratio is incorrect (it does not have the hidpi value),
|
||||
// but it will be set correctly when the initial reflow takes place.
|
||||
let font_context = Arc::new(FontContext::new(system_font_service, resource_threads));
|
||||
let font_context = Arc::new(FontContext::new(
|
||||
system_font_service,
|
||||
webrender_api_sender.clone(),
|
||||
resource_threads,
|
||||
));
|
||||
let device = Device::new(
|
||||
MediaType::screen(),
|
||||
QuirksMode::NoQuirks,
|
||||
|
@ -1227,7 +1231,7 @@ impl RegisteredSpeculativePainters for RegisteredPaintersImpl {
|
|||
}
|
||||
}
|
||||
|
||||
struct LayoutFontMetricsProvider(Arc<FontContext<SystemFontServiceProxy>>);
|
||||
struct LayoutFontMetricsProvider(Arc<FontContext>);
|
||||
|
||||
impl FontMetricsProvider for LayoutFontMetricsProvider {
|
||||
fn query_font_metrics(
|
||||
|
|
|
@ -1101,59 +1101,33 @@ impl WebRenderFontApi for WebRenderFontApiCompositorProxy {
|
|||
flags: FontInstanceFlags,
|
||||
) -> FontInstanceKey {
|
||||
let (sender, receiver) = unbounded();
|
||||
self.0
|
||||
.send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
|
||||
FontToCompositorMsg::AddFontInstance(font_key, size, flags, sender),
|
||||
)));
|
||||
self.0.send(CompositorMsg::Forwarded(
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance(
|
||||
font_key, size, flags, sender,
|
||||
)),
|
||||
));
|
||||
receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
fn add_font(&self, data: Arc<IpcSharedMemory>, index: u32) -> FontKey {
|
||||
let (sender, receiver) = unbounded();
|
||||
self.0
|
||||
.send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
|
||||
FontToCompositorMsg::AddFont(sender, index, data),
|
||||
)));
|
||||
self.0.send(CompositorMsg::Forwarded(
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont(
|
||||
sender, index, data,
|
||||
)),
|
||||
));
|
||||
receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
fn add_system_font(&self, handle: NativeFontHandle) -> FontKey {
|
||||
let (sender, receiver) = unbounded();
|
||||
self.0
|
||||
.send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
|
||||
FontToCompositorMsg::AddSystemFont(sender, handle),
|
||||
)));
|
||||
self.0.send(CompositorMsg::Forwarded(
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddSystemFont(
|
||||
sender, handle,
|
||||
)),
|
||||
));
|
||||
receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
fn forward_add_font_message(
|
||||
&self,
|
||||
data: Arc<IpcSharedMemory>,
|
||||
font_index: u32,
|
||||
result_sender: IpcSender<FontKey>,
|
||||
) {
|
||||
let (sender, receiver) = unbounded();
|
||||
self.0
|
||||
.send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
|
||||
FontToCompositorMsg::AddFont(sender, font_index, data),
|
||||
)));
|
||||
let _ = result_sender.send(receiver.recv().unwrap());
|
||||
}
|
||||
|
||||
fn forward_add_font_instance_message(
|
||||
&self,
|
||||
font_key: FontKey,
|
||||
size: f32,
|
||||
flags: FontInstanceFlags,
|
||||
result_sender: IpcSender<FontInstanceKey>,
|
||||
) {
|
||||
let (sender, receiver) = unbounded();
|
||||
self.0
|
||||
.send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Font(
|
||||
FontToCompositorMsg::AddFontInstance(font_key, size, flags, sender),
|
||||
)));
|
||||
let _ = result_sender.send(receiver.recv().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -141,7 +141,7 @@ pub struct CompositionPipeline {
|
|||
pub enum ForwardedToCompositorMsg {
|
||||
Layout(ScriptToCompositorMsg),
|
||||
Net(NetToCompositorMsg),
|
||||
Font(FontToCompositorMsg),
|
||||
SystemFontService(FontToCompositorMsg),
|
||||
Canvas(CanvasToCompositorMsg),
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,9 @@ impl Debug for ForwardedToCompositorMsg {
|
|||
match self {
|
||||
ForwardedToCompositorMsg::Layout(_) => write!(f, "Layout(ScriptToCompositorMsg)"),
|
||||
ForwardedToCompositorMsg::Net(_) => write!(f, "Net(NetToCompositorMsg)"),
|
||||
ForwardedToCompositorMsg::Font(_) => write!(f, "Font(FontToCompositorMsg)"),
|
||||
ForwardedToCompositorMsg::SystemFontService(_) => {
|
||||
write!(f, "SystemFontService(FontToCompositorMsg)")
|
||||
},
|
||||
ForwardedToCompositorMsg::Canvas(_) => write!(f, "Canvas(CanvasToCompositorMsg)"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,24 +192,6 @@ pub trait WebRenderFontApi {
|
|||
) -> FontInstanceKey;
|
||||
fn add_font(&self, data: Arc<IpcSharedMemory>, index: u32) -> FontKey;
|
||||
fn add_system_font(&self, handle: NativeFontHandle) -> FontKey;
|
||||
|
||||
/// Forward a `AddFont` message, sending it on to the compositor. This is used to get WebRender
|
||||
/// [`FontKey`]s for web fonts in the per-layout `FontContext`.
|
||||
fn forward_add_font_message(
|
||||
&self,
|
||||
data: Arc<IpcSharedMemory>,
|
||||
font_index: u32,
|
||||
result_sender: IpcSender<FontKey>,
|
||||
);
|
||||
/// Forward a `AddFontInstance` message, sending it on to the compositor. This is used to get
|
||||
/// WebRender [`FontInstanceKey`]s for web fonts in the per-layout `FontContext`.
|
||||
fn forward_add_font_instance_message(
|
||||
&self,
|
||||
font_key: FontKey,
|
||||
size: f32,
|
||||
flags: FontInstanceFlags,
|
||||
result_receiver: IpcSender<FontInstanceKey>,
|
||||
);
|
||||
}
|
||||
|
||||
pub enum CanvasToCompositorMsg {
|
||||
|
@ -260,6 +242,8 @@ pub enum ScriptToCompositorMsg {
|
|||
UpdateImages(Vec<SerializedImageUpdate>),
|
||||
/// Remove the given font resources from our WebRender instance.
|
||||
RemoveFonts(Vec<FontKey>, Vec<FontInstanceKey>),
|
||||
AddFontInstance(FontKey, f32, FontInstanceFlags, IpcSender<FontInstanceKey>),
|
||||
AddFont(Arc<IpcSharedMemory>, u32, IpcSender<FontKey>),
|
||||
}
|
||||
|
||||
/// A mechanism to send messages from networking to the WebRender instance.
|
||||
|
@ -294,11 +278,23 @@ impl WebRenderNetApi {
|
|||
pub struct WebRenderScriptApi(IpcSender<ScriptToCompositorMsg>);
|
||||
|
||||
impl WebRenderScriptApi {
|
||||
/// Create a new WebrenderIpcSender object that wraps the provided channel sender.
|
||||
/// Create a new [`WebRenderScriptApi`] object that wraps the provided channel sender.
|
||||
pub fn new(sender: IpcSender<ScriptToCompositorMsg>) -> Self {
|
||||
Self(sender)
|
||||
}
|
||||
|
||||
/// Create a new [`WebRenderScriptApi`] object that does not have a listener on the
|
||||
/// other end.
|
||||
pub fn dummy() -> Self {
|
||||
let (sender, _) = ipc::channel().unwrap();
|
||||
Self::new(sender)
|
||||
}
|
||||
|
||||
/// Get the sender for this proxy.
|
||||
pub fn sender(&self) -> &IpcSender<ScriptToCompositorMsg> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Inform WebRender of the existence of this pipeline.
|
||||
pub fn send_initial_transaction(&self, pipeline: WebRenderPipelineId) {
|
||||
if let Err(e) = self
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue