mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
style: Unify font-family storage
This changes font-family storage to reuse the rust types, removing a bunch of code while at it. This allows us to, for example, use a single static font family for -moz-bullet and clone it, rather than creating a lot of expensive copies. Differential Revision: https://phabricator.services.mozilla.com/D118011
This commit is contained in:
parent
837e41c8eb
commit
67f9b97735
8 changed files with 180 additions and 294 deletions
|
@ -308,11 +308,6 @@ impl_threadsafe_refcount!(
|
|||
bindings::Gecko_AddRefnsIURIArbitraryThread,
|
||||
bindings::Gecko_ReleasensIURIArbitraryThread
|
||||
);
|
||||
impl_threadsafe_refcount!(
|
||||
structs::SharedFontList,
|
||||
bindings::Gecko_AddRefSharedFontListArbitraryThread,
|
||||
bindings::Gecko_ReleaseSharedFontListArbitraryThread
|
||||
);
|
||||
impl_threadsafe_refcount!(
|
||||
structs::SheetLoadDataHolder,
|
||||
bindings::Gecko_AddRefSheetLoadDataHolderArbitraryThread,
|
||||
|
|
|
@ -878,18 +878,19 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
|
||||
// System fonts are all right, and should have the default font type
|
||||
// set to none already, so bail out early.
|
||||
if font.mFont.systemFont {
|
||||
if font.mFont.family.is_system_font {
|
||||
debug_assert_eq!(
|
||||
font.mFont.fontlist.mDefaultFontType,
|
||||
font.mFont.family.families.fallback,
|
||||
GenericFontFamily::None
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let generic = font.mFont.family.families.single_generic().unwrap_or(GenericFontFamily::None);
|
||||
let default_font_type = unsafe {
|
||||
bindings::Gecko_nsStyleFont_ComputeDefaultFontType(
|
||||
builder.device.document(),
|
||||
font.mGenericID,
|
||||
generic,
|
||||
font.mLanguage.mRawPtr,
|
||||
)
|
||||
};
|
||||
|
@ -899,15 +900,15 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
// cursive or fantasy, since they're ignored, see bug 789788), and
|
||||
// we have a generic family to actually replace it with.
|
||||
let prioritize_user_fonts = !use_document_fonts &&
|
||||
default_font_type != GenericFontFamily::None &&
|
||||
matches!(
|
||||
font.mGenericID,
|
||||
generic,
|
||||
GenericFontFamily::None |
|
||||
GenericFontFamily::Fantasy |
|
||||
GenericFontFamily::Cursive
|
||||
) &&
|
||||
default_font_type != GenericFontFamily::None;
|
||||
GenericFontFamily::Fantasy |
|
||||
GenericFontFamily::Cursive
|
||||
);
|
||||
|
||||
if !prioritize_user_fonts && default_font_type == font.mFont.fontlist.mDefaultFontType {
|
||||
if !prioritize_user_fonts && default_font_type == font.mFont.family.families.fallback {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
@ -915,9 +916,9 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
};
|
||||
|
||||
let font = builder.mutate_font().gecko_mut();
|
||||
font.mFont.fontlist.mDefaultFontType = default_font_type;
|
||||
font.mFont.family.families.fallback = default_font_type;
|
||||
if prioritize_user_fonts {
|
||||
unsafe { bindings::Gecko_nsStyleFont_PrioritizeUserFonts(font, default_font_type) }
|
||||
font.mFont.family.families.prioritize_first_generic_or_prepend(default_font_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ use crate::gecko_bindings::bindings::Gecko_CopyConstruct_${style_struct.gecko_ff
|
|||
use crate::gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name};
|
||||
% endfor
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyCounterStyle;
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyFontFamilyFrom;
|
||||
use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
|
||||
|
@ -848,52 +847,6 @@ fn static_assert() {
|
|||
<% impl_font_settings("font_feature_settings", "gfxFontFeature", "FeatureTagValue", "i32", "u32") %>
|
||||
<% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %>
|
||||
|
||||
pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
|
||||
use crate::values::computed::font::GenericFontFamily;
|
||||
|
||||
let is_system_font = v.is_system_font;
|
||||
self.gecko.mFont.systemFont = is_system_font;
|
||||
self.gecko.mGenericID = if is_system_font {
|
||||
GenericFontFamily::None
|
||||
} else {
|
||||
v.families.single_generic().unwrap_or(GenericFontFamily::None)
|
||||
};
|
||||
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 = GenericFontFamily::None;
|
||||
}
|
||||
|
||||
pub fn copy_font_family_from(&mut self, other: &Self) {
|
||||
unsafe { Gecko_CopyFontFamilyFrom(&mut self.gecko.mFont, &other.gecko.mFont); }
|
||||
self.gecko.mGenericID = other.gecko.mGenericID;
|
||||
self.gecko.mFont.systemFont = other.gecko.mFont.systemFont;
|
||||
}
|
||||
|
||||
pub fn reset_font_family(&mut self, other: &Self) {
|
||||
self.copy_font_family_from(other)
|
||||
}
|
||||
|
||||
pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T {
|
||||
use crate::values::computed::font::{FontFamily, SingleFontFamily, FontFamilyList};
|
||||
|
||||
let fontlist = &self.gecko.mFont.fontlist;
|
||||
let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() };
|
||||
|
||||
let families = if shared_fontlist.mNames.is_empty() {
|
||||
let default = SingleFontFamily::Generic(fontlist.mDefaultFontType);
|
||||
FontFamilyList::new(Box::new([default]))
|
||||
} else {
|
||||
FontFamilyList::SharedFontList(shared_fontlist)
|
||||
};
|
||||
|
||||
FontFamily {
|
||||
families,
|
||||
is_system_font: self.gecko.mFont.systemFont,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unzoom_fonts(&mut self, device: &Device) {
|
||||
use crate::values::generics::NonNegative;
|
||||
self.gecko.mSize = NonNegative(device.unzoom_text(self.gecko.mSize.0));
|
||||
|
@ -1001,6 +954,8 @@ fn static_assert() {
|
|||
|
||||
${impl_simple("font_size_adjust", "mFont.sizeAdjust")}
|
||||
|
||||
${impl_simple("font_family", "mFont.family")}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set__x_lang(&mut self, v: longhands::_x_lang::computed_value::T) {
|
||||
let ptr = v.0.as_ptr();
|
||||
|
|
|
@ -314,7 +314,6 @@ pub mod system_font {
|
|||
//! variable reference. We may want to improve this behavior at some
|
||||
//! point. See also https://github.com/w3c/csswg-drafts/issues/1586.
|
||||
|
||||
use crate::values::computed::font::GenericFontFamily;
|
||||
use crate::properties::longhands;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use crate::values::computed::{ToComputedValue, Context};
|
||||
|
@ -356,7 +355,7 @@ pub mod system_font {
|
|||
use std::mem;
|
||||
use crate::values::computed::Percentage;
|
||||
use crate::values::specified::font::KeywordInfo;
|
||||
use crate::values::computed::font::{FontFamily, FontSize, FontStretch, FontStyle, FontFamilyList};
|
||||
use crate::values::computed::font::{FontSize, FontStretch, FontStyle};
|
||||
use crate::values::generics::NonNegative;
|
||||
|
||||
let mut system = mem::MaybeUninit::<nsFont>::uninit();
|
||||
|
@ -375,12 +374,7 @@ pub mod system_font {
|
|||
})));
|
||||
let font_style = FontStyle::from_gecko(system.style);
|
||||
let ret = ComputedSystemFont {
|
||||
font_family: FontFamily {
|
||||
families: FontFamilyList::SharedFontList(
|
||||
unsafe { system.fontlist.mFontlist.mBasePtr.to_safe() }
|
||||
),
|
||||
is_system_font: true,
|
||||
},
|
||||
font_family: system.family.clone(),
|
||||
font_size: FontSize {
|
||||
size: NonNegative(cx.maybe_zoom_text(system.size.0)),
|
||||
keyword_info: KeywordInfo::none()
|
||||
|
@ -403,7 +397,6 @@ pub mod system_font {
|
|||
font_variation_settings: longhands::font_variation_settings::get_initial_value(),
|
||||
font_variant_alternates: longhands::font_variant_alternates::get_initial_value(),
|
||||
system_font: *self,
|
||||
default_font_type: system.fontlist.mDefaultFontType,
|
||||
};
|
||||
unsafe { bindings::Gecko_nsFont_Destroy(system); }
|
||||
ret
|
||||
|
@ -435,7 +428,6 @@ pub mod system_font {
|
|||
pub ${name}: longhands::${name}::computed_value::T,
|
||||
% endfor
|
||||
pub system_font: SystemFont,
|
||||
pub default_font_type: GenericFontFamily,
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -830,7 +830,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
|||
/// the same font as its fallback ('list-style-type') in case it fails to load.
|
||||
#[cfg(feature = "gecko")]
|
||||
fn adjust_for_marker_pseudo(&mut self) {
|
||||
use crate::values::computed::font::{FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSynthesis, SingleFontFamily};
|
||||
use crate::values::computed::font::{FontFamily, FontSynthesis};
|
||||
use crate::values::computed::text::{LetterSpacing, WordSpacing};
|
||||
|
||||
let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker()) &&
|
||||
|
@ -840,14 +840,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
|||
return;
|
||||
}
|
||||
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY) {
|
||||
let moz_bullet_font_family = FontFamily {
|
||||
families: FontFamilyList::new(Box::new([SingleFontFamily::FamilyName(FamilyName {
|
||||
name: atom!("-moz-bullet-font"),
|
||||
syntax: FontFamilyNameSyntax::Identifiers,
|
||||
})])),
|
||||
is_system_font: false,
|
||||
};
|
||||
self.style.mutate_font().set_font_family(moz_bullet_font_family);
|
||||
self.style.mutate_font().set_font_family(FontFamily::moz_bullet().clone());
|
||||
|
||||
// FIXME(mats): We can remove this if support for font-synthesis is added to @font-face rules.
|
||||
// Then we can add it to the @font-face rule in html.css instead.
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
//! Computed values for font properties
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::gecko_bindings::sugar::refptr::RefPtr;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::gecko_bindings::{bindings, structs};
|
||||
use crate::values::animated::ToAnimatedValue;
|
||||
|
@ -26,13 +24,7 @@ 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::{self, ManuallyDrop};
|
||||
#[cfg(feature = "servo")]
|
||||
use std::slice;
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
#[cfg(feature = "gecko")]
|
||||
use to_shmem::{self, SharedMemoryBuilder, ToShmem};
|
||||
|
||||
pub use crate::values::computed::Length as MozScriptMinSize;
|
||||
pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier};
|
||||
|
@ -183,6 +175,7 @@ impl ToAnimatedValue for FontSize {
|
|||
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToResolvedValue)]
|
||||
#[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf, Serialize, Deserialize))]
|
||||
/// Specifies a prioritized list of font family names or generic family names.
|
||||
#[repr(C)]
|
||||
pub struct FontFamily {
|
||||
/// The actual list of family names.
|
||||
pub families: FontFamilyList,
|
||||
|
@ -190,27 +183,95 @@ pub struct FontFamily {
|
|||
pub is_system_font: bool,
|
||||
}
|
||||
|
||||
macro_rules! static_font_family {
|
||||
($ident:ident, $family:expr) => {
|
||||
lazy_static! {
|
||||
static ref $ident: FontFamily = FontFamily {
|
||||
families: FontFamilyList {
|
||||
list: crate::ArcSlice::from_iter_leaked(std::iter::once($family)),
|
||||
fallback: GenericFontFamily::None,
|
||||
},
|
||||
is_system_font: false,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
impl FontFamily {
|
||||
#[inline]
|
||||
/// Get default font family as `serif` which is a generic font-family
|
||||
pub fn serif() -> Self {
|
||||
FontFamily {
|
||||
families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(
|
||||
GenericFontFamily::Serif,
|
||||
)])),
|
||||
is_system_font: false,
|
||||
Self::generic(GenericFontFamily::Serif).clone()
|
||||
}
|
||||
|
||||
/// Returns the font family for `-moz-bullet-font`.
|
||||
pub(crate) fn moz_bullet() -> &'static Self {
|
||||
static_font_family!(MOZ_BULLET, SingleFontFamily::FamilyName(FamilyName {
|
||||
name: atom!("-moz-bullet-font"),
|
||||
syntax: FontFamilyNameSyntax::Identifiers,
|
||||
}));
|
||||
|
||||
&*MOZ_BULLET
|
||||
}
|
||||
|
||||
/// Returns a font family for a single system font.
|
||||
pub fn for_system_font(name: &str) -> Self {
|
||||
Self {
|
||||
families: FontFamilyList {
|
||||
list: crate::ArcSlice::from_iter(std::iter::once(SingleFontFamily::FamilyName(FamilyName {
|
||||
name: Atom::from(name),
|
||||
syntax: FontFamilyNameSyntax::Identifiers,
|
||||
}))),
|
||||
fallback: GenericFontFamily::None,
|
||||
},
|
||||
is_system_font: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a generic font family.
|
||||
pub fn generic(generic: GenericFontFamily) -> &'static Self {
|
||||
macro_rules! generic_font_family {
|
||||
($ident:ident, $family:ident) => {
|
||||
static_font_family!($ident, SingleFontFamily::Generic(GenericFontFamily::$family))
|
||||
}
|
||||
}
|
||||
|
||||
generic_font_family!(SERIF, Serif);
|
||||
generic_font_family!(SANS_SERIF, SansSerif);
|
||||
generic_font_family!(MONOSPACE, Monospace);
|
||||
generic_font_family!(CURSIVE, Cursive);
|
||||
generic_font_family!(FANTASY, Fantasy);
|
||||
generic_font_family!(MOZ_EMOJI, MozEmoji);
|
||||
|
||||
match generic {
|
||||
GenericFontFamily::None => {
|
||||
debug_assert!(false, "Bogus caller!");
|
||||
&*SERIF
|
||||
}
|
||||
GenericFontFamily::Serif => &*SERIF,
|
||||
GenericFontFamily::SansSerif => &*SANS_SERIF,
|
||||
GenericFontFamily::Monospace => &*MONOSPACE,
|
||||
GenericFontFamily::Cursive => &*CURSIVE,
|
||||
GenericFontFamily::Fantasy => &*FANTASY,
|
||||
GenericFontFamily::MozEmoji => &*MOZ_EMOJI,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl MallocSizeOf for FontFamily {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
// SharedFontList objects are generally shared from the pointer
|
||||
// stored in the specified value. So only count this if the
|
||||
// SharedFontList is unshared.
|
||||
let shared_font_list = self.families.shared_font_list().get();
|
||||
unsafe { bindings::Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(shared_font_list) }
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
use malloc_size_of::MallocUnconditionalSizeOf;
|
||||
// SharedFontList objects are generally measured from the pointer stored
|
||||
// in the specified value. So only count this if the SharedFontList is
|
||||
// unshared.
|
||||
let shared_font_list = &self.families.list;
|
||||
if shared_font_list.is_unique() {
|
||||
shared_font_list.unconditional_size_of(ops)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +281,10 @@ impl ToCss for FontFamily {
|
|||
W: fmt::Write,
|
||||
{
|
||||
let mut iter = self.families.iter();
|
||||
iter.next().unwrap().to_css(dest)?;
|
||||
match iter.next() {
|
||||
Some(f) => f.to_css(dest)?,
|
||||
None => return self.families.fallback.to_css(dest),
|
||||
}
|
||||
for family in iter {
|
||||
dest.write_str(", ")?;
|
||||
family.to_css(dest)?;
|
||||
|
@ -229,15 +293,16 @@ impl ToCss for FontFamily {
|
|||
}
|
||||
}
|
||||
|
||||
/// The name of a font family of choice.
|
||||
#[derive(
|
||||
Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem,
|
||||
)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
/// The name of a font family of choice
|
||||
#[repr(C)]
|
||||
pub struct FamilyName {
|
||||
/// Name of the font family
|
||||
/// Name of the font family.
|
||||
pub name: Atom,
|
||||
/// Syntax of the font family
|
||||
/// Syntax of the font family.
|
||||
pub syntax: FontFamilyNameSyntax,
|
||||
}
|
||||
|
||||
|
@ -291,11 +356,13 @@ pub enum FontFamilyNameSyntax {
|
|||
Identifiers,
|
||||
}
|
||||
|
||||
/// A set of faces that vary in weight, width or slope.
|
||||
/// cbindgen:derive-mut-casts=true
|
||||
#[derive(
|
||||
Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToComputedValue, ToResolvedValue, ToShmem,
|
||||
)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))]
|
||||
/// A set of faces that vary in weight, width or slope.
|
||||
#[repr(u8)]
|
||||
pub enum SingleFontFamily {
|
||||
/// The name of a font family of choice.
|
||||
FamilyName(FamilyName),
|
||||
|
@ -429,145 +496,57 @@ impl SingleFontFamily {
|
|||
syntax: FontFamilyNameSyntax::Quoted,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
/// Get the corresponding font-family with family name
|
||||
fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily {
|
||||
if family.mName.mRawPtr.is_null() {
|
||||
debug_assert_ne!(family.mGeneric, GenericFontFamily::None);
|
||||
return SingleFontFamily::Generic(family.mGeneric);
|
||||
}
|
||||
let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
|
||||
SingleFontFamily::FamilyName(FamilyName {
|
||||
name,
|
||||
syntax: family.mSyntax,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Deserialize,
|
||||
Eq,
|
||||
Hash,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
ToComputedValue,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
/// A list of SingleFontFamily
|
||||
pub struct FontFamilyList(Box<[SingleFontFamily]>);
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
#[derive(Clone, Debug, ToComputedValue, ToResolvedValue)]
|
||||
/// A list of SingleFontFamily
|
||||
pub enum FontFamilyList {
|
||||
/// A strong reference to a Gecko SharedFontList object.
|
||||
SharedFontList(
|
||||
#[compute(no_field_bound)]
|
||||
#[resolve(no_field_bound)]
|
||||
RefPtr<structs::SharedFontList>,
|
||||
),
|
||||
/// A font-family generic ID.
|
||||
Generic(GenericFontFamily),
|
||||
/// A list of font families.
|
||||
#[derive(Clone, Debug, ToComputedValue, ToResolvedValue, ToShmem, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub struct FontFamilyList {
|
||||
/// The actual list of font families specified.
|
||||
pub list: crate::ArcSlice<SingleFontFamily>,
|
||||
/// A fallback font type (none, serif, or sans-serif, generally).
|
||||
pub fallback: GenericFontFamily,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl ToShmem for FontFamilyList {
|
||||
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> to_shmem::Result<Self> {
|
||||
// In practice, the only SharedFontList objects we create from shared
|
||||
// style sheets are ones with a single generic entry.
|
||||
Ok(ManuallyDrop::new(match *self {
|
||||
FontFamilyList::SharedFontList(ref r) => {
|
||||
if !(r.mNames.len() == 1 && r.mNames[0].mName.mRawPtr.is_null()) {
|
||||
return Err(String::from(
|
||||
"ToShmem failed for FontFamilyList: cannot handle non-generic families",
|
||||
));
|
||||
}
|
||||
FontFamilyList::Generic(r.mNames[0].mGeneric)
|
||||
},
|
||||
FontFamilyList::Generic(t) => FontFamilyList::Generic(t),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl PartialEq for FontFamilyList {
|
||||
fn eq(&self, other: &FontFamilyList) -> bool {
|
||||
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_list.mNames.iter().zip(other_list.mNames.iter()) {
|
||||
if a.mSyntax != b.mSyntax ||
|
||||
a.mName.mRawPtr != b.mName.mRawPtr ||
|
||||
a.mGeneric != b.mGeneric
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl Eq for FontFamilyList {}
|
||||
|
||||
impl FontFamilyList {
|
||||
/// Return FontFamilyList with a vector of SingleFontFamily
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
|
||||
FontFamilyList(families)
|
||||
/// Return iterator of SingleFontFamily
|
||||
pub fn iter(&self) -> impl Iterator<Item = &SingleFontFamily> {
|
||||
self.list.iter()
|
||||
}
|
||||
|
||||
/// Return FontFamilyList with a vector of SingleFontFamily
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList {
|
||||
let fontlist;
|
||||
let names;
|
||||
unsafe {
|
||||
fontlist = bindings::Gecko_SharedFontList_Create();
|
||||
names = &mut (*fontlist).mNames;
|
||||
names.ensure_capacity(families.len());
|
||||
/// Puts the fallback in the list if needed.
|
||||
pub fn normalize(&mut self) {
|
||||
if self.fallback == GenericFontFamily::None {
|
||||
return;
|
||||
}
|
||||
let mut new_list = self.list.iter().cloned().collect::<Vec<_>>();
|
||||
new_list.push(SingleFontFamily::Generic(self.fallback));
|
||||
self.list = crate::ArcSlice::from_iter(new_list.into_iter());
|
||||
}
|
||||
|
||||
/// If there's a generic font family on the list (which isn't cursive or
|
||||
/// fantasy), then move it to the front of the list. Otherwise, prepend the
|
||||
/// default generic.
|
||||
pub (crate) fn prioritize_first_generic_or_prepend(&mut self, generic: GenericFontFamily) {
|
||||
let index_of_first_generic = self.iter().position(|f| {
|
||||
match *f {
|
||||
SingleFontFamily::Generic(f) => f != GenericFontFamily::Cursive && f != GenericFontFamily::Fantasy,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(0) = index_of_first_generic {
|
||||
return; // Already first
|
||||
}
|
||||
|
||||
let mut new_list = self.list.iter().cloned().collect::<Vec<_>>();
|
||||
let element_to_prepend = match index_of_first_generic {
|
||||
Some(i) => new_list.remove(i),
|
||||
None => SingleFontFamily::Generic(generic),
|
||||
};
|
||||
|
||||
for family in families.iter() {
|
||||
match *family {
|
||||
SingleFontFamily::FamilyName(ref f) => unsafe {
|
||||
bindings::Gecko_nsTArray_FontFamilyName_AppendNamed(
|
||||
names,
|
||||
f.name.as_ptr(),
|
||||
f.syntax,
|
||||
);
|
||||
},
|
||||
SingleFontFamily::Generic(family) => unsafe {
|
||||
bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
FontFamilyList::SharedFontList(unsafe { RefPtr::from_addrefed(fontlist) })
|
||||
}
|
||||
|
||||
/// Return iterator of SingleFontFamily
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn iter(&self) -> slice::Iter<SingleFontFamily> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
/// Return iterator of SingleFontFamily
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn iter(&self) -> FontFamilyNameIter {
|
||||
FontFamilyNameIter {
|
||||
names: &self.shared_font_list().mNames,
|
||||
cur: 0,
|
||||
}
|
||||
new_list.insert(0, element_to_prepend);
|
||||
self.list = crate::ArcSlice::from_iter(new_list.into_iter());
|
||||
}
|
||||
|
||||
/// Return the generic ID if it is a single generic font
|
||||
|
@ -580,46 +559,6 @@ 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(ref r) => r,
|
||||
FontFamilyList::Generic(t) => {
|
||||
unsafe {
|
||||
// TODO(heycam): Should really add StaticRefPtr sugar.
|
||||
let index = t as usize;
|
||||
mem::transmute::<
|
||||
&structs::StaticRefPtr<structs::SharedFontList>,
|
||||
&RefPtr<structs::SharedFontList>,
|
||||
>(&structs::SharedFontList_sSingleGenerics[index])
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator of FontFamily
|
||||
#[cfg(feature = "gecko")]
|
||||
pub struct FontFamilyNameIter<'a> {
|
||||
names: &'a structs::nsTArray<structs::FontFamilyName>,
|
||||
cur: usize,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<'a> Iterator for FontFamilyNameIter<'a> {
|
||||
type Item = SingleFontFamily;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.cur < self.names.len() {
|
||||
let item = SingleFontFamily::from_font_family_name(&self.names[self.cur]);
|
||||
self.cur += 1;
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Preserve the readability of text when font fallback occurs
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::context::QuirksMode;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily};
|
||||
use crate::values::computed::{font as computed, Length, NonNegativeLength};
|
||||
|
@ -24,7 +22,7 @@ use crate::values::CustomIdent;
|
|||
use crate::Atom;
|
||||
use cssparser::{Parser, Token};
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf};
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::values::SequenceWriter;
|
||||
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
|
||||
|
@ -687,9 +685,10 @@ impl FontFamily {
|
|||
/// Parse a specified font-family value
|
||||
pub fn parse_specified<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let values = input.parse_comma_separated(SingleFontFamily::parse)?;
|
||||
Ok(FontFamily::Values(FontFamilyList::new(
|
||||
values.into_boxed_slice(),
|
||||
)))
|
||||
Ok(FontFamily::Values(FontFamilyList {
|
||||
list: crate::ArcSlice::from_iter(values.into_iter()),
|
||||
fallback: computed::GenericFontFamily::None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -698,8 +697,8 @@ impl ToComputedValue for FontFamily {
|
|||
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
FontFamily::Values(ref v) => computed::FontFamily {
|
||||
families: v.clone(),
|
||||
FontFamily::Values(ref list) => computed::FontFamily {
|
||||
families: list.clone(),
|
||||
is_system_font: false,
|
||||
},
|
||||
FontFamily::System(_) => self.compute_system(context),
|
||||
|
@ -713,18 +712,12 @@ impl ToComputedValue for FontFamily {
|
|||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl MallocSizeOf for FontFamily {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
match *self {
|
||||
FontFamily::Values(ref v) => {
|
||||
// Although a SharedFontList object is refcounted, we always
|
||||
// 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
|
||||
}
|
||||
// Although the family list is refcounted, we always attribute
|
||||
// its size to the specified value.
|
||||
v.list.unconditional_size_of(ops)
|
||||
},
|
||||
FontFamily::System(_) => 0,
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ use std::ptr::NonNull;
|
|||
use std::{iter, mem};
|
||||
use to_shmem_derive::ToShmem;
|
||||
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf};
|
||||
|
||||
/// A canary that we stash in ArcSlices.
|
||||
///
|
||||
/// Given we cannot use a zero-sized-type for the header, since well, C++
|
||||
|
@ -137,6 +139,22 @@ impl<T> ArcSlice<T> {
|
|||
std::mem::forget(empty);
|
||||
ptr as *mut _
|
||||
}
|
||||
|
||||
/// Returns whether there's only one reference to this ArcSlice.
|
||||
pub fn is_unique(&self) -> bool {
|
||||
self.0.with_arc(|arc| arc.is_unique())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocUnconditionalSizeOf for ArcSlice<T> {
|
||||
#[allow(unsafe_code)]
|
||||
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut size = unsafe { ops.malloc_size_of(self.0.heap_ptr()) };
|
||||
for el in self.iter() {
|
||||
size += el.size_of(ops);
|
||||
}
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
/// The inner pointer of an ArcSlice<T>, to be sent via FFI.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue