diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs index a141aef4e8b..d8c0cea0f2b 100644 --- a/components/style/gecko_bindings/sugar/refptr.rs +++ b/components/style/gecko_bindings/sugar/refptr.rs @@ -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, diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 91d6c6c99dd..822a7c52053 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -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); } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 0e9b178944c..86cdeefa982 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -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(); diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index cf75bb59123..12191509622 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -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::::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, } } diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index bfd43da6088..5fe28e5bc72 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -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. diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index d5906d0e89f..af1dd87e797 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -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, - ), - /// 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, + /// 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 { - // 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 { + 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::>(); + 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::>(); + 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 { - 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 { - 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, - &RefPtr, - >(&structs::SharedFontList_sSingleGenerics[index]) - } - }, - } - } -} - -/// Iterator of FontFamily -#[cfg(feature = "gecko")] -pub struct FontFamilyNameIter<'a> { - names: &'a structs::nsTArray, - cur: usize, -} - -#[cfg(feature = "gecko")] -impl<'a> Iterator for FontFamilyNameIter<'a> { - type Item = SingleFontFamily; - - fn next(&mut self) -> Option { - 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 diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 102c55420ab..7f3731375a3 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -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> { 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, } diff --git a/components/style_traits/arc_slice.rs b/components/style_traits/arc_slice.rs index 95afe6b3aad..e55861d183b 100644 --- a/components/style_traits/arc_slice.rs +++ b/components/style_traits/arc_slice.rs @@ -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 ArcSlice { 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 MallocUnconditionalSizeOf for ArcSlice { + #[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, to be sent via FFI.