fonts: Add support for generic font families and font size configuration (#32673)

This adds support for generic font families in Servo and allows for
configuration of them as well as their default font sizes. One
interesting fix here is that now monospace default to 13px, like it does
in other browsers.

In addition to that, this exposes a new interface in Stylo which allows
setting a default style. This is quite useful for fonts, but also for
other kinds of default style settings -- like text zoom.

Fixes #8371.
Fixes #14773.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Martin Robinson 2024-07-08 19:17:48 +02:00 committed by GitHub
parent 956b7f62e0
commit 77e9e3deba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 397 additions and 300 deletions

27
Cargo.lock generated
View file

@ -1288,7 +1288,7 @@ dependencies = [
[[package]] [[package]]
name = "derive_common" name = "derive_common"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
@ -1838,6 +1838,7 @@ dependencies = [
"servo_allocator", "servo_allocator",
"servo_arc", "servo_arc",
"servo_atoms", "servo_atoms",
"servo_config",
"servo_url", "servo_url",
"smallvec", "smallvec",
"style", "style",
@ -3755,7 +3756,7 @@ dependencies = [
[[package]] [[package]]
name = "malloc_size_of" name = "malloc_size_of"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"accountable-refcell", "accountable-refcell",
"app_units", "app_units",
@ -5405,7 +5406,7 @@ dependencies = [
[[package]] [[package]]
name = "selectors" name = "selectors"
version = "0.24.0" version = "0.24.0"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
"cssparser", "cssparser",
@ -5693,7 +5694,7 @@ dependencies = [
[[package]] [[package]]
name = "servo_arc" name = "servo_arc"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"nodrop", "nodrop",
"serde", "serde",
@ -5703,7 +5704,7 @@ dependencies = [
[[package]] [[package]]
name = "servo_atoms" name = "servo_atoms"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"string_cache", "string_cache",
"string_cache_codegen", "string_cache_codegen",
@ -5890,7 +5891,7 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]] [[package]]
name = "size_of_test" name = "size_of_test"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"static_assertions", "static_assertions",
] ]
@ -6031,7 +6032,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "static_prefs" name = "static_prefs"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
[[package]] [[package]]
name = "strict-num" name = "strict-num"
@ -6068,7 +6069,7 @@ dependencies = [
[[package]] [[package]]
name = "style" name = "style"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"app_units", "app_units",
"arrayvec", "arrayvec",
@ -6126,7 +6127,7 @@ dependencies = [
[[package]] [[package]]
name = "style_config" name = "style_config"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
] ]
@ -6134,7 +6135,7 @@ dependencies = [
[[package]] [[package]]
name = "style_derive" name = "style_derive"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"darling", "darling",
"derive_common", "derive_common",
@ -6165,7 +6166,7 @@ dependencies = [
[[package]] [[package]]
name = "style_traits" name = "style_traits"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"app_units", "app_units",
"bitflags 2.6.0", "bitflags 2.6.0",
@ -6515,7 +6516,7 @@ dependencies = [
[[package]] [[package]]
name = "to_shmem" name = "to_shmem"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"cssparser", "cssparser",
"servo_arc", "servo_arc",
@ -6528,7 +6529,7 @@ dependencies = [
[[package]] [[package]]
name = "to_shmem_derive" name = "to_shmem_derive"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/stylo?branch=2024-05-31#141446aeea5a0741927c3c83de54a9512e12f4ab" source = "git+https://github.com/servo/stylo?branch=2024-05-31#36bbc6a977f6f16383ea22f2b1215b10f461a7a1"
dependencies = [ dependencies = [
"darling", "darling",
"derive_common", "derive_common",

View file

@ -165,6 +165,14 @@ mod gen {
std::cmp::max(num_cpus::get() * 3 / 4, 1) as i64 std::cmp::max(num_cpus::get() * 3 / 4, 1) as i64
} }
fn default_font_size() -> i64 {
16
}
fn default_monospace_font_size() -> i64 {
13
}
fn black() -> i64 { fn black() -> i64 {
0x000000 0x000000
} }
@ -188,6 +196,23 @@ mod gen {
foreground_color: i64, foreground_color: i64,
} }
}, },
fonts: {
#[serde(default)]
default: String,
#[serde(default)]
serif: String,
#[serde(default)]
#[serde(rename = "fonts.sans-serif")]
sans_serif: String,
#[serde(default)]
monospace: String,
#[serde(default = "default_font_size")]
#[serde(rename = "fonts.default-size")]
default_size: i64,
#[serde(default = "default_monospace_font_size")]
#[serde(rename = "fonts.default-monospace-size")]
default_monospace_size: i64,
},
css: { css: {
animations: { animations: {
testing: { testing: {

View file

@ -36,6 +36,7 @@ range = { path = "../range" }
serde = { workspace = true } serde = { workspace = true }
servo_arc = { workspace = true } servo_arc = { workspace = true }
servo_atoms = { workspace = true } servo_atoms = { workspace = true }
servo_config = { path = "../config" }
servo_url = { path = "../url" } servo_url = { path = "../url" }
smallvec = { workspace = true, features = ["union"] } smallvec = { workspace = true, features = ["union"] }
surfman = { workspace = true } surfman = { workspace = true }

View file

@ -16,11 +16,12 @@ use log::debug;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use parking_lot::RwLock; use parking_lot::RwLock;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use servo_atoms::{atom, Atom};
use smallvec::SmallVec; use smallvec::SmallVec;
use style::computed_values::font_variant_caps; use style::computed_values::font_variant_caps;
use style::properties::style_structs::Font as FontStyleStruct; use style::properties::style_structs::Font as FontStyleStruct;
use style::values::computed::font::{GenericFontFamily, SingleFontFamily}; use style::values::computed::font::{
FamilyName, FontFamilyNameSyntax, GenericFontFamily, SingleFontFamily,
};
use style::values::computed::{FontStretch, FontStyle, FontWeight}; use style::values::computed::{FontStretch, FontStyle, FontWeight};
use unicode_script::Script; use unicode_script::Script;
use webrender_api::{FontInstanceFlags, FontInstanceKey}; use webrender_api::{FontInstanceFlags, FontInstanceKey};
@ -629,10 +630,18 @@ impl FontGroup {
TemplatePredicate: Fn(FontTemplateRef) -> bool, TemplatePredicate: Fn(FontTemplateRef) -> bool,
FontPredicate: Fn(&FontRef) -> bool, FontPredicate: Fn(&FontRef) -> bool,
{ {
iter::once(FontFamilyDescriptor::serif()) iter::once(FontFamilyDescriptor::default())
.chain(fallback_font_families(options).into_iter().map(|family| { .chain(
FontFamilyDescriptor::new(FontFamilyName::from(family), FontSearchScope::Local) fallback_font_families(options)
})) .into_iter()
.map(|family_name| {
let family = SingleFontFamily::FamilyName(FamilyName {
name: family_name.into(),
syntax: FontFamilyNameSyntax::Quoted,
});
FontFamilyDescriptor::new(family, FontSearchScope::Local)
}),
)
.filter_map(|family_descriptor| { .filter_map(|family_descriptor| {
FontGroupFamily { FontGroupFamily {
family_descriptor, family_descriptor,
@ -675,11 +684,8 @@ struct FontGroupFamily {
impl FontGroupFamily { impl FontGroupFamily {
fn new(family: &SingleFontFamily) -> FontGroupFamily { fn new(family: &SingleFontFamily) -> FontGroupFamily {
let family_descriptor =
FontFamilyDescriptor::new(FontFamilyName::from(family), FontSearchScope::Any);
FontGroupFamily { FontGroupFamily {
family_descriptor, family_descriptor: FontFamilyDescriptor::new(family.clone(), FontSearchScope::Any),
members: None, members: None,
} }
} }
@ -781,73 +787,24 @@ pub enum FontSearchScope {
Local, Local,
} }
/// A font family name used in font selection.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum FontFamilyName {
/// A specific name such as `"Arial"`
Specific(Atom),
/// A generic name such as `sans-serif`
Generic(Atom),
}
impl FontFamilyName {
pub fn name(&self) -> &str {
match *self {
FontFamilyName::Specific(ref name) => name,
FontFamilyName::Generic(ref name) => name,
}
}
}
impl<'a> From<&'a SingleFontFamily> for FontFamilyName {
fn from(other: &'a SingleFontFamily) -> FontFamilyName {
match *other {
SingleFontFamily::FamilyName(ref family_name) => {
FontFamilyName::Specific(family_name.name.clone())
},
SingleFontFamily::Generic(generic) => FontFamilyName::Generic(match generic {
GenericFontFamily::None => panic!("Shouldn't appear in style"),
GenericFontFamily::Serif => atom!("serif"),
GenericFontFamily::SansSerif => atom!("sans-serif"),
GenericFontFamily::Monospace => atom!("monospace"),
GenericFontFamily::Cursive => atom!("cursive"),
GenericFontFamily::Fantasy => atom!("fantasy"),
GenericFontFamily::SystemUi => atom!("system-ui"),
}),
}
}
}
impl<'a> From<&'a str> for FontFamilyName {
fn from(other: &'a str) -> FontFamilyName {
FontFamilyName::Specific(Atom::from(other))
}
}
/// The font family parameters for font selection. /// The font family parameters for font selection.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct FontFamilyDescriptor { pub struct FontFamilyDescriptor {
pub name: FontFamilyName, pub family: SingleFontFamily,
pub scope: FontSearchScope, pub scope: FontSearchScope,
} }
impl FontFamilyDescriptor { impl FontFamilyDescriptor {
pub fn new(name: FontFamilyName, scope: FontSearchScope) -> FontFamilyDescriptor { pub fn new(family: SingleFontFamily, scope: FontSearchScope) -> FontFamilyDescriptor {
FontFamilyDescriptor { name, scope } FontFamilyDescriptor { family, scope }
} }
fn serif() -> FontFamilyDescriptor { fn default() -> FontFamilyDescriptor {
FontFamilyDescriptor { FontFamilyDescriptor {
name: FontFamilyName::Generic(atom!("serif")), family: SingleFontFamily::Generic(GenericFontFamily::None),
scope: FontSearchScope::Local, scope: FontSearchScope::Local,
} }
} }
pub fn name(&self) -> &str {
self.name.name()
}
} }
/// Given a mapping array `mapping` and a value, map that value onto /// Given a mapping array `mapping` and a value, map that value onto

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::OnceCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::{Deref, RangeInclusive}; use std::ops::{Deref, RangeInclusive};
use std::sync::Arc; use std::sync::Arc;
@ -14,23 +15,25 @@ use ipc_channel::ipc::{self, IpcBytesReceiver, IpcBytesSender, IpcReceiver, IpcS
use log::debug; use log::debug;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use servo_atoms::Atom; use servo_config::pref;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use style::font_face::{FontFaceRuleData, FontStyle as FontFaceStyle}; use style::font_face::{FontFaceRuleData, FontStyle as FontFaceStyle};
use style::values::computed::font::{FixedPoint, FontStyleFixedPoint}; use style::values::computed::font::{
FixedPoint, FontStyleFixedPoint, GenericFontFamily, SingleFontFamily,
};
use style::values::computed::{FontStretch, FontWeight}; use style::values::computed::{FontStretch, FontWeight};
use style::values::specified::FontStretch as SpecifiedFontStretch; use style::values::specified::FontStretch as SpecifiedFontStretch;
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey};
use webrender_traits::WebRenderFontApi; use webrender_traits::WebRenderFontApi;
use crate::font::{FontDescriptor, FontFamilyName}; use crate::font::FontDescriptor;
use crate::font_store::FontStore; use crate::font_store::FontStore;
use crate::font_template::{ use crate::font_template::{
FontTemplate, FontTemplateDescriptor, FontTemplateRef, FontTemplateRefMethods, FontTemplate, FontTemplateDescriptor, FontTemplateRef, FontTemplateRefMethods,
}; };
use crate::platform::font_list::{ use crate::platform::font_list::{
for_each_available_family, for_each_variation, system_default_family, LocalFontIdentifier, default_system_generic_font_family, for_each_available_family, for_each_variation,
SANS_SERIF_FONT_FAMILY, LocalFontIdentifier,
}; };
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
@ -60,7 +63,7 @@ pub struct SerializedFontTemplate {
pub enum Command { pub enum Command {
GetFontTemplates( GetFontTemplates(
Option<FontDescriptor>, Option<FontDescriptor>,
FontFamilyName, SingleFontFamily,
IpcSender<Vec<SerializedFontTemplate>>, IpcSender<Vec<SerializedFontTemplate>>,
), ),
GetFontInstance( GetFontInstance(
@ -75,43 +78,27 @@ pub enum Command {
Ping, Ping,
} }
#[derive(Default)]
struct ResolvedGenericFontFamilies {
default: OnceCell<LowercaseFontFamilyName>,
serif: OnceCell<LowercaseFontFamilyName>,
sans_serif: OnceCell<LowercaseFontFamilyName>,
monospace: OnceCell<LowercaseFontFamilyName>,
fantasy: OnceCell<LowercaseFontFamilyName>,
cursive: OnceCell<LowercaseFontFamilyName>,
system_ui: OnceCell<LowercaseFontFamilyName>,
}
/// The font cache thread itself. It maintains a list of reference counted /// The font cache thread itself. It maintains a list of reference counted
/// font templates that are currently in use. /// font templates that are currently in use.
struct FontCache { struct FontCache {
port: IpcReceiver<Command>, port: IpcReceiver<Command>,
generic_fonts: HashMap<FontFamilyName, LowercaseString>,
font_data: HashMap<FontIdentifier, Arc<Vec<u8>>>, font_data: HashMap<FontIdentifier, Arc<Vec<u8>>>,
local_families: FontStore, local_families: FontStore,
webrender_api: Box<dyn WebRenderFontApi>, webrender_api: Box<dyn WebRenderFontApi>,
webrender_fonts: HashMap<FontIdentifier, FontKey>, webrender_fonts: HashMap<FontIdentifier, FontKey>,
font_instances: HashMap<(FontKey, Au), FontInstanceKey>, font_instances: HashMap<(FontKey, Au), FontInstanceKey>,
} generic_fonts: ResolvedGenericFontFamilies,
fn populate_generic_fonts() -> HashMap<FontFamilyName, LowercaseString> {
let mut generic_fonts = HashMap::with_capacity(5);
append_map(&mut generic_fonts, "serif", "Times New Roman");
append_map(&mut generic_fonts, "sans-serif", SANS_SERIF_FONT_FAMILY);
append_map(&mut generic_fonts, "cursive", "Apple Chancery");
append_map(&mut generic_fonts, "fantasy", "Papyrus");
append_map(&mut generic_fonts, "monospace", "Menlo");
fn append_map(
generic_fonts: &mut HashMap<FontFamilyName, LowercaseString>,
generic_name: &str,
mapped_name: &str,
) {
let family_name = match system_default_family(generic_name) {
Some(system_default) => LowercaseString::new(&system_default),
None => LowercaseString::new(mapped_name),
};
let generic_name = FontFamilyName::Generic(Atom::from(generic_name));
generic_fonts.insert(generic_name, family_name);
}
generic_fonts
} }
impl FontCache { impl FontCache {
@ -120,9 +107,9 @@ impl FontCache {
let msg = self.port.recv().unwrap(); let msg = self.port.recv().unwrap();
match msg { match msg {
Command::GetFontTemplates(descriptor_to_match, font_family_name, result) => { Command::GetFontTemplates(descriptor_to_match, font_family, result) => {
let templates = let templates =
self.find_font_templates(descriptor_to_match.as_ref(), &font_family_name); self.find_font_templates(descriptor_to_match.as_ref(), &font_family);
debug!("Found templates for descriptor {descriptor_to_match:?}: "); debug!("Found templates for descriptor {descriptor_to_match:?}: ");
debug!(" {templates:?}"); debug!(" {templates:?}");
@ -192,28 +179,21 @@ impl FontCache {
fn refresh_local_families(&mut self) { fn refresh_local_families(&mut self) {
self.local_families.clear(); self.local_families.clear();
for_each_available_family(|family_name| { for_each_available_family(|family_name| {
let family_name = LowercaseString::new(&family_name); self.local_families
self.local_families.families.entry(family_name).or_default(); .families
.entry(family_name.as_str().into())
.or_default();
}); });
} }
fn transform_family(&self, family_name: &FontFamilyName) -> LowercaseString {
match self.generic_fonts.get(family_name) {
None => LowercaseString::from(family_name),
Some(mapped_family) => (*mapped_family).clone(),
}
}
fn find_font_templates( fn find_font_templates(
&mut self, &mut self,
descriptor_to_match: Option<&FontDescriptor>, descriptor_to_match: Option<&FontDescriptor>,
family_name: &FontFamilyName, family: &SingleFontFamily,
) -> Vec<FontTemplateRef> { ) -> Vec<FontTemplateRef> {
// TODO(Issue #188): look up localized font family names if canonical name not found // TODO(Issue #188): look up localized font family names if canonical name not found
// look up canonical name // look up canonical name
// TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'. let family_name = self.family_name_for_single_font_family(family);
// if such family exists, try to match style to a font
let family_name = self.transform_family(family_name);
self.local_families self.local_families
.families .families
.get_mut(&family_name) .get_mut(&family_name)
@ -267,13 +247,53 @@ impl FontCache {
webrender_font_api.add_font_instance(font_key, pt_size.to_f32_px(), flags) webrender_font_api.add_font_instance(font_key, pt_size.to_f32_px(), flags)
}) })
} }
pub(crate) fn family_name_for_single_font_family(
&mut self,
family: &SingleFontFamily,
) -> LowercaseFontFamilyName {
let generic = match family {
SingleFontFamily::FamilyName(family_name) => return family_name.name.clone().into(),
SingleFontFamily::Generic(generic) => generic,
};
let resolved_font = match generic {
GenericFontFamily::None => &self.generic_fonts.default,
GenericFontFamily::Serif => &self.generic_fonts.serif,
GenericFontFamily::SansSerif => &self.generic_fonts.sans_serif,
GenericFontFamily::Monospace => &self.generic_fonts.monospace,
GenericFontFamily::Cursive => &self.generic_fonts.cursive,
GenericFontFamily::Fantasy => &self.generic_fonts.fantasy,
GenericFontFamily::SystemUi => &self.generic_fonts.system_ui,
};
resolved_font
.get_or_init(|| {
// First check whether the font is set in the preferences.
let family_name = match generic {
GenericFontFamily::None => pref!(fonts.default),
GenericFontFamily::Serif => pref!(fonts.serif),
GenericFontFamily::SansSerif => pref!(fonts.sans_serif),
GenericFontFamily::Monospace => pref!(fonts.monospace),
_ => String::new(),
};
if !family_name.is_empty() {
return family_name.into();
}
// Otherwise ask the platform for the default family for the generic font.
default_system_generic_font_family(*generic)
})
.clone()
}
} }
pub trait FontSource: Clone { pub trait FontSource: Clone {
fn find_matching_font_templates( fn find_matching_font_templates(
&self, &self,
descriptor_to_match: Option<&FontDescriptor>, descriptor_to_match: Option<&FontDescriptor>,
font_family_name: &FontFamilyName, font_family_name: &SingleFontFamily,
) -> Vec<FontTemplateRef>; ) -> Vec<FontTemplateRef>;
fn get_system_font_instance( fn get_system_font_instance(
&self, &self,
@ -313,7 +333,7 @@ pub enum ComputedFontStyleDescriptor {
/// on the contents of the font itself. /// on the contents of the font itself.
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct CSSFontFaceDescriptors { pub struct CSSFontFaceDescriptors {
pub family_name: LowercaseString, pub family_name: LowercaseFontFamilyName,
pub weight: Option<(FontWeight, FontWeight)>, pub weight: Option<(FontWeight, FontWeight)>,
pub stretch: Option<(FontStretch, FontStretch)>, pub stretch: Option<(FontStretch, FontStretch)>,
pub style: Option<ComputedFontStyleDescriptor>, pub style: Option<ComputedFontStyleDescriptor>,
@ -323,7 +343,7 @@ pub struct CSSFontFaceDescriptors {
impl CSSFontFaceDescriptors { impl CSSFontFaceDescriptors {
pub fn new(family_name: &str) -> Self { pub fn new(family_name: &str) -> Self {
CSSFontFaceDescriptors { CSSFontFaceDescriptors {
family_name: LowercaseString::new(family_name), family_name: family_name.into(),
..Default::default() ..Default::default()
} }
} }
@ -373,7 +393,7 @@ impl From<&FontFaceRuleData> for CSSFontFaceDescriptors {
.map(|ranges| ranges.iter().map(|range| range.start..=range.end).collect()); .map(|ranges| ranges.iter().map(|range| range.start..=range.end).collect());
CSSFontFaceDescriptors { CSSFontFaceDescriptors {
family_name: LowercaseString::new(&family_name), family_name: family_name.into(),
weight, weight,
stretch, stretch,
style, style,
@ -389,18 +409,15 @@ impl FontCacheThread {
thread::Builder::new() thread::Builder::new()
.name("FontCache".to_owned()) .name("FontCache".to_owned())
.spawn(move || { .spawn(move || {
// TODO: Allow users to specify these.
let generic_fonts = populate_generic_fonts();
#[allow(clippy::default_constructed_unit_structs)] #[allow(clippy::default_constructed_unit_structs)]
let mut cache = FontCache { let mut cache = FontCache {
port, port,
generic_fonts,
font_data: HashMap::new(), font_data: HashMap::new(),
local_families: Default::default(), local_families: Default::default(),
webrender_api, webrender_api,
webrender_fonts: HashMap::new(), webrender_fonts: HashMap::new(),
font_instances: HashMap::new(), font_instances: HashMap::new(),
generic_fonts: Default::default(),
}; };
cache.refresh_local_families(); cache.refresh_local_families();
@ -454,13 +471,13 @@ impl FontSource for FontCacheThread {
fn find_matching_font_templates( fn find_matching_font_templates(
&self, &self,
descriptor_to_match: Option<&FontDescriptor>, descriptor_to_match: Option<&FontDescriptor>,
font_family_name: &FontFamilyName, font_family: &SingleFontFamily,
) -> Vec<FontTemplateRef> { ) -> Vec<FontTemplateRef> {
let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel"); let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel");
self.chan self.chan
.send(Command::GetFontTemplates( .send(Command::GetFontTemplates(
descriptor_to_match.cloned(), descriptor_to_match.cloned(),
font_family_name.clone(), font_family.clone(),
response_chan, response_chan,
)) ))
.expect("failed to send message to font cache thread"); .expect("failed to send message to font cache thread");
@ -521,25 +538,19 @@ impl FontSource for FontCacheThread {
} }
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct LowercaseString { pub struct LowercaseFontFamilyName {
inner: String, inner: String,
} }
impl LowercaseString { impl<T: AsRef<str>> From<T> for LowercaseFontFamilyName {
pub fn new(s: &str) -> LowercaseString { fn from(value: T) -> Self {
LowercaseString { LowercaseFontFamilyName {
inner: s.to_lowercase(), inner: value.as_ref().to_lowercase(),
} }
} }
} }
impl<'a> From<&'a FontFamilyName> for LowercaseString { impl Deref for LowercaseFontFamilyName {
fn from(family_name: &'a FontFamilyName) -> LowercaseString {
LowercaseString::new(family_name.name())
}
}
impl Deref for LowercaseString {
type Target = str; type Target = str;
#[inline] #[inline]
@ -548,7 +559,7 @@ impl Deref for LowercaseString {
} }
} }
impl fmt::Display for LowercaseString { impl fmt::Display for LowercaseFontFamilyName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(f) self.inner.fmt(f)
} }

View file

@ -25,18 +25,18 @@ use style::media_queries::Device;
use style::properties::style_structs::Font as FontStyleStruct; use style::properties::style_structs::Font as FontStyleStruct;
use style::shared_lock::SharedRwLockReadGuard; use style::shared_lock::SharedRwLockReadGuard;
use style::stylesheets::{CssRule, DocumentStyleSheet, FontFaceRule, StylesheetInDocument}; use style::stylesheets::{CssRule, DocumentStyleSheet, FontFaceRule, StylesheetInDocument};
use style::values::computed::font::{FamilyName, FontFamilyNameSyntax, SingleFontFamily};
use style::Atom; use style::Atom;
use url::Url; use url::Url;
use webrender_api::{FontInstanceKey, FontKey}; use webrender_api::{FontInstanceKey, FontKey};
use crate::font::{ use crate::font::{
Font, FontDescriptor, FontFamilyDescriptor, FontFamilyName, FontGroup, FontRef, FontSearchScope, Font, FontDescriptor, FontFamilyDescriptor, FontGroup, FontRef, FontSearchScope,
};
use crate::font_cache_thread::{
CSSFontFaceDescriptors, FontIdentifier, FontSource, LowercaseString,
}; };
use crate::font_cache_thread::{CSSFontFaceDescriptors, FontIdentifier, FontSource};
use crate::font_store::{CrossThreadFontStore, CrossThreadWebRenderFontStore}; use crate::font_store::{CrossThreadFontStore, CrossThreadWebRenderFontStore};
use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods}; use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods};
use crate::LowercaseFontFamilyName;
static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h) static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h)
@ -170,28 +170,39 @@ impl<S: FontSource> FontContext<S> {
font font
} }
fn matching_web_font_templates(
&self,
descriptor_to_match: &FontDescriptor,
family_descriptor: &FontFamilyDescriptor,
) -> Option<Vec<FontTemplateRef>> {
if family_descriptor.scope != FontSearchScope::Any {
return None;
}
// Do not look for generic fonts in our list of web fonts.
let SingleFontFamily::FamilyName(ref family_name) = family_descriptor.family else {
return None;
};
self.web_fonts
.read()
.families
.get(&family_name.name.clone().into())
.map(|templates| templates.find_for_descriptor(Some(descriptor_to_match)))
}
/// Try to find matching templates in this [`FontContext`], first looking in the list of web fonts and
/// falling back to asking the [`super::FontCacheThread`] for a matching system font.
pub fn matching_templates( pub fn matching_templates(
&self, &self,
descriptor_to_match: &FontDescriptor, descriptor_to_match: &FontDescriptor,
family_descriptor: &FontFamilyDescriptor, family_descriptor: &FontFamilyDescriptor,
) -> Vec<FontTemplateRef> { ) -> Vec<FontTemplateRef> {
// First try to find an appropriate web font that matches this descriptor. self.matching_web_font_templates(descriptor_to_match, family_descriptor)
if family_descriptor.scope == FontSearchScope::Any { .unwrap_or_else(|| {
let family_name = LowercaseString::from(&family_descriptor.name); self.cache
if let Some(templates) = self .matching_templates(descriptor_to_match, family_descriptor)
.web_fonts })
.read()
.families
.get(&family_name)
.map(|templates| templates.find_for_descriptor(Some(descriptor_to_match)))
{
return templates;
}
}
// If not request a matching font from the system font cache.
self.cache
.matching_templates(descriptor_to_match, family_descriptor)
} }
/// Create a `Font` for use in layout calculations, from a `FontTemplateData` returned by the /// Create a `Font` for use in layout calculations, from a `FontTemplateData` returned by the
@ -310,10 +321,13 @@ impl<S: FontSource + Send + 'static> FontContextWebFontMethods for Arc<FontConte
local_fonts local_fonts
.entry(family_name.name.clone()) .entry(family_name.name.clone())
.or_insert_with(|| { .or_insert_with(|| {
let family_name = FontFamilyName::Specific(family_name.name.clone()); let family = SingleFontFamily::FamilyName(FamilyName {
name: family_name.name.clone(),
syntax: FontFamilyNameSyntax::Quoted,
});
self.font_source self.font_source
.lock() .lock()
.find_matching_font_templates(None, &family_name) .find_matching_font_templates(None, &family)
.first() .first()
.cloned() .cloned()
}); });
@ -453,7 +467,7 @@ impl<S: FontSource + Send + 'static> FontContextWebFontMethods for Arc<FontConte
struct RemoteWebFontDownloader<FCT: FontSource> { struct RemoteWebFontDownloader<FCT: FontSource> {
font_context: Arc<FontContext<FCT>>, font_context: Arc<FontContext<FCT>>,
url: ServoArc<Url>, url: ServoArc<Url>,
web_font_family_name: LowercaseString, web_font_family_name: LowercaseFontFamilyName,
response_valid: Mutex<bool>, response_valid: Mutex<bool>,
response_data: Mutex<Vec<u8>>, response_data: Mutex<Vec<u8>>,
} }
@ -468,7 +482,7 @@ impl<FCT: FontSource + Send + 'static> RemoteWebFontDownloader<FCT> {
fn download( fn download(
url_source: UrlSource, url_source: UrlSource,
font_context: Arc<FontContext<FCT>>, font_context: Arc<FontContext<FCT>>,
web_font_family_name: LowercaseString, web_font_family_name: LowercaseFontFamilyName,
state: WebFontDownloadState, state: WebFontDownloadState,
) { ) {
// https://drafts.csswg.org/css-fonts/#font-fetching-requirements // https://drafts.csswg.org/css-fonts/#font-fetching-requirements
@ -652,7 +666,7 @@ impl<FCT: FontSource> CachingFontSource<FCT> {
let templates = self let templates = self
.font_cache_thread .font_cache_thread
.lock() .lock()
.find_matching_font_templates(Some(descriptor_to_match), &family_descriptor.name); .find_matching_font_templates(Some(descriptor_to_match), &family_descriptor.family);
self.templates.write().insert(cache_key, templates.clone()); self.templates.write().insert(cache_key, templates.clone());
templates templates

View file

@ -14,13 +14,13 @@ use style::values::computed::{FontStyle, FontWeight};
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey};
use crate::font::FontDescriptor; use crate::font::FontDescriptor;
use crate::font_cache_thread::{FontIdentifier, FontSource, LowercaseString}; use crate::font_cache_thread::{FontIdentifier, FontSource, LowercaseFontFamilyName};
use crate::font_context::WebFontDownloadState; use crate::font_context::WebFontDownloadState;
use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods, IsOblique}; use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods, IsOblique};
#[derive(Default)] #[derive(Default)]
pub struct FontStore { pub struct FontStore {
pub(crate) families: HashMap<LowercaseString, FontTemplates>, pub(crate) families: HashMap<LowercaseFontFamilyName, FontTemplates>,
web_fonts_loading: Vec<(DocumentStyleSheet, usize)>, web_fonts_loading: Vec<(DocumentStyleSheet, usize)>,
} }
pub(crate) type CrossThreadFontStore = Arc<RwLock<FontStore>>; pub(crate) type CrossThreadFontStore = Arc<RwLock<FontStore>>;

View file

@ -10,13 +10,16 @@ use base::text::{is_cjk, UnicodeBlock, UnicodeBlockMethod};
use log::warn; use log::warn;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{ use style::values::computed::{
FontStretch as StyleFontStretch, FontStyle as StyleFontStyle, FontWeight as StyleFontWeight, FontStretch as StyleFontStretch, FontStyle as StyleFontStyle, FontWeight as StyleFontWeight,
}; };
use style::Atom; use style::Atom;
use super::xml::{Attribute, Node}; use super::xml::{Attribute, Node};
use crate::{FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor}; use crate::{
FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName,
};
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref FONT_LIST: FontList = FontList::new(); static ref FONT_LIST: FontList = FontList::new();
@ -515,17 +518,6 @@ where
} }
} }
pub fn system_default_family(generic_name: &str) -> Option<String> {
if let Some(family) = FONT_LIST.find_family(&generic_name) {
Some(family.name.clone())
} else if let Some(alias) = FONT_LIST.find_alias(&generic_name) {
Some(alias.from.clone())
} else {
// First font defined in the fonts.xml is the default on Android.
FONT_LIST.families.get(0).map(|family| family.name.clone())
}
}
// Based on gfxAndroidPlatform::GetCommonFallbackFonts() in Gecko // Based on gfxAndroidPlatform::GetCommonFallbackFonts() in Gecko
pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> { pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> {
let mut families = vec![]; let mut families = vec![];
@ -581,4 +573,14 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st
families families
} }
pub static SANS_SERIF_FONT_FAMILY: &'static str = "sans-serif"; pub fn default_system_generic_font_family(generic: GenericFontFamily) -> LowercaseFontFamilyName {
match generic {
GenericFontFamily::None | GenericFontFamily::Serif => "serif",
GenericFontFamily::SansSerif => "sans-serif",
GenericFontFamily::Monospace => "monospace",
GenericFontFamily::Cursive => "cursive",
GenericFontFamily::Fantasy => "serif",
GenericFontFamily::SystemUi => "Droid Sans",
}
.into()
}

View file

@ -27,6 +27,7 @@ use libc::{c_char, c_int};
use log::debug; use log::debug;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{FontStretch, FontStyle, FontWeight}; use style::values::computed::{FontStretch, FontStyle, FontWeight};
use style::Atom; use style::Atom;
use unicode_script::Script; use unicode_script::Script;
@ -35,7 +36,7 @@ use super::c_str_to_string;
use crate::font::map_platform_values_to_style_values; use crate::font::map_platform_values_to_style_values;
use crate::font_template::{FontTemplate, FontTemplateDescriptor}; use crate::font_template::{FontTemplate, FontTemplateDescriptor};
use crate::platform::add_noto_fallback_families; use crate::platform::add_noto_fallback_families;
use crate::{EmojiPresentationPreference, FallbackFontSelectionOptions}; use crate::{EmojiPresentationPreference, FallbackFontSelectionOptions, LowercaseFontFamilyName};
/// An identifier for a local font on systems using Freetype. /// An identifier for a local font on systems using Freetype.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
@ -166,41 +167,6 @@ where
} }
} }
pub fn system_default_family(generic_name: &str) -> Option<String> {
let generic_name_c = CString::new(generic_name).unwrap();
let generic_name_ptr = generic_name_c.as_ptr();
unsafe {
let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);
FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
let mut result = 0;
let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result);
let family_name = if result == FcResultMatch {
let mut match_string: *mut FcChar8 = ptr::null_mut();
FcPatternGetString(
family_match,
FC_FAMILY.as_ptr() as *mut c_char,
0,
&mut match_string,
);
let result = c_str_to_string(match_string as *const c_char);
FcPatternDestroy(family_match);
Some(result)
} else {
None
};
FcPatternDestroy(pattern);
family_name
}
}
pub static SANS_SERIF_FONT_FAMILY: &str = "DejaVu Sans";
// Based on gfxPlatformGtk::GetCommonFallbackFonts() in Gecko // Based on gfxPlatformGtk::GetCommonFallbackFonts() in Gecko
pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> { pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> {
let mut families = Vec::new(); let mut families = Vec::new();
@ -241,6 +207,58 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st
families families
} }
pub fn default_system_generic_font_family(generic: GenericFontFamily) -> LowercaseFontFamilyName {
let generic_string = match generic {
GenericFontFamily::None | GenericFontFamily::Serif => "serif",
GenericFontFamily::SansSerif => "sans-serif",
GenericFontFamily::Monospace => "monospace",
GenericFontFamily::Cursive => "cursive",
GenericFontFamily::Fantasy => "fantasy",
GenericFontFamily::SystemUi => "sans-serif",
};
let generic_name_c = CString::new(generic_string).unwrap();
let generic_name_ptr = generic_name_c.as_ptr();
unsafe {
let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);
FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
let mut result = 0;
let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result);
if result == FcResultMatch {
let mut match_string: *mut FcChar8 = ptr::null_mut();
FcPatternGetString(
family_match,
FC_FAMILY.as_ptr() as *mut c_char,
0,
&mut match_string,
);
let family_name = c_str_to_string(match_string as *const c_char);
FcPatternDestroy(family_match);
FcPatternDestroy(pattern);
return family_name.into();
}
FcPatternDestroy(family_match);
FcPatternDestroy(pattern);
}
match generic {
GenericFontFamily::None | GenericFontFamily::Serif => "Noto Serif",
GenericFontFamily::SansSerif => "Noto Sans",
GenericFontFamily::Monospace => "Deja Vu Sans Mono",
GenericFontFamily::Cursive => "Comic Sans MS",
GenericFontFamily::Fantasy => "Impact",
GenericFontFamily::SystemUi => "Noto Sans",
}
.into()
}
fn font_style_from_fontconfig_pattern(pattern: *mut FcPattern) -> Option<FontStyle> { fn font_style_from_fontconfig_pattern(pattern: *mut FcPattern) -> Option<FontStyle> {
let mut slant: c_int = 0; let mut slant: c_int = 0;
unsafe { unsafe {

View file

@ -10,12 +10,15 @@ use base::text::{is_cjk, UnicodeBlock, UnicodeBlockMethod};
use log::warn; use log::warn;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{ use style::values::computed::{
FontStretch as StyleFontStretch, FontStyle as StyleFontStyle, FontWeight as StyleFontWeight, FontStretch as StyleFontStretch, FontStyle as StyleFontStyle, FontWeight as StyleFontWeight,
}; };
use style::Atom; use style::Atom;
use crate::{FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor}; use crate::{
FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName,
};
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref FONT_LIST: FontList = FontList::new(); static ref FONT_LIST: FontList = FontList::new();
@ -185,16 +188,6 @@ where
} }
} }
pub fn system_default_family(generic_name: &str) -> Option<String> {
if let Some(family) = FONT_LIST.find_family(&generic_name) {
Some(family.name.clone())
} else if let Some(alias) = FONT_LIST.find_alias(&generic_name) {
Some(alias.from.clone())
} else {
FONT_LIST.families.get(0).map(|family| family.name.clone())
}
}
// Based on fonts present in OpenHarmony. // Based on fonts present in OpenHarmony.
pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> { pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> {
let mut families = vec![]; let mut families = vec![];
@ -242,4 +235,6 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st
families families
} }
pub static SANS_SERIF_FONT_FAMILY: &'static str = "HarmonyOS Sans"; pub fn default_system_generic_font_family(_generic: GenericFontFamily) -> LowercaseFontFamilyName {
"HarmonyOS Sans".into()
}

View file

@ -10,6 +10,7 @@ use base::text::{unicode_plane, UnicodeBlock, UnicodeBlockMethod};
use log::debug; use log::debug;
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::Atom; use style::Atom;
use unicode_script::Script; use unicode_script::Script;
use webrender_api::NativeFontHandle; use webrender_api::NativeFontHandle;
@ -17,7 +18,8 @@ use webrender_api::NativeFontHandle;
use crate::platform::add_noto_fallback_families; use crate::platform::add_noto_fallback_families;
use crate::platform::font::CoreTextFontTraitsMapping; use crate::platform::font::CoreTextFontTraitsMapping;
use crate::{ use crate::{
EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor, EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate,
FontTemplateDescriptor, LowercaseFontFamilyName,
}; };
/// An identifier for a local font on a MacOS system. These values comes from the CoreText /// An identifier for a local font on a MacOS system. These values comes from the CoreText
@ -89,10 +91,6 @@ where
} }
} }
pub fn system_default_family(_generic_name: &str) -> Option<String> {
None
}
/// Get the list of fallback fonts given an optional codepoint. This is /// Get the list of fallback fonts given an optional codepoint. This is
/// based on `gfxPlatformMac::GetCommonFallbackFonts()` in Gecko from /// based on `gfxPlatformMac::GetCommonFallbackFonts()` in Gecko from
/// <https://searchfox.org/mozilla-central/source/gfx/thebes/gfxPlatformMac.cpp>. /// <https://searchfox.org/mozilla-central/source/gfx/thebes/gfxPlatformMac.cpp>.
@ -210,4 +208,14 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st
families families
} }
pub static SANS_SERIF_FONT_FAMILY: &str = "Helvetica"; pub fn default_system_generic_font_family(generic: GenericFontFamily) -> LowercaseFontFamilyName {
match generic {
GenericFontFamily::None | GenericFontFamily::Serif => "Times",
GenericFontFamily::SansSerif => "Helvetica",
GenericFontFamily::Monospace => "Menlo",
GenericFontFamily::Cursive => "Apple Chancery",
GenericFontFamily::Fantasy => "Papyrus",
GenericFontFamily::SystemUi => "Menlo",
}
.into()
}

View file

@ -9,19 +9,15 @@ use base::text::{unicode_plane, UnicodeBlock, UnicodeBlockMethod};
use dwrote::{Font, FontCollection, FontDescriptor, FontStretch, FontStyle}; use dwrote::{Font, FontCollection, FontDescriptor, FontStretch, FontStyle};
use malloc_size_of_derive::MallocSizeOf; use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{FontStyle as StyleFontStyle, FontWeight as StyleFontWeight}; use style::values::computed::{FontStyle as StyleFontStyle, FontWeight as StyleFontWeight};
use style::values::specified::font::FontStretchKeyword; use style::values::specified::font::FontStretchKeyword;
use crate::{ use crate::{
EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor, EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate,
FontTemplateDescriptor, LowercaseFontFamilyName,
}; };
pub static SANS_SERIF_FONT_FAMILY: &str = "Arial";
pub fn system_default_family(_: &str) -> Option<String> {
Some("Verdana".to_owned())
}
pub fn for_each_available_family<F>(mut callback: F) pub fn for_each_available_family<F>(mut callback: F)
where where
F: FnMut(String), F: FnMut(String),
@ -377,3 +373,15 @@ impl From<&Font> for FontTemplateDescriptor {
FontTemplateDescriptor::new(weight, stretch, style) FontTemplateDescriptor::new(weight, stretch, style)
} }
} }
pub fn default_system_generic_font_family(generic: GenericFontFamily) -> LowercaseFontFamilyName {
match generic {
GenericFontFamily::None | GenericFontFamily::Serif => "Times New Roman",
GenericFontFamily::SansSerif => "Arial",
GenericFontFamily::Monospace => "Courier New",
GenericFontFamily::Cursive => "Comic Sans MS",
GenericFontFamily::Fantasy => "Impact",
GenericFontFamily::SystemUi => "Segoe UI",
}
.into()
}

View file

@ -12,8 +12,8 @@ use std::rc::Rc;
use app_units::Au; use app_units::Au;
use fonts::{ use fonts::{
fallback_font_families, CSSFontFaceDescriptors, FallbackFontSelectionOptions, FontContext, fallback_font_families, CSSFontFaceDescriptors, FallbackFontSelectionOptions, FontContext,
FontDescriptor, FontFamilyDescriptor, FontFamilyName, FontIdentifier, FontSearchScope, FontDescriptor, FontFamilyDescriptor, FontIdentifier, FontSearchScope, FontSource,
FontSource, FontTemplate, FontTemplateRef, FontTemplates, FontTemplate, FontTemplateRef, FontTemplates,
}; };
use ipc_channel::ipc; use ipc_channel::ipc;
use net_traits::ResourceThreads; use net_traits::ResourceThreads;
@ -97,12 +97,16 @@ impl FontSource for MockFontCacheThread {
fn find_matching_font_templates( fn find_matching_font_templates(
&self, &self,
descriptor_to_match: Option<&FontDescriptor>, descriptor_to_match: Option<&FontDescriptor>,
font_family_name: &FontFamilyName, font_family: &SingleFontFamily,
) -> Vec<FontTemplateRef> { ) -> Vec<FontTemplateRef> {
self.find_font_count.set(self.find_font_count.get() + 1); self.find_font_count.set(self.find_font_count.get() + 1);
let SingleFontFamily::FamilyName(family_name) = font_family else {
return Vec::new();
};
self.families self.families
.borrow_mut() .borrow_mut()
.get_mut(font_family_name.name()) .get_mut(&*family_name.name)
.map(|family| family.find_for_descriptor(descriptor_to_match)) .map(|family| family.find_for_descriptor(descriptor_to_match))
.unwrap_or_default() .unwrap_or_default()
} }
@ -295,8 +299,11 @@ fn test_font_template_is_cached() {
pt_size: Au(10), pt_size: Au(10),
}; };
let family_descriptor = let family = SingleFontFamily::FamilyName(FamilyName {
FontFamilyDescriptor::new(FontFamilyName::from("CSSTest Basic"), FontSearchScope::Any); name: "CSSTest Basic".into(),
syntax: FontFamilyNameSyntax::Quoted,
});
let family_descriptor = FontFamilyDescriptor::new(family, FontSearchScope::Any);
let font_template = context.matching_templates(&font_descriptor, &family_descriptor)[0].clone(); let font_template = context.matching_templates(&font_descriptor, &family_descriptor)[0].clone();

View file

@ -1350,14 +1350,9 @@ impl<'table> TableCellStyleInfo<'table> {
}; };
{ {
let cell_flow = &self.cell.block_flow; let cell_flow = &self.cell.block_flow;
let initial = ComputedValues::initial_values();
let build_dl = |sty: &ComputedValues, state: &mut &mut DisplayListBuildState| { let build_dl = |sty: &ComputedValues, state: &mut &mut DisplayListBuildState| {
let background = sty.get_background(); let background = sty.get_background();
// Don't redraw backgrounds that we've already drawn
if std::ptr::eq(background, initial.get_background()) {
return;
}
let background_color = sty.resolve_color(background.background_color.clone()); let background_color = sty.resolve_color(background.background_color.clone());
cell_flow.build_display_list_for_background_if_applicable_with_background( cell_flow.build_display_list_for_background_if_applicable_with_background(
state, state,

View file

@ -301,7 +301,11 @@ impl BoxTree {
layout_context: &LayoutContext, layout_context: &LayoutContext,
viewport: euclid::Size2D<f32, CSSPixel>, viewport: euclid::Size2D<f32, CSSPixel>,
) -> FragmentTree { ) -> FragmentTree {
let style = ComputedValues::initial_values(); let style = layout_context
.style_context
.stylist
.device()
.default_computed_values();
// FIXME: use the documents mode: // FIXME: use the documents mode:
// https://drafts.csswg.org/css-writing-modes/#principal-flow // https://drafts.csswg.org/css-writing-modes/#principal-flow

View file

@ -9,6 +9,7 @@ use std::iter::repeat;
use log::warn; use log::warn;
use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode; use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode;
use servo_arc::Arc; use servo_arc::Arc;
use style::properties::style_structs::Font;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::selector_parser::PseudoElement; use style::selector_parser::PseudoElement;
use style::str::char_is_whitespace; use style::str::char_is_whitespace;
@ -248,9 +249,11 @@ impl TableBuilder {
} }
pub fn new_for_tests() -> Self { pub fn new_for_tests() -> Self {
let testing_style =
ComputedValues::initial_values_with_font_override(Font::initial_values());
Self::new( Self::new(
ComputedValues::initial_values().to_arc(), testing_style.clone(),
ComputedValues::initial_values().to_arc(), testing_style.clone(),
BaseFragmentInfo::anonymous(), BaseFragmentInfo::anonymous(),
) )
} }

View file

@ -75,6 +75,7 @@ pub use construct::TableBuilder;
use euclid::{Point2D, Size2D, UnknownUnit, Vector2D}; use euclid::{Point2D, Size2D, UnknownUnit, Vector2D};
use serde::Serialize; use serde::Serialize;
use servo_arc::Arc; use servo_arc::Arc;
use style::properties::style_structs::Font;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style_traits::dom::OpaqueNode; use style_traits::dom::OpaqueNode;
@ -215,7 +216,8 @@ impl TableSlotCell {
}, },
colspan, colspan,
rowspan, rowspan,
style: ComputedValues::initial_values().to_arc(), style: ComputedValues::initial_values_with_font_override(Font::initial_values())
.to_arc(),
base_fragment_info: BaseFragmentInfo::new_for_node(OpaqueNode(id)), base_fragment_info: BaseFragmentInfo::new_for_node(OpaqueNode(id)),
} }
} }

View file

@ -73,6 +73,7 @@ use script_traits::{
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
use servo_atoms::Atom; use servo_atoms::Atom;
use servo_config::opts::{self, DebugOptions}; use servo_config::opts::{self, DebugOptions};
use servo_config::pref;
use servo_url::{ImmutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, ServoUrl};
use style::animation::{AnimationSetKey, DocumentAnimationSet, ElementAnimationSet}; use style::animation::{AnimationSetKey, DocumentAnimationSet, ElementAnimationSet};
use style::context::{ use style::context::{
@ -86,7 +87,7 @@ use style::invalidation::element::restyle_hints::RestyleHint;
use style::logical_geometry::LogicalPoint; use style::logical_geometry::LogicalPoint;
use style::media_queries::{Device, MediaList, MediaType}; use style::media_queries::{Device, MediaList, MediaType};
use style::properties::style_structs::Font; use style::properties::style_structs::Font;
use style::properties::PropertyId; use style::properties::{ComputedValues, PropertyId};
use style::selector_parser::{PseudoElement, SnapshotMap}; use style::selector_parser::{PseudoElement, SnapshotMap};
use style::servo::media_queries::FontMetricsProvider; use style::servo::media_queries::FontMetricsProvider;
use style::servo::restyle_damage::ServoRestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage;
@ -98,6 +99,9 @@ use style::stylesheets::{
use style::stylist::Stylist; use style::stylist::Stylist;
use style::traversal::DomTraversal; use style::traversal::DomTraversal;
use style::traversal_flags::TraversalFlags; use style::traversal_flags::TraversalFlags;
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{FontSize, Length, NonNegativeLength};
use style::values::specified::font::KeywordInfo;
use style_traits::{CSSPixel, DevicePixel, SpeculativePainter}; use style_traits::{CSSPixel, DevicePixel, SpeculativePainter};
use url::Url; use url::Url;
use webrender_api::{units, ColorF, HitTestFlags}; use webrender_api::{units, ColorF, HitTestFlags};
@ -579,6 +583,14 @@ impl LayoutThread {
// Let webrender know about this pipeline by sending an empty display list. // Let webrender know about this pipeline by sending an empty display list.
webrender_api.send_initial_transaction(id.into()); webrender_api.send_initial_transaction(id.into());
let mut font = Font::initial_values();
let default_font_size = pref!(fonts.default_size);
font.font_size = FontSize {
computed_size: NonNegativeLength::new(default_font_size as f32),
used_size: NonNegativeLength::new(default_font_size as f32),
keyword_info: KeywordInfo::medium(),
};
let font_context = Arc::new(FontContext::new(font_cache_thread, resource_threads)); let font_context = Arc::new(FontContext::new(font_cache_thread, resource_threads));
let device = Device::new( let device = Device::new(
MediaType::screen(), MediaType::screen(),
@ -586,6 +598,7 @@ impl LayoutThread {
window_size.initial_viewport, window_size.initial_viewport,
window_size.device_pixel_ratio, window_size.device_pixel_ratio,
Box::new(LayoutFontMetricsProvider), Box::new(LayoutFontMetricsProvider),
ComputedValues::initial_values_with_font_override(font),
); );
LayoutThread { LayoutThread {
@ -1409,6 +1422,7 @@ impl LayoutThread {
window_size_data.initial_viewport, window_size_data.initial_viewport,
window_size_data.device_pixel_ratio, window_size_data.device_pixel_ratio,
Box::new(LayoutFontMetricsProvider), Box::new(LayoutFontMetricsProvider),
self.stylist.device().default_computed_values().to_arc(),
); );
// Preserve any previously computed root font size. // Preserve any previously computed root font size.
@ -1631,4 +1645,12 @@ impl FontMetricsProvider for LayoutFontMetricsProvider {
) -> style::font_metrics::FontMetrics { ) -> style::font_metrics::FontMetrics {
Default::default() Default::default()
} }
fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
Length::new(match generic {
GenericFontFamily::Monospace => pref!(fonts.default_monospace_size),
_ => pref!(fonts.default_size),
} as f32)
.max(Length::new(0.0))
}
} }

View file

@ -59,6 +59,7 @@ use script_traits::{
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
use servo_atoms::Atom; use servo_atoms::Atom;
use servo_config::opts::{self, DebugOptions}; use servo_config::opts::{self, DebugOptions};
use servo_config::pref;
use servo_url::{ImmutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, ServoUrl};
use style::animation::DocumentAnimationSet; use style::animation::DocumentAnimationSet;
use style::context::{ use style::context::{
@ -71,7 +72,7 @@ use style::global_style_data::{GLOBAL_STYLE_DATA, STYLE_THREAD_POOL};
use style::invalidation::element::restyle_hints::RestyleHint; use style::invalidation::element::restyle_hints::RestyleHint;
use style::media_queries::{Device, MediaList, MediaType}; use style::media_queries::{Device, MediaList, MediaType};
use style::properties::style_structs::Font; use style::properties::style_structs::Font;
use style::properties::PropertyId; use style::properties::{ComputedValues, PropertyId};
use style::selector_parser::{PseudoElement, SnapshotMap}; use style::selector_parser::{PseudoElement, SnapshotMap};
use style::servo::media_queries::FontMetricsProvider; use style::servo::media_queries::FontMetricsProvider;
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards}; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
@ -82,7 +83,9 @@ use style::stylesheets::{
use style::stylist::Stylist; use style::stylist::Stylist;
use style::traversal::DomTraversal; use style::traversal::DomTraversal;
use style::traversal_flags::TraversalFlags; use style::traversal_flags::TraversalFlags;
use style::values::computed::CSSPixelLength; use style::values::computed::font::GenericFontFamily;
use style::values::computed::{CSSPixelLength, FontSize, Length, NonNegativeLength};
use style::values::specified::font::KeywordInfo;
use style::{driver, Zero}; use style::{driver, Zero};
use style_traits::{CSSPixel, DevicePixel, SpeculativePainter}; use style_traits::{CSSPixel, DevicePixel, SpeculativePainter};
use url::Url; use url::Url;
@ -494,6 +497,14 @@ impl LayoutThread {
// Let webrender know about this pipeline by sending an empty display list. // Let webrender know about this pipeline by sending an empty display list.
webrender_api_sender.send_initial_transaction(id.into()); webrender_api_sender.send_initial_transaction(id.into());
let mut font = Font::initial_values();
let default_font_size = pref!(fonts.default_size);
font.font_size = FontSize {
computed_size: NonNegativeLength::new(default_font_size as f32),
used_size: NonNegativeLength::new(default_font_size as f32),
keyword_info: KeywordInfo::medium(),
};
// The device pixel ratio is incorrect (it does not have the hidpi value), // The device pixel ratio is incorrect (it does not have the hidpi value),
// but it will be set correctly when the initial reflow takes place. // but it will be set correctly when the initial reflow takes place.
let font_context = Arc::new(FontContext::new(font_cache_thread, resource_threads)); let font_context = Arc::new(FontContext::new(font_cache_thread, resource_threads));
@ -503,6 +514,7 @@ impl LayoutThread {
window_size.initial_viewport, window_size.initial_viewport,
window_size.device_pixel_ratio, window_size.device_pixel_ratio,
Box::new(LayoutFontMetricsProvider(font_context.clone())), Box::new(LayoutFontMetricsProvider(font_context.clone())),
ComputedValues::initial_values_with_font_override(font),
); );
LayoutThread { LayoutThread {
@ -1043,6 +1055,7 @@ impl LayoutThread {
window_size_data.initial_viewport, window_size_data.initial_viewport,
window_size_data.device_pixel_ratio, window_size_data.device_pixel_ratio,
Box::new(LayoutFontMetricsProvider(self.font_context.clone())), Box::new(LayoutFontMetricsProvider(self.font_context.clone())),
self.stylist.device().default_computed_values().to_arc(),
); );
// Preserve any previously computed root font size. // Preserve any previously computed root font size.
@ -1262,6 +1275,14 @@ impl FontMetricsProvider for LayoutFontMetricsProvider {
script_script_percent_scale_down: None, script_script_percent_scale_down: None,
} }
} }
fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
Length::new(match generic {
GenericFontFamily::Monospace => pref!(fonts.default_monospace_size),
_ => pref!(fonts.default_size),
} as f32)
.max(Length::new(0.0))
}
} }
impl Debug for LayoutFontMetricsProvider { impl Debug for LayoutFontMetricsProvider {

View file

@ -14,7 +14,7 @@ use style::custom_properties::{
use style::font_metrics::FontMetrics; use style::font_metrics::FontMetrics;
use style::media_queries::{Device, MediaType}; use style::media_queries::{Device, MediaType};
use style::properties::style_structs::Font; use style::properties::style_structs::Font;
use style::properties::{CustomDeclaration, CustomDeclarationValue, StyleBuilder}; use style::properties::{ComputedValues, CustomDeclaration, CustomDeclarationValue, StyleBuilder};
use style::rule_cache::RuleCacheConditions; use style::rule_cache::RuleCacheConditions;
use style::rule_tree::CascadeLevel; use style::rule_tree::CascadeLevel;
use style::servo::media_queries::FontMetricsProvider; use style::servo::media_queries::FontMetricsProvider;
@ -22,6 +22,7 @@ use style::stylesheets::container_rule::ContainerSizeQuery;
use style::stylesheets::layer_rule::LayerOrder; use style::stylesheets::layer_rule::LayerOrder;
use style::stylesheets::UrlExtraData; use style::stylesheets::UrlExtraData;
use style::stylist::Stylist; use style::stylist::Stylist;
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{Context, Length}; use style::values::computed::{Context, Length};
use test::{self, Bencher}; use test::{self, Bencher};
use url::Url; use url::Url;
@ -40,6 +41,9 @@ impl FontMetricsProvider for DummyMetricsProvider {
) -> FontMetrics { ) -> FontMetrics {
Default::default() Default::default()
} }
fn base_size_for_generic(&self, _: GenericFontFamily) -> Length {
Length::new(16.)
}
} }
fn cascade( fn cascade(
@ -60,12 +64,14 @@ fn cascade(
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let initial_style = ComputedValues::initial_values_with_font_override(Font::initial_values());
let device = Device::new( let device = Device::new(
MediaType::screen(), MediaType::screen(),
QuirksMode::NoQuirks, QuirksMode::NoQuirks,
Size2D::new(800., 600.), Size2D::new(800., 600.),
Scale::new(1.0), Scale::new(1.0),
Box::new(DummyMetricsProvider), Box::new(DummyMetricsProvider),
initial_style,
); );
let stylist = Stylist::new(device, QuirksMode::NoQuirks); let stylist = Stylist::new(device, QuirksMode::NoQuirks);
let mut builder = StyleBuilder::new(stylist.device(), Some(&stylist), None, None, None, false); let mut builder = StyleBuilder::new(stylist.device(), Some(&stylist), None, None, None, false);

View file

@ -11,7 +11,9 @@ use style::context::QuirksMode;
use style::font_metrics::FontMetrics; use style::font_metrics::FontMetrics;
use style::media_queries::{Device, MediaType}; use style::media_queries::{Device, MediaType};
use style::properties::style_structs::Font; use style::properties::style_structs::Font;
use style::properties::{longhands, Importance, PropertyDeclaration, PropertyDeclarationBlock}; use style::properties::{
longhands, ComputedValues, Importance, PropertyDeclaration, PropertyDeclarationBlock,
};
use style::selector_map::SelectorMap; use style::selector_map::SelectorMap;
use style::selector_parser::{SelectorImpl, SelectorParser}; use style::selector_parser::{SelectorImpl, SelectorParser};
use style::servo::media_queries::FontMetricsProvider; use style::servo::media_queries::FontMetricsProvider;
@ -21,6 +23,7 @@ use style::stylist::{
needs_revalidation_for_testing, ContainerConditionId, LayerId, Rule, ScopeConditionId, Stylist, needs_revalidation_for_testing, ContainerConditionId, LayerId, Rule, ScopeConditionId, Stylist,
}; };
use style::thread_state::{self, ThreadState}; use style::thread_state::{self, ThreadState};
use style::values::computed::font::GenericFontFamily;
use style::values::computed::Length; use style::values::computed::Length;
use url::Url; use url::Url;
@ -38,6 +41,9 @@ impl FontMetricsProvider for DummyMetricsProvider {
) -> FontMetrics { ) -> FontMetrics {
Default::default() Default::default()
} }
fn base_size_for_generic(&self, _: GenericFontFamily) -> Length {
Length::new(16.)
}
} }
/// Helper method to get some Rules from selector strings. /// Helper method to get some Rules from selector strings.
@ -241,12 +247,14 @@ fn test_insert() {
} }
fn mock_stylist() -> Stylist { fn mock_stylist() -> Stylist {
let initial_style = ComputedValues::initial_values_with_font_override(Font::initial_values());
let device = Device::new( let device = Device::new(
MediaType::screen(), MediaType::screen(),
QuirksMode::NoQuirks, QuirksMode::NoQuirks,
Size2D::new(0f32, 0f32), Size2D::new(0f32, 0f32),
Scale::new(1.0), Scale::new(1.0),
Box::new(DummyMetricsProvider), Box::new(DummyMetricsProvider),
initial_style,
); );
Stylist::new(device, QuirksMode::NoQuirks) Stylist::new(device, QuirksMode::NoQuirks)
} }

View file

@ -1,3 +0,0 @@
[font-family-valid.html]
[e.style['font-family'\] = "System-UI" should set the property value]
expected: FAIL

View file

@ -1,2 +0,0 @@
[system-ui-ar.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[system-ui-mixed.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[system-ui-ur.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[system-ui.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[transform-input-017.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[input-checkbox-switch-rtl.tentative.html]
expected: FAIL

View file

@ -2236,7 +2236,7 @@
] ]
], ],
"font_size.html": [ "font_size.html": [
"4ffd55261f2f9e5b4dd2beaf8de8fb528c1de718", "4f0fafc984a312881c0182325c1dc8876ea67f09",
[ [
null, null,
[ [
@ -8724,7 +8724,7 @@
[] []
], ],
"font_face_attribute_ref.html": [ "font_face_attribute_ref.html": [
"f018747d2ab41119af5e06d6a018101169592cab", "14378f20cead025327c4cf296ac766b39ebea13a",
[] []
], ],
"font_fallback_failed_ref.html": [ "font_fallback_failed_ref.html": [
@ -8732,7 +8732,7 @@
[] []
], ],
"font_size_ref.html": [ "font_size_ref.html": [
"6bcf54338856d79af998eefad7bc7bb9f94d0236", "923a3c45c8a5c333b575bedfff8500291547f265",
[] []
], ],
"font_style_ref.html": [ "font_style_ref.html": [

View file

@ -2,8 +2,8 @@
<html> <html>
<head> <head>
</head> </head>
<body style="font-family: monospace"> <body>
<p>Servo</p> <p><span style="font-family: monospace;">Servo</span></p>
<p>Servo</p> <p><span style="font-family: monospace;">Servo</span></p>
</body> </body>
</html> </html>

View file

@ -10,10 +10,14 @@
<p style="font-size: 200%">200% is 40px. <p style="font-size: 200%">200% is 40px.
<p style="font-size: smaller">smaller is 16.66666…px. <p style="font-size: smaller">smaller is 16.66666…px.
<p style="font-size: larger">larger is 24px. <p style="font-size: larger">larger is 24px.
<p style="font-size: xx-small">xx-small is 9.6px. <!-- When the size is a keyword like the ones below, the resulting size is
<p style="font-size: x-small">x-small is 12px. based the "base size" of the generic font (or the default font size if
<p style="font-size: small">small is 14.2222…px. there is no generic font). Right now in Servo that size for serif is 16px
by default -->
<p style="font-size: xx-small">xx-small is 9px.
<p style="font-size: x-small">x-small is 10px.
<p style="font-size: small">small is 13px.
<p style="font-size: medium">medium is 16px. <p style="font-size: medium">medium is 16px.
<p style="font-size: large">large is 19.2px. <p style="font-size: large">large is 18px.
<p style="font-size: x-large">x-large is 24px. <p style="font-size: x-large">x-large is 24px.
<p style="font-size: xx-large">xx-large is 32px. <p style="font-size: xx-large">xx-large is 32px.

View file

@ -8,10 +8,10 @@
<p style="font-size: 40px">200% is 40px. <p style="font-size: 40px">200% is 40px.
<p style="font-size: 16.6666666666666666666666666666px">smaller is 16.66666…px. <p style="font-size: 16.6666666666666666666666666666px">smaller is 16.66666…px.
<p style="font-size: 24px">larger is 24px. <p style="font-size: 24px">larger is 24px.
<p style="font-size: 9.6px">xx-small is 9.6px. <p style="font-size: 9px">xx-small is 9px.
<p style="font-size: 12px">x-small is 12px. <p style="font-size: 10px">x-small is 10px.
<p style="font-size: 14.2222222222222222222222222222px">small is 14.2222…px. <p style="font-size: 13px">small is 13px.
<p style="font-size: 16px">medium is 16px. <p style="font-size: 16px">medium is 16px.
<p style="font-size: 19.2px">large is 19.2px. <p style="font-size: 18px">large is 18px.
<p style="font-size: 24px">x-large is 24px. <p style="font-size: 24px">x-large is 24px.
<p style="font-size: 32px">xx-large is 32px. <p style="font-size: 32px">xx-large is 32px.