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