mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
style: Cleanup generic font-family handling.
To be more similar between Rust and C++. This introduces GenericFontFamily and exposes that plus FontFamilyNameSyntax to C++, using that where appropriate instead of plain uint8_t as we were doing. As a follow-up, as discussed on IRC with Jonathan, we can remove the -moz-fixed family, and turn it just into an alias of Monospace. The only non-trivial change is the MatchType changes, but they're ok I think. The code already assumed at most one CSS generic, and the struct still takes 8 bits. I've verified that the relevant tests are passing (though try is closed). Differential Revision: https://phabricator.services.mozilla.com/D24272
This commit is contained in:
parent
c49a88ec84
commit
2184e3f2e5
7 changed files with 124 additions and 250 deletions
|
@ -43,7 +43,7 @@ pub trait FontMetricsProvider {
|
|||
}
|
||||
|
||||
/// 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: crate::values::computed::font::GenericFontFamily) -> Au;
|
||||
|
||||
/// Construct from a shared style context
|
||||
fn create_from(context: &SharedStyleContext) -> Self
|
||||
|
|
|
@ -69,6 +69,7 @@ use crate::selector_parser::{AttrValue, HorizontalDirection, Lang};
|
|||
use crate::shared_lock::Locked;
|
||||
use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||
use crate::stylist::CascadeData;
|
||||
use crate::values::computed::font::GenericFontFamily;
|
||||
use crate::values::specified::length::FontBaseSize;
|
||||
use crate::CaseSensitivityExt;
|
||||
use app_units::Au;
|
||||
|
@ -1041,7 +1042,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
|
|||
GeckoFontMetricsProvider::new()
|
||||
}
|
||||
|
||||
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au {
|
||||
fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Au {
|
||||
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);
|
||||
|
@ -1100,16 +1101,17 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
|
|||
}
|
||||
|
||||
impl structs::FontSizePrefs {
|
||||
fn size_for_generic(&self, font_family: u8) -> Au {
|
||||
fn size_for_generic(&self, font_family: GenericFontFamily) -> 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,
|
||||
_ => unreachable!("Unknown generic ID"),
|
||||
GenericFontFamily::None => self.mDefaultVariableSize,
|
||||
GenericFontFamily::Serif => self.mDefaultSerifSize,
|
||||
GenericFontFamily::SansSerif => self.mDefaultSansSerifSize,
|
||||
GenericFontFamily::Monospace => self.mDefaultMonospaceSize,
|
||||
GenericFontFamily::Cursive => self.mDefaultCursiveSize,
|
||||
GenericFontFamily::Fantasy => self.mDefaultFantasySize,
|
||||
GenericFontFamily::MozEmoji => {
|
||||
unreachable!("Should never get here, since this doesn't (yet) appear on font family")
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -683,6 +683,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
#[cfg(feature = "gecko")]
|
||||
fn recompute_default_font_family_type_if_needed(&mut self) {
|
||||
use crate::gecko_bindings::{bindings, structs};
|
||||
use crate::values::computed::font::GenericFontFamily;
|
||||
|
||||
if !self.seen.contains(LonghandId::XLang) &&
|
||||
!self.seen.contains(LonghandId::FontFamily) {
|
||||
|
@ -697,7 +698,7 @@ 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 {
|
||||
debug_assert_eq!(font.mFont.fontlist.mDefaultFontType, structs::FontFamilyType::eFamily_none);
|
||||
debug_assert_eq!(font.mFont.fontlist.mDefaultFontType, GenericFontFamily::None);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -717,11 +718,11 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
!use_document_fonts &&
|
||||
matches!(
|
||||
font.mGenericID,
|
||||
structs::kGenericFont_NONE |
|
||||
structs::kGenericFont_fantasy |
|
||||
structs::kGenericFont_cursive
|
||||
GenericFontFamily::None |
|
||||
GenericFontFamily::Fantasy |
|
||||
GenericFontFamily::Cursive
|
||||
) &&
|
||||
default_font_type != structs::FontFamilyType::eFamily_none;
|
||||
default_font_type != GenericFontFamily::None;
|
||||
|
||||
if !prioritize_user_fonts && default_font_type == font.mFont.fontlist.mDefaultFontType {
|
||||
// Nothing to do.
|
||||
|
|
|
@ -1984,20 +1984,20 @@ fn static_assert() {
|
|||
<% 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::gecko_bindings::structs::FontFamilyType;
|
||||
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 {
|
||||
structs::kGenericFont_NONE
|
||||
GenericFontFamily::None
|
||||
} else {
|
||||
v.families.single_generic().unwrap_or(structs::kGenericFont_NONE)
|
||||
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 = FontFamilyType::eFamily_none;
|
||||
self.gecko.mFont.fontlist.mDefaultFontType = GenericFontFamily::None;
|
||||
}
|
||||
|
||||
pub fn copy_font_family_from(&mut self, other: &Self) {
|
||||
|
@ -2011,33 +2011,13 @@ fn static_assert() {
|
|||
}
|
||||
|
||||
pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T {
|
||||
use crate::gecko_bindings::structs::FontFamilyType;
|
||||
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 = fontlist.mDefaultFontType;
|
||||
let default = match default {
|
||||
FontFamilyType::eFamily_serif => {
|
||||
SingleFontFamily::Generic(atom!("serif"))
|
||||
}
|
||||
_ => {
|
||||
// This can break with some combinations of user prefs, see
|
||||
// bug 1442195 for example. It doesn't really matter in this
|
||||
// case...
|
||||
//
|
||||
// FIXME(emilio): Probably should be storing the whole
|
||||
// default font name instead though.
|
||||
debug_assert_eq!(
|
||||
default,
|
||||
FontFamilyType::eFamily_sans_serif,
|
||||
"Default generic should be serif or sans-serif"
|
||||
);
|
||||
SingleFontFamily::Generic(atom!("sans-serif"))
|
||||
}
|
||||
};
|
||||
let default = SingleFontFamily::Generic(fontlist.mDefaultFontType);
|
||||
FontFamilyList::new(Box::new([default]))
|
||||
} else {
|
||||
FontFamilyList::SharedFontList(shared_fontlist)
|
||||
|
|
|
@ -326,7 +326,7 @@ ${helpers.predefined_type(
|
|||
|
||||
use app_units::Au;
|
||||
use cssparser::{Parser, ToCss};
|
||||
use crate::gecko_bindings::structs::FontFamilyType;
|
||||
use crate::values::computed::font::GenericFontFamily;
|
||||
use crate::properties::longhands;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -466,7 +466,7 @@ ${helpers.predefined_type(
|
|||
pub ${name}: longhands::${name}::computed_value::T,
|
||||
% endfor
|
||||
pub system_font: SystemFont,
|
||||
pub default_font_type: FontFamilyType,
|
||||
pub default_font_type: GenericFontFamily,
|
||||
}
|
||||
|
||||
impl SystemFont {
|
||||
|
|
|
@ -157,10 +157,6 @@ impl FontSize {
|
|||
}
|
||||
}
|
||||
|
||||
/// XXXManishearth it might be better to
|
||||
/// animate this as computed, however this complicates
|
||||
/// clamping and might not be the right thing to do.
|
||||
/// We should figure it out.
|
||||
impl ToAnimatedValue for FontSize {
|
||||
type AnimatedValue = NonNegativeLength;
|
||||
|
||||
|
@ -178,8 +174,8 @@ impl ToAnimatedValue for FontSize {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf))]
|
||||
/// Specifies a prioritized list of font family names or generic family names.
|
||||
pub struct FontFamily {
|
||||
/// The actual list of family names.
|
||||
|
@ -193,7 +189,7 @@ impl FontFamily {
|
|||
/// Get default font family as `serif` which is a generic font-family
|
||||
pub fn serif() -> Self {
|
||||
FontFamily {
|
||||
families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(atom!("serif"))])),
|
||||
families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(GenericFontFamily::Serif)])),
|
||||
is_system_font: false,
|
||||
}
|
||||
}
|
||||
|
@ -232,7 +228,7 @@ pub struct FamilyName {
|
|||
/// Name of the font family
|
||||
pub name: Atom,
|
||||
/// Syntax of the font family
|
||||
pub syntax: FamilyNameSyntax,
|
||||
pub syntax: FontFamilyNameSyntax,
|
||||
}
|
||||
|
||||
impl ToCss for FamilyName {
|
||||
|
@ -241,12 +237,12 @@ impl ToCss for FamilyName {
|
|||
W: fmt::Write,
|
||||
{
|
||||
match self.syntax {
|
||||
FamilyNameSyntax::Quoted => {
|
||||
FontFamilyNameSyntax::Quoted => {
|
||||
dest.write_char('"')?;
|
||||
write!(CssStringWriter::new(dest), "{}", self.name)?;
|
||||
dest.write_char('"')
|
||||
},
|
||||
FamilyNameSyntax::Identifiers => {
|
||||
FontFamilyNameSyntax::Identifiers => {
|
||||
let mut first = true;
|
||||
for ident in self.name.to_string().split(' ') {
|
||||
if first {
|
||||
|
@ -268,11 +264,12 @@ impl ToCss for FamilyName {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
/// Font family names must either be given quoted as strings,
|
||||
/// or unquoted as a sequence of one or more identifiers.
|
||||
pub enum FamilyNameSyntax {
|
||||
#[repr(u8)]
|
||||
pub enum FontFamilyNameSyntax {
|
||||
/// The family name was specified in a quoted form, e.g. "Font Name"
|
||||
/// or 'Font Name'.
|
||||
Quoted,
|
||||
|
@ -282,85 +279,79 @@ pub enum FamilyNameSyntax {
|
|||
Identifiers,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))]
|
||||
/// A set of faces that vary in weight, width or slope.
|
||||
pub enum SingleFontFamily {
|
||||
/// The name of a font family of choice.
|
||||
FamilyName(FamilyName),
|
||||
/// Generic family name.
|
||||
Generic(Atom),
|
||||
Generic(GenericFontFamily),
|
||||
}
|
||||
|
||||
/// A generic font-family name.
|
||||
///
|
||||
/// The order here is important, if you change it make sure that
|
||||
/// `gfxPlatformFontList.h`s ranged array and `gfxFontFamilyList`'s
|
||||
/// sSingleGenerics are updated as well.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Parse, ToCss)]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum GenericFontFamily {
|
||||
/// No generic family specified, only for internal usage.
|
||||
#[css(skip)]
|
||||
None,
|
||||
Serif,
|
||||
SansSerif,
|
||||
Monospace,
|
||||
Cursive,
|
||||
Fantasy,
|
||||
/// This is basically monospace, but with different font prefs. We should
|
||||
/// consider removing it in favor of just using the monospace.* prefs, since
|
||||
/// in practice we don't override the monospace prefs at all.
|
||||
#[cfg(feature = "gecko")]
|
||||
MozFixed,
|
||||
/// An internal value for emoji font selection.
|
||||
#[css(skip)]
|
||||
#[cfg(feature = "gecko")]
|
||||
MozEmoji,
|
||||
}
|
||||
|
||||
// TODO(emilio): Derive this when we make -moz-fixed a parse alias of Monospace.
|
||||
impl ToCss for GenericFontFamily {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: fmt::Write,
|
||||
{
|
||||
dest.write_str(match *self {
|
||||
GenericFontFamily::MozEmoji |
|
||||
GenericFontFamily::Default => return Ok(()),
|
||||
GenericFontFamily::MozFixed |
|
||||
GenericFontFamily::Monospace => "monospace",
|
||||
GenericFontFamily::Serif => "serif",
|
||||
GenericFontFamily::SansSerif => "sans-serif",
|
||||
GenericFontFamily::Cursive => "cursive",
|
||||
GenericFontFamily::Fantasy => "fantasy",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SingleFontFamily {
|
||||
#[inline]
|
||||
/// Get font family name as Atom
|
||||
pub fn atom(&self) -> &Atom {
|
||||
match *self {
|
||||
SingleFontFamily::FamilyName(ref family_name) => &family_name.name,
|
||||
SingleFontFamily::Generic(ref name) => name,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
|
||||
/// Get font family name
|
||||
pub fn name(&self) -> &str {
|
||||
self.atom()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
|
||||
/// Get the corresponding font-family with Atom
|
||||
pub fn from_atom(input: Atom) -> SingleFontFamily {
|
||||
match input {
|
||||
atom!("serif") |
|
||||
atom!("sans-serif") |
|
||||
atom!("cursive") |
|
||||
atom!("fantasy") |
|
||||
atom!("monospace") => return SingleFontFamily::Generic(input),
|
||||
_ => {},
|
||||
}
|
||||
match_ignore_ascii_case! { &input,
|
||||
"serif" => return SingleFontFamily::Generic(atom!("serif")),
|
||||
"sans-serif" => return SingleFontFamily::Generic(atom!("sans-serif")),
|
||||
"cursive" => return SingleFontFamily::Generic(atom!("cursive")),
|
||||
"fantasy" => return SingleFontFamily::Generic(atom!("fantasy")),
|
||||
"monospace" => return SingleFontFamily::Generic(atom!("monospace")),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// We don't know if it's quoted or not. So we set it to
|
||||
// quoted by default.
|
||||
SingleFontFamily::FamilyName(FamilyName {
|
||||
name: input,
|
||||
syntax: FamilyNameSyntax::Quoted,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse a font-family value
|
||||
/// Parse a font-family value.
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(value) = input.try(|i| i.expect_string_cloned()) {
|
||||
return Ok(SingleFontFamily::FamilyName(FamilyName {
|
||||
name: Atom::from(&*value),
|
||||
syntax: FamilyNameSyntax::Quoted,
|
||||
syntax: FontFamilyNameSyntax::Quoted,
|
||||
}));
|
||||
}
|
||||
let first_ident = input.expect_ident()?.clone();
|
||||
|
||||
// FIXME(bholley): The fast thing to do here would be to look up the
|
||||
// string (as lowercase) in the static atoms table. We don't have an
|
||||
// API to do that yet though, so we do the simple thing for now.
|
||||
let mut css_wide_keyword = false;
|
||||
match_ignore_ascii_case! { &first_ident,
|
||||
"serif" => return Ok(SingleFontFamily::Generic(atom!("serif"))),
|
||||
"sans-serif" => return Ok(SingleFontFamily::Generic(atom!("sans-serif"))),
|
||||
"cursive" => return Ok(SingleFontFamily::Generic(atom!("cursive"))),
|
||||
"fantasy" => return Ok(SingleFontFamily::Generic(atom!("fantasy"))),
|
||||
"monospace" => return Ok(SingleFontFamily::Generic(atom!("monospace"))),
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
"-moz-fixed" => return Ok(SingleFontFamily::Generic(atom!("-moz-fixed"))),
|
||||
let first_ident = input.expect_ident_cloned()?;
|
||||
if let Ok(generic) = GenericFontFamily::from_ident(&first_ident) {
|
||||
return Ok(SingleFontFamily::Generic(generic));
|
||||
}
|
||||
|
||||
let reserved = match_ignore_ascii_case! { &first_ident,
|
||||
// https://drafts.csswg.org/css-fonts/#propdef-font-family
|
||||
// "Font family names that happen to be the same as a keyword value
|
||||
// (`inherit`, `serif`, `sans-serif`, `monospace`, `fantasy`, and `cursive`)
|
||||
|
@ -368,18 +359,15 @@ impl SingleFontFamily {
|
|||
// The keywords ‘initial’ and ‘default’ are reserved for future use
|
||||
// and must also be quoted when used as font names.
|
||||
// UAs must not consider these keywords as matching the <family-name> type."
|
||||
"inherit" => css_wide_keyword = true,
|
||||
"initial" => css_wide_keyword = true,
|
||||
"unset" => css_wide_keyword = true,
|
||||
"default" => css_wide_keyword = true,
|
||||
_ => {}
|
||||
}
|
||||
"inherit" | "initial" | "unset" | "revert" | "default" => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let mut value = first_ident.as_ref().to_owned();
|
||||
|
||||
// These keywords are not allowed by themselves.
|
||||
// The only way this value can be valid with with another keyword.
|
||||
if css_wide_keyword {
|
||||
if reserved {
|
||||
let ident = input.expect_ident()?;
|
||||
value.push(' ');
|
||||
value.push_str(&ident);
|
||||
|
@ -393,9 +381,9 @@ impl SingleFontFamily {
|
|||
// `font-family: \ a\ \ b\ \ c\ ;`, it is tricky to serialize them
|
||||
// as identifiers correctly. Just mark them quoted so we don't need
|
||||
// to worry about them in serialization code.
|
||||
FamilyNameSyntax::Quoted
|
||||
FontFamilyNameSyntax::Quoted
|
||||
} else {
|
||||
FamilyNameSyntax::Identifiers
|
||||
FontFamilyNameSyntax::Identifiers
|
||||
};
|
||||
Ok(SingleFontFamily::FamilyName(FamilyName {
|
||||
name: Atom::from(value),
|
||||
|
@ -403,94 +391,18 @@ impl SingleFontFamily {
|
|||
}))
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
/// Return the generic ID for a given generic font name
|
||||
pub fn generic(name: &Atom) -> (structs::FontFamilyType, u8) {
|
||||
use crate::gecko_bindings::structs::FontFamilyType;
|
||||
if *name == atom!("serif") {
|
||||
(FontFamilyType::eFamily_serif, structs::kGenericFont_serif)
|
||||
} else if *name == atom!("sans-serif") {
|
||||
(
|
||||
FontFamilyType::eFamily_sans_serif,
|
||||
structs::kGenericFont_sans_serif,
|
||||
)
|
||||
} else if *name == atom!("cursive") {
|
||||
(
|
||||
FontFamilyType::eFamily_cursive,
|
||||
structs::kGenericFont_cursive,
|
||||
)
|
||||
} else if *name == atom!("fantasy") {
|
||||
(
|
||||
FontFamilyType::eFamily_fantasy,
|
||||
structs::kGenericFont_fantasy,
|
||||
)
|
||||
} else if *name == atom!("monospace") {
|
||||
(
|
||||
FontFamilyType::eFamily_monospace,
|
||||
structs::kGenericFont_monospace,
|
||||
)
|
||||
} else if *name == atom!("-moz-fixed") {
|
||||
(
|
||||
FontFamilyType::eFamily_moz_fixed,
|
||||
structs::kGenericFont_moz_fixed,
|
||||
)
|
||||
} else {
|
||||
panic!("Unknown generic {}", name);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
/// Get the corresponding font-family with family name
|
||||
fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily {
|
||||
use crate::gecko_bindings::structs::FontFamilyType;
|
||||
|
||||
match family.mType {
|
||||
FontFamilyType::eFamily_sans_serif => SingleFontFamily::Generic(atom!("sans-serif")),
|
||||
FontFamilyType::eFamily_serif => SingleFontFamily::Generic(atom!("serif")),
|
||||
FontFamilyType::eFamily_monospace => SingleFontFamily::Generic(atom!("monospace")),
|
||||
FontFamilyType::eFamily_cursive => SingleFontFamily::Generic(atom!("cursive")),
|
||||
FontFamilyType::eFamily_fantasy => SingleFontFamily::Generic(atom!("fantasy")),
|
||||
FontFamilyType::eFamily_moz_fixed => SingleFontFamily::Generic(atom!("-moz-fixed")),
|
||||
FontFamilyType::eFamily_named => {
|
||||
let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
|
||||
SingleFontFamily::FamilyName(FamilyName {
|
||||
name,
|
||||
syntax: FamilyNameSyntax::Identifiers,
|
||||
})
|
||||
},
|
||||
FontFamilyType::eFamily_named_quoted => {
|
||||
let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
|
||||
SingleFontFamily::FamilyName(FamilyName {
|
||||
name,
|
||||
syntax: FamilyNameSyntax::Quoted,
|
||||
})
|
||||
},
|
||||
_ => panic!("Found unexpected font FontFamilyType"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for SingleFontFamily {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: fmt::Write,
|
||||
{
|
||||
match *self {
|
||||
SingleFontFamily::FamilyName(ref name) => name.to_css(dest),
|
||||
|
||||
// All generic values accepted by the parser are known to not require escaping.
|
||||
SingleFontFamily::Generic(ref name) => {
|
||||
#[cfg(feature = "gecko")]
|
||||
{
|
||||
// We should treat -moz-fixed as monospace
|
||||
if name == &atom!("-moz-fixed") {
|
||||
return dest.write_str("monospace");
|
||||
}
|
||||
}
|
||||
|
||||
write!(dest, "{}", name)
|
||||
},
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,7 +418,7 @@ pub enum FontFamilyList {
|
|||
/// A strong reference to a Gecko SharedFontList object.
|
||||
SharedFontList(RefPtr<structs::SharedFontList>),
|
||||
/// A font-family generic ID.
|
||||
Generic(structs::FontFamilyType),
|
||||
Generic(GenericFontFamily),
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -514,38 +426,19 @@ impl ToShmem for FontFamilyList {
|
|||
fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
|
||||
// In practice, the only SharedFontList objects we create from shared
|
||||
// style sheets are ones with a single generic entry.
|
||||
ManuallyDrop::new(match self {
|
||||
FontFamilyList::SharedFontList(r) => {
|
||||
ManuallyDrop::new(match *self {
|
||||
FontFamilyList::SharedFontList(ref r) => {
|
||||
assert!(
|
||||
r.mNames.len() == 1 && r.mNames[0].mName.mRawPtr.is_null(),
|
||||
"ToShmem failed for FontFamilyList: cannot handle non-generic families",
|
||||
);
|
||||
FontFamilyList::Generic(r.mNames[0].mType)
|
||||
FontFamilyList::Generic(r.mNames[0].mGeneric)
|
||||
},
|
||||
FontFamilyList::Generic(t) => FontFamilyList::Generic(*t),
|
||||
FontFamilyList::Generic(t) => FontFamilyList::Generic(t),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl Hash for FontFamilyList {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
use crate::string_cache::WeakAtom;
|
||||
|
||||
for name in self.shared_font_list().mNames.iter() {
|
||||
name.mType.hash(state);
|
||||
if !name.mName.mRawPtr.is_null() {
|
||||
unsafe {
|
||||
WeakAtom::new(name.mName.mRawPtr).hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl PartialEq for FontFamilyList {
|
||||
fn eq(&self, other: &FontFamilyList) -> bool {
|
||||
|
@ -556,7 +449,8 @@ impl PartialEq for FontFamilyList {
|
|||
return false;
|
||||
}
|
||||
for (a, b) in self_list.mNames.iter().zip(other_list.mNames.iter()) {
|
||||
if a.mType != b.mType || a.mName.mRawPtr != b.mName.mRawPtr {
|
||||
if a.mSyntax != b.mSyntax || a.mName.mRawPtr != b.mName.mRawPtr ||
|
||||
a.mGeneric != b.mGeneric {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -588,19 +482,17 @@ impl FontFamilyList {
|
|||
for family in families.iter() {
|
||||
match *family {
|
||||
SingleFontFamily::FamilyName(ref f) => {
|
||||
let quoted = matches!(f.syntax, FamilyNameSyntax::Quoted);
|
||||
unsafe {
|
||||
bindings::Gecko_nsTArray_FontFamilyName_AppendNamed(
|
||||
names,
|
||||
f.name.as_ptr(),
|
||||
quoted,
|
||||
f.syntax,
|
||||
);
|
||||
}
|
||||
},
|
||||
SingleFontFamily::Generic(ref name) => {
|
||||
let (family_type, _generic) = SingleFontFamily::generic(name);
|
||||
SingleFontFamily::Generic(family) => {
|
||||
unsafe {
|
||||
bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family_type);
|
||||
bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -625,12 +517,11 @@ impl FontFamilyList {
|
|||
}
|
||||
|
||||
/// Return the generic ID if it is a single generic font
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn single_generic(&self) -> Option<u8> {
|
||||
pub fn single_generic(&self) -> Option<GenericFontFamily> {
|
||||
let mut iter = self.iter();
|
||||
if let Some(SingleFontFamily::Generic(ref name)) = iter.next() {
|
||||
if let Some(SingleFontFamily::Generic(f)) = iter.next() {
|
||||
if iter.next().is_none() {
|
||||
return Some(SingleFontFamily::generic(name).1);
|
||||
return Some(f);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -639,13 +530,12 @@ impl FontFamilyList {
|
|||
/// 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,
|
||||
match *self {
|
||||
FontFamilyList::SharedFontList(ref 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);
|
||||
let index = t as usize;
|
||||
mem::transmute::<
|
||||
&structs::StaticRefPtr<structs::SharedFontList>,
|
||||
&RefPtr<structs::SharedFontList>,
|
||||
|
|
|
@ -515,7 +515,8 @@ impl From<LengthPercentage> for FontSize {
|
|||
}
|
||||
|
||||
/// Specifies a prioritized list of font family names or generic family names.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, ToCss, ToShmem)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
|
||||
#[cfg_attr(feature = "servo", derive(Hash))]
|
||||
pub enum FontFamily {
|
||||
/// List of `font-family`
|
||||
#[css(comma)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue