style: Allow references to static, single-generic C++ SharedFontList objects from Rust FontFamilyList.

UA style sheets only ever specify a single generic font family in font-family
properties, so we pre-create a unique, static SharedFontList for each generic
and change the representation of FontFamilyList to be able to refer to them
by their generic ID.  This avoids having to share refcounted SharedFontList
objects across processes.

Differential Revision: https://phabricator.services.mozilla.com/D17183
This commit is contained in:
Cameron McCormack 2019-03-30 00:15:51 +00:00 committed by Emilio Cobos Álvarez
parent 91586eea0e
commit b6b5ddda71
4 changed files with 59 additions and 23 deletions

View file

@ -1993,7 +1993,9 @@ fn static_assert() {
} else {
v.families.single_generic().unwrap_or(structs::kGenericFont_NONE)
};
self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move(v.families.0.clone());
self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move(
v.families.shared_font_list().clone()
);
// Fixed-up if needed in Cascade::fixup_font_stuff.
self.gecko.mFont.fontlist.mDefaultFontType = FontFamilyType::eFamily_none;
}
@ -2038,7 +2040,7 @@ fn static_assert() {
};
FontFamilyList::new(Box::new([default]))
} else {
FontFamilyList(shared_fontlist)
FontFamilyList::SharedFontList(shared_fontlist)
};
FontFamily {

View file

@ -406,9 +406,9 @@ ${helpers.predefined_type(
let font_style = FontStyle::from_gecko(system.style);
let ret = ComputedSystemFont {
font_family: FontFamily {
families: FontFamilyList(unsafe {
system.fontlist.mFontlist.mBasePtr.to_safe()
}),
families: FontFamilyList::SharedFontList(
unsafe { system.fontlist.mFontlist.mBasePtr.to_safe() }
),
is_system_font: true,
},
font_size: FontSize {

View file

@ -24,6 +24,8 @@ use cssparser::{serialize_identifier, CssStringWriter, Parser};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
#[cfg(feature = "gecko")]
use std::mem;
#[cfg(feature = "servo")]
use std::slice;
use style_traits::{CssWriter, ParseError, ToCss};
@ -202,9 +204,8 @@ impl MallocSizeOf for FontFamily {
// SharedFontList objects are generally shared from the pointer
// stored in the specified value. So only count this if the
// SharedFontList is unshared.
unsafe {
bindings::Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(self.families.0.get())
}
let shared_font_list = self.families.shared_font_list().get();
unsafe { bindings::Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(shared_font_list) }
}
}
@ -500,7 +501,12 @@ pub struct FontFamilyList(Box<[SingleFontFamily]>);
#[cfg(feature = "gecko")]
#[derive(Clone, Debug)]
/// A list of SingleFontFamily
pub struct FontFamilyList(pub RefPtr<structs::SharedFontList>);
pub enum FontFamilyList {
/// A strong reference to a Gecko SharedFontList object.
SharedFontList(RefPtr<structs::SharedFontList>),
/// A font-family generic ID.
Generic(structs::FontFamilyType),
}
#[cfg(feature = "gecko")]
impl Hash for FontFamilyList {
@ -510,7 +516,7 @@ impl Hash for FontFamilyList {
{
use crate::string_cache::WeakAtom;
for name in self.0.mNames.iter() {
for name in self.shared_font_list().mNames.iter() {
name.mType.hash(state);
if !name.mName.mRawPtr.is_null() {
unsafe {
@ -524,10 +530,13 @@ impl Hash for FontFamilyList {
#[cfg(feature = "gecko")]
impl PartialEq for FontFamilyList {
fn eq(&self, other: &FontFamilyList) -> bool {
if self.0.mNames.len() != other.0.mNames.len() {
let self_list = self.shared_font_list();
let other_list = other.shared_font_list();
if self_list.mNames.len() != other_list.mNames.len() {
return false;
}
for (a, b) in self.0.mNames.iter().zip(other.0.mNames.iter()) {
for (a, b) in self_list.mNames.iter().zip(other_list.mNames.iter()) {
if a.mType != b.mType || a.mName.mRawPtr != b.mName.mRawPtr {
return false;
}
@ -540,14 +549,14 @@ impl PartialEq for FontFamilyList {
impl Eq for FontFamilyList {}
impl FontFamilyList {
#[cfg(feature = "servo")]
/// Return FontFamilyList with a vector of SingleFontFamily
#[cfg(feature = "servo")]
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
FontFamilyList(families)
}
#[cfg(feature = "gecko")]
/// Return FontFamilyList with a vector of SingleFontFamily
#[cfg(feature = "gecko")]
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
let fontlist;
let names;
@ -578,26 +587,26 @@ impl FontFamilyList {
}
}
FontFamilyList(unsafe { RefPtr::from_addrefed(fontlist) })
FontFamilyList::SharedFontList(unsafe { RefPtr::from_addrefed(fontlist) })
}
#[cfg(feature = "servo")]
/// Return iterator of SingleFontFamily
#[cfg(feature = "servo")]
pub fn iter(&self) -> slice::Iter<SingleFontFamily> {
self.0.iter()
}
#[cfg(feature = "gecko")]
/// Return iterator of SingleFontFamily
#[cfg(feature = "gecko")]
pub fn iter(&self) -> FontFamilyNameIter {
FontFamilyNameIter {
names: &self.0.mNames,
names: &self.shared_font_list().mNames,
cur: 0,
}
}
#[cfg(feature = "gecko")]
/// Return the generic ID if it is a single generic font
#[cfg(feature = "gecko")]
pub fn single_generic(&self) -> Option<u8> {
let mut iter = self.iter();
if let Some(SingleFontFamily::Generic(ref name)) = iter.next() {
@ -607,10 +616,29 @@ impl FontFamilyList {
}
None
}
/// Return a reference to the Gecko SharedFontList.
#[cfg(feature = "gecko")]
pub fn shared_font_list(&self) -> &RefPtr<structs::SharedFontList> {
match self {
FontFamilyList::SharedFontList(r) => r,
FontFamilyList::Generic(t) => {
unsafe {
// TODO(heycam): Should really add StaticRefPtr sugar.
let index =
(*t as usize) - (structs::FontFamilyType::eFamily_generic_first as usize);
mem::transmute::<
&structs::StaticRefPtr<structs::SharedFontList>,
&RefPtr<structs::SharedFontList>,
>(&structs::SharedFontList_sSingleGenerics[index])
}
},
}
}
}
#[cfg(feature = "gecko")]
/// Iterator of FontFamily
#[cfg(feature = "gecko")]
pub struct FontFamilyNameIter<'a> {
names: &'a structs::nsTArray<structs::FontFamilyName>,
cur: usize,
@ -631,8 +659,8 @@ impl<'a> Iterator for FontFamilyNameIter<'a> {
}
}
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
/// Preserve the readability of text when font fallback occurs
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
pub enum FontSizeAdjust {
#[animation(error)]
/// None variant

View file

@ -567,8 +567,14 @@ impl MallocSizeOf for FontFamily {
match *self {
FontFamily::Values(ref v) => {
// Although a SharedFontList object is refcounted, we always
// attribute its size to the specified value.
unsafe { bindings::Gecko_SharedFontList_SizeOfIncludingThis(v.0.get()) }
// attribute its size to the specified value, as long as it's
// not a value in SharedFontList::sSingleGenerics.
if matches!(v, FontFamilyList::SharedFontList(_)) {
let ptr = v.shared_font_list().get();
unsafe { bindings::Gecko_SharedFontList_SizeOfIncludingThis(ptr) }
} else {
0
}
},
FontFamily::System(_) => 0,
}