From 77e9e3deba3925e8024719a6c3c54fbd4dddee7a Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Mon, 8 Jul 2024 19:17:48 +0200 Subject: [PATCH] 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 Co-authored-by: Mukilan Thiyagarajan --- Cargo.lock | 27 +-- components/config/prefs.rs | 25 +++ components/fonts/Cargo.toml | 1 + components/fonts/font.rs | 85 +++------- components/fonts/font_cache_thread.rs | 155 ++++++++++-------- components/fonts/font_context.rs | 66 +++++--- components/fonts/font_store.rs | 4 +- .../platform/freetype/android/font_list.rs | 28 ++-- .../fonts/platform/freetype/font_list.rs | 90 ++++++---- .../fonts/platform/freetype/ohos/font_list.rs | 19 +-- components/fonts/platform/macos/font_list.rs | 20 ++- .../fonts/platform/windows/font_list.rs | 22 ++- components/fonts/tests/font_context.rs | 19 ++- components/layout/table.rs | 5 - components/layout_2020/flow/root.rs | 6 +- components/layout_2020/table/construct.rs | 7 +- components/layout_2020/table/mod.rs | 4 +- components/layout_thread/lib.rs | 24 ++- components/layout_thread_2020/lib.rs | 25 ++- tests/unit/style/custom_properties.rs | 8 +- tests/unit/style/stylist.rs | 10 +- .../parsing/font-family-valid.html.ini | 3 - .../meta/css/css-fonts/system-ui-ar.html.ini | 2 - .../css/css-fonts/system-ui-mixed.html.ini | 2 - .../meta/css/css-fonts/system-ui-ur.html.ini | 2 - .../wpt/meta/css/css-fonts/system-ui.html.ini | 2 - .../transform-input-017.html.ini | 2 - ...put-checkbox-switch-rtl.tentative.html.ini | 2 - tests/wpt/mozilla/meta/MANIFEST.json | 6 +- .../tests/css/font_face_attribute_ref.html | 6 +- tests/wpt/mozilla/tests/css/font_size.html | 12 +- .../wpt/mozilla/tests/css/font_size_ref.html | 8 +- 32 files changed, 397 insertions(+), 300 deletions(-) delete mode 100644 tests/wpt/meta/css/css-fonts/parsing/font-family-valid.html.ini delete mode 100644 tests/wpt/meta/css/css-fonts/system-ui-ar.html.ini delete mode 100644 tests/wpt/meta/css/css-fonts/system-ui-mixed.html.ini delete mode 100644 tests/wpt/meta/css/css-fonts/system-ui-ur.html.ini delete mode 100644 tests/wpt/meta/css/css-fonts/system-ui.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-input-017.html.ini delete mode 100644 tests/wpt/meta/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html.ini diff --git a/Cargo.lock b/Cargo.lock index ff3094ecbd4..b02b5552592 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "derive_common" 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 = [ "darling", "proc-macro2", @@ -1838,6 +1838,7 @@ dependencies = [ "servo_allocator", "servo_arc", "servo_atoms", + "servo_config", "servo_url", "smallvec", "style", @@ -3755,7 +3756,7 @@ dependencies = [ [[package]] name = "malloc_size_of" 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 = [ "accountable-refcell", "app_units", @@ -5405,7 +5406,7 @@ dependencies = [ [[package]] name = "selectors" 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 = [ "bitflags 2.6.0", "cssparser", @@ -5693,7 +5694,7 @@ dependencies = [ [[package]] name = "servo_arc" 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 = [ "nodrop", "serde", @@ -5703,7 +5704,7 @@ dependencies = [ [[package]] name = "servo_atoms" 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 = [ "string_cache", "string_cache_codegen", @@ -5890,7 +5891,7 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "size_of_test" 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 = [ "static_assertions", ] @@ -6031,7 +6032,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "static_prefs" 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]] name = "strict-num" @@ -6068,7 +6069,7 @@ dependencies = [ [[package]] name = "style" 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 = [ "app_units", "arrayvec", @@ -6126,7 +6127,7 @@ dependencies = [ [[package]] name = "style_config" 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 = [ "lazy_static", ] @@ -6134,7 +6135,7 @@ dependencies = [ [[package]] name = "style_derive" 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 = [ "darling", "derive_common", @@ -6165,7 +6166,7 @@ dependencies = [ [[package]] name = "style_traits" 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 = [ "app_units", "bitflags 2.6.0", @@ -6515,7 +6516,7 @@ dependencies = [ [[package]] name = "to_shmem" 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 = [ "cssparser", "servo_arc", @@ -6528,7 +6529,7 @@ dependencies = [ [[package]] name = "to_shmem_derive" 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 = [ "darling", "derive_common", diff --git a/components/config/prefs.rs b/components/config/prefs.rs index c758e0cfe8a..0780dcd9536 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -165,6 +165,14 @@ mod gen { 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 { 0x000000 } @@ -188,6 +196,23 @@ mod gen { 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: { animations: { testing: { diff --git a/components/fonts/Cargo.toml b/components/fonts/Cargo.toml index e8a165c0524..a0301ceaad8 100644 --- a/components/fonts/Cargo.toml +++ b/components/fonts/Cargo.toml @@ -36,6 +36,7 @@ range = { path = "../range" } serde = { workspace = true } servo_arc = { workspace = true } servo_atoms = { workspace = true } +servo_config = { path = "../config" } servo_url = { path = "../url" } smallvec = { workspace = true, features = ["union"] } surfman = { workspace = true } diff --git a/components/fonts/font.rs b/components/fonts/font.rs index 918186ecc0c..dd3cbe7d2cc 100644 --- a/components/fonts/font.rs +++ b/components/fonts/font.rs @@ -16,11 +16,12 @@ use log::debug; use malloc_size_of_derive::MallocSizeOf; use parking_lot::RwLock; use serde::{Deserialize, Serialize}; -use servo_atoms::{atom, Atom}; use smallvec::SmallVec; use style::computed_values::font_variant_caps; 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 unicode_script::Script; use webrender_api::{FontInstanceFlags, FontInstanceKey}; @@ -629,10 +630,18 @@ impl FontGroup { TemplatePredicate: Fn(FontTemplateRef) -> bool, FontPredicate: Fn(&FontRef) -> bool, { - iter::once(FontFamilyDescriptor::serif()) - .chain(fallback_font_families(options).into_iter().map(|family| { - FontFamilyDescriptor::new(FontFamilyName::from(family), FontSearchScope::Local) - })) + iter::once(FontFamilyDescriptor::default()) + .chain( + 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| { FontGroupFamily { family_descriptor, @@ -675,11 +684,8 @@ struct FontGroupFamily { impl FontGroupFamily { fn new(family: &SingleFontFamily) -> FontGroupFamily { - let family_descriptor = - FontFamilyDescriptor::new(FontFamilyName::from(family), FontSearchScope::Any); - FontGroupFamily { - family_descriptor, + family_descriptor: FontFamilyDescriptor::new(family.clone(), FontSearchScope::Any), members: None, } } @@ -781,73 +787,24 @@ pub enum FontSearchScope { 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. #[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct FontFamilyDescriptor { - pub name: FontFamilyName, + pub family: SingleFontFamily, pub scope: FontSearchScope, } impl FontFamilyDescriptor { - pub fn new(name: FontFamilyName, scope: FontSearchScope) -> FontFamilyDescriptor { - FontFamilyDescriptor { name, scope } + pub fn new(family: SingleFontFamily, scope: FontSearchScope) -> FontFamilyDescriptor { + FontFamilyDescriptor { family, scope } } - fn serif() -> FontFamilyDescriptor { + fn default() -> FontFamilyDescriptor { FontFamilyDescriptor { - name: FontFamilyName::Generic(atom!("serif")), + family: SingleFontFamily::Generic(GenericFontFamily::None), scope: FontSearchScope::Local, } } - - pub fn name(&self) -> &str { - self.name.name() - } } /// Given a mapping array `mapping` and a value, map that value onto diff --git a/components/fonts/font_cache_thread.rs b/components/fonts/font_cache_thread.rs index bde22d4b515..0e45f0ab1a5 100644 --- a/components/fonts/font_cache_thread.rs +++ b/components/fonts/font_cache_thread.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::borrow::ToOwned; +use std::cell::OnceCell; use std::collections::HashMap; use std::ops::{Deref, RangeInclusive}; use std::sync::Arc; @@ -14,23 +15,25 @@ use ipc_channel::ipc::{self, IpcBytesReceiver, IpcBytesSender, IpcReceiver, IpcS use log::debug; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; -use servo_atoms::Atom; +use servo_config::pref; use servo_url::ServoUrl; 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::specified::FontStretch as SpecifiedFontStretch; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; use webrender_traits::WebRenderFontApi; -use crate::font::{FontDescriptor, FontFamilyName}; +use crate::font::FontDescriptor; use crate::font_store::FontStore; use crate::font_template::{ FontTemplate, FontTemplateDescriptor, FontTemplateRef, FontTemplateRefMethods, }; use crate::platform::font_list::{ - for_each_available_family, for_each_variation, system_default_family, LocalFontIdentifier, - SANS_SERIF_FONT_FAMILY, + default_system_generic_font_family, for_each_available_family, for_each_variation, + LocalFontIdentifier, }; #[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] @@ -60,7 +63,7 @@ pub struct SerializedFontTemplate { pub enum Command { GetFontTemplates( Option, - FontFamilyName, + SingleFontFamily, IpcSender>, ), GetFontInstance( @@ -75,43 +78,27 @@ pub enum Command { Ping, } +#[derive(Default)] +struct ResolvedGenericFontFamilies { + default: OnceCell, + serif: OnceCell, + sans_serif: OnceCell, + monospace: OnceCell, + fantasy: OnceCell, + cursive: OnceCell, + system_ui: OnceCell, +} + /// The font cache thread itself. It maintains a list of reference counted /// font templates that are currently in use. struct FontCache { port: IpcReceiver, - generic_fonts: HashMap, font_data: HashMap>>, local_families: FontStore, webrender_api: Box, webrender_fonts: HashMap, font_instances: HashMap<(FontKey, Au), FontInstanceKey>, -} - -fn populate_generic_fonts() -> HashMap { - 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, - 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 + generic_fonts: ResolvedGenericFontFamilies, } impl FontCache { @@ -120,9 +107,9 @@ impl FontCache { let msg = self.port.recv().unwrap(); match msg { - Command::GetFontTemplates(descriptor_to_match, font_family_name, result) => { + Command::GetFontTemplates(descriptor_to_match, font_family, result) => { 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!(" {templates:?}"); @@ -192,28 +179,21 @@ impl FontCache { fn refresh_local_families(&mut self) { self.local_families.clear(); for_each_available_family(|family_name| { - let family_name = LowercaseString::new(&family_name); - self.local_families.families.entry(family_name).or_default(); + self.local_families + .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( &mut self, descriptor_to_match: Option<&FontDescriptor>, - family_name: &FontFamilyName, + family: &SingleFontFamily, ) -> Vec { // TODO(Issue #188): look up localized font family names if canonical name not found // look up canonical name - // TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'. - // if such family exists, try to match style to a font - let family_name = self.transform_family(family_name); + let family_name = self.family_name_for_single_font_family(family); self.local_families .families .get_mut(&family_name) @@ -267,13 +247,53 @@ impl FontCache { 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 { fn find_matching_font_templates( &self, descriptor_to_match: Option<&FontDescriptor>, - font_family_name: &FontFamilyName, + font_family_name: &SingleFontFamily, ) -> Vec; fn get_system_font_instance( &self, @@ -313,7 +333,7 @@ pub enum ComputedFontStyleDescriptor { /// on the contents of the font itself. #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct CSSFontFaceDescriptors { - pub family_name: LowercaseString, + pub family_name: LowercaseFontFamilyName, pub weight: Option<(FontWeight, FontWeight)>, pub stretch: Option<(FontStretch, FontStretch)>, pub style: Option, @@ -323,7 +343,7 @@ pub struct CSSFontFaceDescriptors { impl CSSFontFaceDescriptors { pub fn new(family_name: &str) -> Self { CSSFontFaceDescriptors { - family_name: LowercaseString::new(family_name), + family_name: family_name.into(), ..Default::default() } } @@ -373,7 +393,7 @@ impl From<&FontFaceRuleData> for CSSFontFaceDescriptors { .map(|ranges| ranges.iter().map(|range| range.start..=range.end).collect()); CSSFontFaceDescriptors { - family_name: LowercaseString::new(&family_name), + family_name: family_name.into(), weight, stretch, style, @@ -389,18 +409,15 @@ impl FontCacheThread { thread::Builder::new() .name("FontCache".to_owned()) .spawn(move || { - // TODO: Allow users to specify these. - let generic_fonts = populate_generic_fonts(); - #[allow(clippy::default_constructed_unit_structs)] let mut cache = FontCache { port, - generic_fonts, font_data: HashMap::new(), local_families: Default::default(), webrender_api, webrender_fonts: HashMap::new(), font_instances: HashMap::new(), + generic_fonts: Default::default(), }; cache.refresh_local_families(); @@ -454,13 +471,13 @@ impl FontSource for FontCacheThread { fn find_matching_font_templates( &self, descriptor_to_match: Option<&FontDescriptor>, - font_family_name: &FontFamilyName, + font_family: &SingleFontFamily, ) -> Vec { let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel"); self.chan .send(Command::GetFontTemplates( descriptor_to_match.cloned(), - font_family_name.clone(), + font_family.clone(), response_chan, )) .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)] -pub struct LowercaseString { +pub struct LowercaseFontFamilyName { inner: String, } -impl LowercaseString { - pub fn new(s: &str) -> LowercaseString { - LowercaseString { - inner: s.to_lowercase(), +impl> From for LowercaseFontFamilyName { + fn from(value: T) -> Self { + LowercaseFontFamilyName { + inner: value.as_ref().to_lowercase(), } } } -impl<'a> From<&'a FontFamilyName> for LowercaseString { - fn from(family_name: &'a FontFamilyName) -> LowercaseString { - LowercaseString::new(family_name.name()) - } -} - -impl Deref for LowercaseString { +impl Deref for LowercaseFontFamilyName { type Target = str; #[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 { self.inner.fmt(f) } diff --git a/components/fonts/font_context.rs b/components/fonts/font_context.rs index ef02f7d07d9..efadb035067 100644 --- a/components/fonts/font_context.rs +++ b/components/fonts/font_context.rs @@ -25,18 +25,18 @@ use style::media_queries::Device; use style::properties::style_structs::Font as FontStyleStruct; use style::shared_lock::SharedRwLockReadGuard; use style::stylesheets::{CssRule, DocumentStyleSheet, FontFaceRule, StylesheetInDocument}; +use style::values::computed::font::{FamilyName, FontFamilyNameSyntax, SingleFontFamily}; use style::Atom; use url::Url; use webrender_api::{FontInstanceKey, FontKey}; use crate::font::{ - Font, FontDescriptor, FontFamilyDescriptor, FontFamilyName, FontGroup, FontRef, FontSearchScope, -}; -use crate::font_cache_thread::{ - CSSFontFaceDescriptors, FontIdentifier, FontSource, LowercaseString, + Font, FontDescriptor, FontFamilyDescriptor, FontGroup, FontRef, FontSearchScope, }; +use crate::font_cache_thread::{CSSFontFaceDescriptors, FontIdentifier, FontSource}; use crate::font_store::{CrossThreadFontStore, CrossThreadWebRenderFontStore}; use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods}; +use crate::LowercaseFontFamilyName; static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h) @@ -170,28 +170,39 @@ impl FontContext { font } + fn matching_web_font_templates( + &self, + descriptor_to_match: &FontDescriptor, + family_descriptor: &FontFamilyDescriptor, + ) -> Option> { + 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( &self, descriptor_to_match: &FontDescriptor, family_descriptor: &FontFamilyDescriptor, ) -> Vec { - // First try to find an appropriate web font that matches this descriptor. - if family_descriptor.scope == FontSearchScope::Any { - let family_name = LowercaseString::from(&family_descriptor.name); - if let Some(templates) = self - .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) + self.matching_web_font_templates(descriptor_to_match, family_descriptor) + .unwrap_or_else(|| { + self.cache + .matching_templates(descriptor_to_match, family_descriptor) + }) } /// Create a `Font` for use in layout calculations, from a `FontTemplateData` returned by the @@ -310,10 +321,13 @@ impl FontContextWebFontMethods for Arc FontContextWebFontMethods for Arc { font_context: Arc>, url: ServoArc, - web_font_family_name: LowercaseString, + web_font_family_name: LowercaseFontFamilyName, response_valid: Mutex, response_data: Mutex>, } @@ -468,7 +482,7 @@ impl RemoteWebFontDownloader { fn download( url_source: UrlSource, font_context: Arc>, - web_font_family_name: LowercaseString, + web_font_family_name: LowercaseFontFamilyName, state: WebFontDownloadState, ) { // https://drafts.csswg.org/css-fonts/#font-fetching-requirements @@ -652,7 +666,7 @@ impl CachingFontSource { let templates = self .font_cache_thread .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()); templates diff --git a/components/fonts/font_store.rs b/components/fonts/font_store.rs index ff6d56abac2..e5287b5bf88 100644 --- a/components/fonts/font_store.rs +++ b/components/fonts/font_store.rs @@ -14,13 +14,13 @@ use style::values::computed::{FontStyle, FontWeight}; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; 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_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods, IsOblique}; #[derive(Default)] pub struct FontStore { - pub(crate) families: HashMap, + pub(crate) families: HashMap, web_fonts_loading: Vec<(DocumentStyleSheet, usize)>, } pub(crate) type CrossThreadFontStore = Arc>; diff --git a/components/fonts/platform/freetype/android/font_list.rs b/components/fonts/platform/freetype/android/font_list.rs index 0fd0c336487..b7152a8efc7 100644 --- a/components/fonts/platform/freetype/android/font_list.rs +++ b/components/fonts/platform/freetype/android/font_list.rs @@ -10,13 +10,16 @@ use base::text::{is_cjk, UnicodeBlock, UnicodeBlockMethod}; use log::warn; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; +use style::values::computed::font::GenericFontFamily; use style::values::computed::{ FontStretch as StyleFontStretch, FontStyle as StyleFontStyle, FontWeight as StyleFontWeight, }; use style::Atom; use super::xml::{Attribute, Node}; -use crate::{FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor}; +use crate::{ + FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName, +}; lazy_static::lazy_static! { static ref FONT_LIST: FontList = FontList::new(); @@ -515,17 +518,6 @@ where } } -pub fn system_default_family(generic_name: &str) -> Option { - 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 pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> { let mut families = vec![]; @@ -581,4 +573,14 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st 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() +} diff --git a/components/fonts/platform/freetype/font_list.rs b/components/fonts/platform/freetype/font_list.rs index 95e4b4043d2..0212344ba45 100644 --- a/components/fonts/platform/freetype/font_list.rs +++ b/components/fonts/platform/freetype/font_list.rs @@ -27,6 +27,7 @@ use libc::{c_char, c_int}; use log::debug; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; +use style::values::computed::font::GenericFontFamily; use style::values::computed::{FontStretch, FontStyle, FontWeight}; use style::Atom; 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_template::{FontTemplate, FontTemplateDescriptor}; 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. #[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] @@ -166,41 +167,6 @@ where } } -pub fn system_default_family(generic_name: &str) -> Option { - 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 pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> { let mut families = Vec::new(); @@ -241,6 +207,58 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st 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 { let mut slant: c_int = 0; unsafe { diff --git a/components/fonts/platform/freetype/ohos/font_list.rs b/components/fonts/platform/freetype/ohos/font_list.rs index 819535a618d..ee14200f0d1 100644 --- a/components/fonts/platform/freetype/ohos/font_list.rs +++ b/components/fonts/platform/freetype/ohos/font_list.rs @@ -10,12 +10,15 @@ use base::text::{is_cjk, UnicodeBlock, UnicodeBlockMethod}; use log::warn; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; +use style::values::computed::font::GenericFontFamily; use style::values::computed::{ FontStretch as StyleFontStretch, FontStyle as StyleFontStyle, FontWeight as StyleFontWeight, }; use style::Atom; -use crate::{FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor}; +use crate::{ + FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName, +}; lazy_static::lazy_static! { static ref FONT_LIST: FontList = FontList::new(); @@ -185,16 +188,6 @@ where } } -pub fn system_default_family(generic_name: &str) -> Option { - 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. pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> { let mut families = vec![]; @@ -242,4 +235,6 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st families } -pub static SANS_SERIF_FONT_FAMILY: &'static str = "HarmonyOS Sans"; +pub fn default_system_generic_font_family(_generic: GenericFontFamily) -> LowercaseFontFamilyName { + "HarmonyOS Sans".into() +} diff --git a/components/fonts/platform/macos/font_list.rs b/components/fonts/platform/macos/font_list.rs index b2176b31f42..a2d12c4247f 100644 --- a/components/fonts/platform/macos/font_list.rs +++ b/components/fonts/platform/macos/font_list.rs @@ -10,6 +10,7 @@ use base::text::{unicode_plane, UnicodeBlock, UnicodeBlockMethod}; use log::debug; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; +use style::values::computed::font::GenericFontFamily; use style::Atom; use unicode_script::Script; use webrender_api::NativeFontHandle; @@ -17,7 +18,8 @@ use webrender_api::NativeFontHandle; use crate::platform::add_noto_fallback_families; use crate::platform::font::CoreTextFontTraitsMapping; 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 @@ -89,10 +91,6 @@ where } } -pub fn system_default_family(_generic_name: &str) -> Option { - None -} - /// Get the list of fallback fonts given an optional codepoint. This is /// based on `gfxPlatformMac::GetCommonFallbackFonts()` in Gecko from /// . @@ -210,4 +208,14 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st 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() +} diff --git a/components/fonts/platform/windows/font_list.rs b/components/fonts/platform/windows/font_list.rs index 31c1d631160..3a2c32e66be 100644 --- a/components/fonts/platform/windows/font_list.rs +++ b/components/fonts/platform/windows/font_list.rs @@ -9,19 +9,15 @@ use base::text::{unicode_plane, UnicodeBlock, UnicodeBlockMethod}; use dwrote::{Font, FontCollection, FontDescriptor, FontStretch, FontStyle}; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; +use style::values::computed::font::GenericFontFamily; use style::values::computed::{FontStyle as StyleFontStyle, FontWeight as StyleFontWeight}; use style::values::specified::font::FontStretchKeyword; 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 { - Some("Verdana".to_owned()) -} - pub fn for_each_available_family(mut callback: F) where F: FnMut(String), @@ -377,3 +373,15 @@ impl From<&Font> for FontTemplateDescriptor { 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() +} diff --git a/components/fonts/tests/font_context.rs b/components/fonts/tests/font_context.rs index 652760d7f33..eb1154e6e8f 100644 --- a/components/fonts/tests/font_context.rs +++ b/components/fonts/tests/font_context.rs @@ -12,8 +12,8 @@ use std::rc::Rc; use app_units::Au; use fonts::{ fallback_font_families, CSSFontFaceDescriptors, FallbackFontSelectionOptions, FontContext, - FontDescriptor, FontFamilyDescriptor, FontFamilyName, FontIdentifier, FontSearchScope, - FontSource, FontTemplate, FontTemplateRef, FontTemplates, + FontDescriptor, FontFamilyDescriptor, FontIdentifier, FontSearchScope, FontSource, + FontTemplate, FontTemplateRef, FontTemplates, }; use ipc_channel::ipc; use net_traits::ResourceThreads; @@ -97,12 +97,16 @@ impl FontSource for MockFontCacheThread { fn find_matching_font_templates( &self, descriptor_to_match: Option<&FontDescriptor>, - font_family_name: &FontFamilyName, + font_family: &SingleFontFamily, ) -> Vec { self.find_font_count.set(self.find_font_count.get() + 1); + let SingleFontFamily::FamilyName(family_name) = font_family else { + return Vec::new(); + }; + self.families .borrow_mut() - .get_mut(font_family_name.name()) + .get_mut(&*family_name.name) .map(|family| family.find_for_descriptor(descriptor_to_match)) .unwrap_or_default() } @@ -295,8 +299,11 @@ fn test_font_template_is_cached() { pt_size: Au(10), }; - let family_descriptor = - FontFamilyDescriptor::new(FontFamilyName::from("CSSTest Basic"), FontSearchScope::Any); + let family = SingleFontFamily::FamilyName(FamilyName { + 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(); diff --git a/components/layout/table.rs b/components/layout/table.rs index b91e77966ee..cc257c854f5 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -1350,14 +1350,9 @@ impl<'table> TableCellStyleInfo<'table> { }; { let cell_flow = &self.cell.block_flow; - let initial = ComputedValues::initial_values(); let build_dl = |sty: &ComputedValues, state: &mut &mut DisplayListBuildState| { 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()); cell_flow.build_display_list_for_background_if_applicable_with_background( state, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 16d242d728b..0530de0b8f7 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -301,7 +301,11 @@ impl BoxTree { layout_context: &LayoutContext, viewport: euclid::Size2D, ) -> FragmentTree { - let style = ComputedValues::initial_values(); + let style = layout_context + .style_context + .stylist + .device() + .default_computed_values(); // FIXME: use the document’s mode: // https://drafts.csswg.org/css-writing-modes/#principal-flow diff --git a/components/layout_2020/table/construct.rs b/components/layout_2020/table/construct.rs index 8e90cab0e4a..db7d515aa3e 100644 --- a/components/layout_2020/table/construct.rs +++ b/components/layout_2020/table/construct.rs @@ -9,6 +9,7 @@ use std::iter::repeat; use log::warn; use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode; use servo_arc::Arc; +use style::properties::style_structs::Font; use style::properties::ComputedValues; use style::selector_parser::PseudoElement; use style::str::char_is_whitespace; @@ -248,9 +249,11 @@ impl TableBuilder { } pub fn new_for_tests() -> Self { + let testing_style = + ComputedValues::initial_values_with_font_override(Font::initial_values()); Self::new( - ComputedValues::initial_values().to_arc(), - ComputedValues::initial_values().to_arc(), + testing_style.clone(), + testing_style.clone(), BaseFragmentInfo::anonymous(), ) } diff --git a/components/layout_2020/table/mod.rs b/components/layout_2020/table/mod.rs index 2296c72a5dd..1e29e605605 100644 --- a/components/layout_2020/table/mod.rs +++ b/components/layout_2020/table/mod.rs @@ -75,6 +75,7 @@ pub use construct::TableBuilder; use euclid::{Point2D, Size2D, UnknownUnit, Vector2D}; use serde::Serialize; use servo_arc::Arc; +use style::properties::style_structs::Font; use style::properties::ComputedValues; use style_traits::dom::OpaqueNode; @@ -215,7 +216,8 @@ impl TableSlotCell { }, colspan, 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)), } } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 2973c4fd0c1..b9a52ee4986 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -73,6 +73,7 @@ use script_traits::{ use servo_arc::Arc as ServoArc; use servo_atoms::Atom; use servo_config::opts::{self, DebugOptions}; +use servo_config::pref; use servo_url::{ImmutableOrigin, ServoUrl}; use style::animation::{AnimationSetKey, DocumentAnimationSet, ElementAnimationSet}; use style::context::{ @@ -86,7 +87,7 @@ use style::invalidation::element::restyle_hints::RestyleHint; use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaList, MediaType}; use style::properties::style_structs::Font; -use style::properties::PropertyId; +use style::properties::{ComputedValues, PropertyId}; use style::selector_parser::{PseudoElement, SnapshotMap}; use style::servo::media_queries::FontMetricsProvider; use style::servo::restyle_damage::ServoRestyleDamage; @@ -98,6 +99,9 @@ use style::stylesheets::{ use style::stylist::Stylist; use style::traversal::DomTraversal; 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 url::Url; use webrender_api::{units, ColorF, HitTestFlags}; @@ -579,6 +583,14 @@ impl LayoutThread { // Let webrender know about this pipeline by sending an empty display list. 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 device = Device::new( MediaType::screen(), @@ -586,6 +598,7 @@ impl LayoutThread { window_size.initial_viewport, window_size.device_pixel_ratio, Box::new(LayoutFontMetricsProvider), + ComputedValues::initial_values_with_font_override(font), ); LayoutThread { @@ -1409,6 +1422,7 @@ impl LayoutThread { window_size_data.initial_viewport, window_size_data.device_pixel_ratio, Box::new(LayoutFontMetricsProvider), + self.stylist.device().default_computed_values().to_arc(), ); // Preserve any previously computed root font size. @@ -1631,4 +1645,12 @@ impl FontMetricsProvider for LayoutFontMetricsProvider { ) -> style::font_metrics::FontMetrics { 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)) + } } diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 41a15df6cc7..84ff7d2fbed 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -59,6 +59,7 @@ use script_traits::{ use servo_arc::Arc as ServoArc; use servo_atoms::Atom; use servo_config::opts::{self, DebugOptions}; +use servo_config::pref; use servo_url::{ImmutableOrigin, ServoUrl}; use style::animation::DocumentAnimationSet; 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::media_queries::{Device, MediaList, MediaType}; use style::properties::style_structs::Font; -use style::properties::PropertyId; +use style::properties::{ComputedValues, PropertyId}; use style::selector_parser::{PseudoElement, SnapshotMap}; use style::servo::media_queries::FontMetricsProvider; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards}; @@ -82,7 +83,9 @@ use style::stylesheets::{ use style::stylist::Stylist; use style::traversal::DomTraversal; 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_traits::{CSSPixel, DevicePixel, SpeculativePainter}; use url::Url; @@ -494,6 +497,14 @@ impl LayoutThread { // Let webrender know about this pipeline by sending an empty display list. 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), // but it will be set correctly when the initial reflow takes place. let font_context = Arc::new(FontContext::new(font_cache_thread, resource_threads)); @@ -503,6 +514,7 @@ impl LayoutThread { window_size.initial_viewport, window_size.device_pixel_ratio, Box::new(LayoutFontMetricsProvider(font_context.clone())), + ComputedValues::initial_values_with_font_override(font), ); LayoutThread { @@ -1043,6 +1055,7 @@ impl LayoutThread { window_size_data.initial_viewport, window_size_data.device_pixel_ratio, Box::new(LayoutFontMetricsProvider(self.font_context.clone())), + self.stylist.device().default_computed_values().to_arc(), ); // Preserve any previously computed root font size. @@ -1262,6 +1275,14 @@ impl FontMetricsProvider for LayoutFontMetricsProvider { 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 { diff --git a/tests/unit/style/custom_properties.rs b/tests/unit/style/custom_properties.rs index 6c61805aab6..93eafe16fe7 100644 --- a/tests/unit/style/custom_properties.rs +++ b/tests/unit/style/custom_properties.rs @@ -14,7 +14,7 @@ use style::custom_properties::{ use style::font_metrics::FontMetrics; use style::media_queries::{Device, MediaType}; 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_tree::CascadeLevel; 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::UrlExtraData; use style::stylist::Stylist; +use style::values::computed::font::GenericFontFamily; use style::values::computed::{Context, Length}; use test::{self, Bencher}; use url::Url; @@ -40,6 +41,9 @@ impl FontMetricsProvider for DummyMetricsProvider { ) -> FontMetrics { Default::default() } + fn base_size_for_generic(&self, _: GenericFontFamily) -> Length { + Length::new(16.) + } } fn cascade( @@ -60,12 +64,14 @@ fn cascade( }) .collect::>(); + let initial_style = ComputedValues::initial_values_with_font_override(Font::initial_values()); let device = Device::new( MediaType::screen(), QuirksMode::NoQuirks, Size2D::new(800., 600.), Scale::new(1.0), Box::new(DummyMetricsProvider), + initial_style, ); let stylist = Stylist::new(device, QuirksMode::NoQuirks); let mut builder = StyleBuilder::new(stylist.device(), Some(&stylist), None, None, None, false); diff --git a/tests/unit/style/stylist.rs b/tests/unit/style/stylist.rs index 2b6f1a9437c..eab122d4b23 100644 --- a/tests/unit/style/stylist.rs +++ b/tests/unit/style/stylist.rs @@ -11,7 +11,9 @@ use style::context::QuirksMode; use style::font_metrics::FontMetrics; use style::media_queries::{Device, MediaType}; 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_parser::{SelectorImpl, SelectorParser}; use style::servo::media_queries::FontMetricsProvider; @@ -21,6 +23,7 @@ use style::stylist::{ needs_revalidation_for_testing, ContainerConditionId, LayerId, Rule, ScopeConditionId, Stylist, }; use style::thread_state::{self, ThreadState}; +use style::values::computed::font::GenericFontFamily; use style::values::computed::Length; use url::Url; @@ -38,6 +41,9 @@ impl FontMetricsProvider for DummyMetricsProvider { ) -> FontMetrics { Default::default() } + fn base_size_for_generic(&self, _: GenericFontFamily) -> Length { + Length::new(16.) + } } /// Helper method to get some Rules from selector strings. @@ -241,12 +247,14 @@ fn test_insert() { } fn mock_stylist() -> Stylist { + let initial_style = ComputedValues::initial_values_with_font_override(Font::initial_values()); let device = Device::new( MediaType::screen(), QuirksMode::NoQuirks, Size2D::new(0f32, 0f32), Scale::new(1.0), Box::new(DummyMetricsProvider), + initial_style, ); Stylist::new(device, QuirksMode::NoQuirks) } diff --git a/tests/wpt/meta/css/css-fonts/parsing/font-family-valid.html.ini b/tests/wpt/meta/css/css-fonts/parsing/font-family-valid.html.ini deleted file mode 100644 index b17ac3de579..00000000000 --- a/tests/wpt/meta/css/css-fonts/parsing/font-family-valid.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[font-family-valid.html] - [e.style['font-family'\] = "System-UI" should set the property value] - expected: FAIL diff --git a/tests/wpt/meta/css/css-fonts/system-ui-ar.html.ini b/tests/wpt/meta/css/css-fonts/system-ui-ar.html.ini deleted file mode 100644 index d334315178a..00000000000 --- a/tests/wpt/meta/css/css-fonts/system-ui-ar.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[system-ui-ar.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-fonts/system-ui-mixed.html.ini b/tests/wpt/meta/css/css-fonts/system-ui-mixed.html.ini deleted file mode 100644 index 9965271ed89..00000000000 --- a/tests/wpt/meta/css/css-fonts/system-ui-mixed.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[system-ui-mixed.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-fonts/system-ui-ur.html.ini b/tests/wpt/meta/css/css-fonts/system-ui-ur.html.ini deleted file mode 100644 index d9e58e116a2..00000000000 --- a/tests/wpt/meta/css/css-fonts/system-ui-ur.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[system-ui-ur.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-fonts/system-ui.html.ini b/tests/wpt/meta/css/css-fonts/system-ui.html.ini deleted file mode 100644 index fc1193a36c4..00000000000 --- a/tests/wpt/meta/css/css-fonts/system-ui.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[system-ui.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-input-017.html.ini b/tests/wpt/meta/css/css-transforms/transform-input-017.html.ini deleted file mode 100644 index 0f1ebae4a3e..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-input-017.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-input-017.html] - expected: FAIL diff --git a/tests/wpt/meta/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html.ini b/tests/wpt/meta/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html.ini deleted file mode 100644 index 89d10ae3c9a..00000000000 --- a/tests/wpt/meta/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[input-checkbox-switch-rtl.tentative.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 5ffc6a8ba75..fbb91fa1a9c 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -2236,7 +2236,7 @@ ] ], "font_size.html": [ - "4ffd55261f2f9e5b4dd2beaf8de8fb528c1de718", + "4f0fafc984a312881c0182325c1dc8876ea67f09", [ null, [ @@ -8724,7 +8724,7 @@ [] ], "font_face_attribute_ref.html": [ - "f018747d2ab41119af5e06d6a018101169592cab", + "14378f20cead025327c4cf296ac766b39ebea13a", [] ], "font_fallback_failed_ref.html": [ @@ -8732,7 +8732,7 @@ [] ], "font_size_ref.html": [ - "6bcf54338856d79af998eefad7bc7bb9f94d0236", + "923a3c45c8a5c333b575bedfff8500291547f265", [] ], "font_style_ref.html": [ diff --git a/tests/wpt/mozilla/tests/css/font_face_attribute_ref.html b/tests/wpt/mozilla/tests/css/font_face_attribute_ref.html index f018747d2ab..14378f20cea 100644 --- a/tests/wpt/mozilla/tests/css/font_face_attribute_ref.html +++ b/tests/wpt/mozilla/tests/css/font_face_attribute_ref.html @@ -2,8 +2,8 @@ - -

Servo

-

Servo

+ +

Servo

+

Servo

diff --git a/tests/wpt/mozilla/tests/css/font_size.html b/tests/wpt/mozilla/tests/css/font_size.html index 4ffd55261f2..4f0fafc984a 100644 --- a/tests/wpt/mozilla/tests/css/font_size.html +++ b/tests/wpt/mozilla/tests/css/font_size.html @@ -10,10 +10,14 @@

200% is 40px.

smaller is 16.66666…px.

larger is 24px. -

xx-small is 9.6px. -

x-small is 12px. -

small is 14.2222…px. + +

xx-small is 9px. +

x-small is 10px. +

small is 13px.

medium is 16px. -

large is 19.2px. +

large is 18px.

x-large is 24px.

xx-large is 32px. diff --git a/tests/wpt/mozilla/tests/css/font_size_ref.html b/tests/wpt/mozilla/tests/css/font_size_ref.html index 6bcf5433885..923a3c45c8a 100644 --- a/tests/wpt/mozilla/tests/css/font_size_ref.html +++ b/tests/wpt/mozilla/tests/css/font_size_ref.html @@ -8,10 +8,10 @@

200% is 40px.

smaller is 16.66666…px.

larger is 24px. -

xx-small is 9.6px. -

x-small is 12px. -

small is 14.2222…px. +

xx-small is 9px. +

x-small is 10px. +

small is 13px.

medium is 16px. -

large is 19.2px. +

large is 18px.

x-large is 24px.

xx-large is 32px.