mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
stylo: Use font metrics provider as a cache for font size results
This commit is contained in:
parent
e402c72d0e
commit
2febe7ccde
8 changed files with 60 additions and 24 deletions
|
@ -308,6 +308,7 @@ mod bindings {
|
||||||
"mozilla::SERVO_PREF_.*",
|
"mozilla::SERVO_PREF_.*",
|
||||||
"kNameSpaceID_.*",
|
"kNameSpaceID_.*",
|
||||||
"kGenericFont_.*",
|
"kGenericFont_.*",
|
||||||
|
"kPresContext_.*",
|
||||||
];
|
];
|
||||||
let whitelist = [
|
let whitelist = [
|
||||||
"RawGecko.*",
|
"RawGecko.*",
|
||||||
|
|
|
@ -46,8 +46,16 @@ impl FontMetricsProvider for ServoMetricsProvider {
|
||||||
fn create_from(_: &SharedStyleContext) -> Self {
|
fn create_from(_: &SharedStyleContext) -> Self {
|
||||||
ServoMetricsProvider
|
ServoMetricsProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_size(&self, _font_name: &Atom, _font_family: u8) -> Au {
|
||||||
|
unreachable!("Dummy provider should never be used to compute font size")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Servo's font metrics provider will probably not live in this crate, so this will
|
||||||
|
// have to be replaced with something else (perhaps a trait method on TElement)
|
||||||
|
// when we get there
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
/// Construct a font metrics provider for the current product
|
/// Construct a font metrics provider for the current product
|
||||||
pub fn get_metrics_provider_for_product() -> ::gecko::wrapper::GeckoFontMetricsProvider {
|
pub fn get_metrics_provider_for_product() -> ::gecko::wrapper::GeckoFontMetricsProvider {
|
||||||
|
@ -61,7 +69,7 @@ pub fn get_metrics_provider_for_product() -> ServoMetricsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait used to represent something capable of providing us font metrics.
|
/// A trait used to represent something capable of providing us font metrics.
|
||||||
pub trait FontMetricsProvider: Send + fmt::Debug {
|
pub trait FontMetricsProvider: fmt::Debug {
|
||||||
/// Obtain the metrics for given font family.
|
/// Obtain the metrics for given font family.
|
||||||
///
|
///
|
||||||
/// TODO: We could make this take the full list, I guess, and save a few
|
/// TODO: We could make this take the full list, I guess, and save a few
|
||||||
|
@ -72,9 +80,7 @@ pub trait FontMetricsProvider: Send + fmt::Debug {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get default size of a given language and generic family
|
/// Get default size of a given language and generic family
|
||||||
fn get_size(&self, _font_name: &Atom, _font_family: u8) -> Au {
|
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au;
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct from a shared style context
|
/// Construct from a shared style context
|
||||||
fn create_from(context: &SharedStyleContext) -> Self where Self: Sized;
|
fn create_from(context: &SharedStyleContext) -> Self where Self: Sized;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
//! style system it's kind of pointless in the Stylo case, and only Servo forces
|
//! style system it's kind of pointless in the Stylo case, and only Servo forces
|
||||||
//! the separation between the style system implementation and everything else.
|
//! the separation between the style system implementation and everything else.
|
||||||
|
|
||||||
|
use app_units::Au;
|
||||||
use atomic_refcell::AtomicRefCell;
|
use atomic_refcell::AtomicRefCell;
|
||||||
use context::{SharedStyleContext, UpdateAnimationsTasks};
|
use context::{SharedStyleContext, UpdateAnimationsTasks};
|
||||||
use data::ElementData;
|
use data::ElementData;
|
||||||
|
@ -21,6 +22,7 @@ use dom::{self, AnimationRules, DescendantsBit, LayoutIterator, NodeInfo, TEleme
|
||||||
use dom::{OpaqueNode, PresentationalHintsSynthetizer};
|
use dom::{OpaqueNode, PresentationalHintsSynthetizer};
|
||||||
use element_state::ElementState;
|
use element_state::ElementState;
|
||||||
use error_reporting::StdoutErrorReporter;
|
use error_reporting::StdoutErrorReporter;
|
||||||
|
use font_metrics::FontMetricsProvider;
|
||||||
use gecko::global_style_data::GLOBAL_STYLE_DATA;
|
use gecko::global_style_data::GLOBAL_STYLE_DATA;
|
||||||
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
|
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
|
||||||
use gecko::snapshot_helpers;
|
use gecko::snapshot_helpers;
|
||||||
|
@ -432,8 +434,11 @@ fn get_animation_rule(element: &GeckoElement,
|
||||||
pub struct GeckoFontMetricsProvider {
|
pub struct GeckoFontMetricsProvider {
|
||||||
/// Cache of base font sizes for each language
|
/// Cache of base font sizes for each language
|
||||||
///
|
///
|
||||||
/// Should have at most 31 elements (the number of language groups). Usually
|
/// Usually will have 1 element.
|
||||||
/// will have 1.
|
///
|
||||||
|
// This may be slow on pages using more languages, might be worth optimizing
|
||||||
|
// by caching lang->group mapping separately and/or using a hashmap on larger
|
||||||
|
// loads.
|
||||||
pub font_size_cache: RefCell<Vec<(Atom, ::gecko_bindings::structs::FontSizePrefs)>>,
|
pub font_size_cache: RefCell<Vec<(Atom, ::gecko_bindings::structs::FontSizePrefs)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,10 +451,38 @@ impl GeckoFontMetricsProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::font_metrics::FontMetricsProvider for GeckoFontMetricsProvider {
|
impl FontMetricsProvider for GeckoFontMetricsProvider {
|
||||||
fn create_from(_: &SharedStyleContext) -> Self {
|
fn create_from(_: &SharedStyleContext) -> GeckoFontMetricsProvider {
|
||||||
GeckoFontMetricsProvider::new()
|
GeckoFontMetricsProvider::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au {
|
||||||
|
use gecko_bindings::bindings::Gecko_GetBaseSize;
|
||||||
|
let mut cache = self.font_size_cache.borrow_mut();
|
||||||
|
if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) {
|
||||||
|
return sizes.1.size_for_generic(font_family);
|
||||||
|
}
|
||||||
|
let sizes = unsafe {
|
||||||
|
Gecko_GetBaseSize(font_name.as_ptr())
|
||||||
|
};
|
||||||
|
cache.push((font_name.clone(), sizes));
|
||||||
|
sizes.size_for_generic(font_family)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl structs::FontSizePrefs {
|
||||||
|
fn size_for_generic(&self, font_family: u8) -> Au {
|
||||||
|
Au(match font_family {
|
||||||
|
structs::kPresContext_DefaultVariableFont_ID => self.mDefaultVariableSize,
|
||||||
|
structs::kPresContext_DefaultFixedFont_ID => self.mDefaultFixedSize,
|
||||||
|
structs::kGenericFont_serif => self.mDefaultSerifSize,
|
||||||
|
structs::kGenericFont_sans_serif => self.mDefaultSansSerifSize,
|
||||||
|
structs::kGenericFont_monospace => self.mDefaultMonospaceSize,
|
||||||
|
structs::kGenericFont_cursive => self.mDefaultCursiveSize,
|
||||||
|
structs::kGenericFont_fantasy => self.mDefaultFantasySize,
|
||||||
|
x => unreachable!("Unknown generic ID {}", x),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> TElement for GeckoElement<'le> {
|
impl<'le> TElement for GeckoElement<'le> {
|
||||||
|
|
|
@ -1063,9 +1063,7 @@ extern "C" {
|
||||||
aSource: *const nsStyleFont);
|
aSource: *const nsStyleFont);
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_GetBaseSize(lang: *mut nsIAtom,
|
pub fn Gecko_GetBaseSize(lang: *mut nsIAtom) -> FontSizePrefs;
|
||||||
pres_context: RawGeckoPresContextBorrowed)
|
|
||||||
-> FontSizePrefs;
|
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
|
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
|
||||||
|
|
|
@ -19547,6 +19547,8 @@ pub mod root {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct gfxMissingFontRecorder([u8; 0]);
|
pub struct gfxMissingFontRecorder([u8; 0]);
|
||||||
|
pub const kPresContext_DefaultVariableFont_ID: u8 = 0;
|
||||||
|
pub const kPresContext_DefaultFixedFont_ID: u8 = 1;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct nsRootPresContext {
|
pub struct nsRootPresContext {
|
||||||
|
|
|
@ -18981,6 +18981,8 @@ pub mod root {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct gfxMissingFontRecorder([u8; 0]);
|
pub struct gfxMissingFontRecorder([u8; 0]);
|
||||||
|
pub const kPresContext_DefaultVariableFont_ID: u8 = 0;
|
||||||
|
pub const kPresContext_DefaultFixedFont_ID: u8 = 1;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct nsRootPresContext {
|
pub struct nsRootPresContext {
|
||||||
|
|
|
@ -186,10 +186,11 @@ impl fmt::Display for WeakAtom {
|
||||||
|
|
||||||
impl Atom {
|
impl Atom {
|
||||||
/// Execute a callback with the atom represented by `ptr`.
|
/// Execute a callback with the atom represented by `ptr`.
|
||||||
pub unsafe fn with<F>(ptr: *mut nsIAtom, callback: &mut F) where F: FnMut(&Atom) {
|
pub unsafe fn with<F, R: 'static>(ptr: *mut nsIAtom, callback: &mut F) -> R where F: FnMut(&Atom) -> R {
|
||||||
let atom = Atom(WeakAtom::new(ptr));
|
let atom = Atom(WeakAtom::new(ptr));
|
||||||
callback(&atom);
|
let ret = callback(&atom);
|
||||||
mem::forget(atom);
|
mem::forget(atom);
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an atom from an static atom pointer without checking in release
|
/// Creates an atom from an static atom pointer without checking in release
|
||||||
|
|
|
@ -562,17 +562,10 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
|
|
||||||
// XXXManishearth handle quirks mode
|
// XXXManishearth handle quirks mode
|
||||||
|
|
||||||
let base_sizes = unsafe {
|
let ref gecko_font = cx.style().get_font().gecko();
|
||||||
Gecko_GetBaseSize(cx.style().get_font().gecko().mLanguage.raw())
|
let base_size = unsafe { Atom::with(gecko_font.mLanguage.raw(), &mut |atom| {
|
||||||
};
|
cx.font_metrics_provider.get_size(atom, gecko_font.mGenericID).0
|
||||||
let base_size = match cx.style().get_font().gecko().mGenericID {
|
}) };
|
||||||
structs::kGenericFont_serif => base_sizes.mDefaultSerifSize,
|
|
||||||
structs::kGenericFont_sans_serif => base_sizes.mDefaultSansSerifSize,
|
|
||||||
structs::kGenericFont_monospace => base_sizes.mDefaultMonospaceSize,
|
|
||||||
structs::kGenericFont_cursive => base_sizes.mDefaultCursiveSize,
|
|
||||||
structs::kGenericFont_fantasy => base_sizes.mDefaultFantasySize,
|
|
||||||
x => unreachable!("Unknown generic ID {}", x),
|
|
||||||
};
|
|
||||||
|
|
||||||
let base_size_px = au_to_int_px(base_size as f32);
|
let base_size_px = au_to_int_px(base_size as f32);
|
||||||
let html_size = *self as usize;
|
let html_size = *self as usize;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue