diff --git a/components/gfx/font_store.rs b/components/gfx/font_store.rs index 8abb74fc188..c0b52b7707e 100644 --- a/components/gfx/font_store.rs +++ b/components/gfx/font_store.rs @@ -7,14 +7,16 @@ use std::sync::Arc; use app_units::Au; use atomic_refcell::AtomicRefCell; +use log::warn; use parking_lot::RwLock; use style::stylesheets::DocumentStyleSheet; +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_context::WebFontDownloadState; -use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods}; +use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods, IsOblique}; #[derive(Default)] pub struct FontStore { @@ -132,10 +134,69 @@ impl WebRenderFontStore { } } -/// A list of font templates that make up a given font family. +/// A struct that represents the available templates in a "simple family." A simple family +/// is one that contains <= 4 available faces: regular, bold, italic, and bold italic. Having +/// this simple family abstraction makes font matching much faster for families that don't +/// have a complex set of fonts. +/// +/// This optimization is taken from: +/// https://searchfox.org/mozilla-central/source/gfx/thebes/gfxFontEntry.cpp. #[derive(Clone, Debug, Default)] +struct SimpleFamily { + regular: Option, + bold: Option, + italic: Option, + bold_italic: Option, +} + +impl SimpleFamily { + /// Find a font in this family that matches a given descriptor. + fn find_for_descriptor(&self, descriptor_to_match: &FontDescriptor) -> Option { + let want_bold = descriptor_to_match.weight >= FontWeight::BOLD_THRESHOLD; + let want_italic = descriptor_to_match.style != FontStyle::NORMAL; + + // This represents the preference of which font to return from the [`SimpleFamily`], + // given what kind of font we are requesting. + let preference = match (want_bold, want_italic) { + (true, true) => [&self.bold_italic, &self.italic, &self.bold, &self.regular], + (true, false) => [&self.bold, &self.regular, &self.bold_italic, &self.italic], + (false, true) => [&self.italic, &self.bold_italic, &self.regular, &self.bold], + (false, false) => [&self.regular, &self.bold, &self.italic, &self.bold_italic], + }; + preference + .iter() + .filter_map(|template| (*template).clone()) + .next() + } + + fn remove_templates_for_stylesheet(&mut self, stylesheet: &DocumentStyleSheet) { + let remove_if_template_matches = |template: &mut Option| { + if template.as_ref().map_or(false, |template| { + template.borrow().stylesheet.as_ref() == Some(stylesheet) + }) { + *template = None; + } + }; + remove_if_template_matches(&mut self.regular); + remove_if_template_matches(&mut self.bold); + remove_if_template_matches(&mut self.italic); + remove_if_template_matches(&mut self.bold_italic); + } +} +/// A list of font templates that make up a given font family. +#[derive(Clone, Debug)] pub struct FontTemplates { pub(crate) templates: Vec, + simple_family: Option, +} + +impl Default for FontTemplates { + fn default() -> Self { + Self { + templates: Default::default(), + simple_family: Some(SimpleFamily::default()), + } + } } impl FontTemplates { @@ -148,21 +209,18 @@ impl FontTemplates { return self.templates.clone(); }; - // TODO(Issue #189): optimize lookup for - // regular/bold/italic/bolditalic with fixed offsets and a - // static decision table for fallback between these values. - let matching_templates: Vec = self - .templates - .iter() - .filter(|template| template.matches_font_descriptor(descriptor_to_match)) - .cloned() - .collect(); - if !matching_templates.is_empty() { - return matching_templates; + if self.templates.len() == 1 { + return vec![self.templates[0].clone()]; + } + + if let Some(template) = self + .simple_family + .as_ref() + .and_then(|simple_family| simple_family.find_for_descriptor(descriptor_to_match)) + { + return vec![template]; } - // We didn't find an exact match. Do more expensive fuzzy matching. - // TODO(#190): Do a better job. let mut best_templates = Vec::new(); let mut best_distance = f32::MAX; for template in self.templates.iter() { @@ -198,8 +256,62 @@ impl FontTemplates { return; } } - self.templates - .push(Arc::new(AtomicRefCell::new(new_template))); + + let new_template = Arc::new(AtomicRefCell::new(new_template)); + self.templates.push(new_template.clone()); + self.update_simple_family(new_template); + } + + fn update_simple_family(&mut self, added_template: FontTemplateRef) { + // If this was detected to not be a simple family before, it cannot ever be one + // in the future. + let Some(simple_family) = self.simple_family.as_mut() else { + return; + }; + + if self.templates.len() > 4 { + self.simple_family = None; + return; + } + + // Variation fonts are never simple families. + if added_template.descriptor().is_variation_font() { + self.simple_family = None; + return; + } + + let Some(first) = self.templates.first() else { + warn!("Called before adding any templates."); + return; + }; + + // If the stretch between any of these fonts differ, it cannot be a simple family nor if this + // font is oblique. + let stretch = added_template.descriptor().stretch.0; + let style = added_template.descriptor().style.0; + if first.descriptor().stretch.0 != stretch || style.is_oblique() { + self.simple_family = None; + return; + } + + let weight = added_template.descriptor().weight.0; + let supports_bold = weight >= FontWeight::BOLD_THRESHOLD; + let is_italic = style == FontStyle::ITALIC; + let slot = match (supports_bold, is_italic) { + (true, true) => &mut simple_family.bold_italic, + (true, false) => &mut simple_family.bold, + (false, true) => &mut simple_family.italic, + (false, false) => &mut simple_family.regular, + }; + + // If the slot was already filled there are two fonts with the same simple properties + // and this isn't a simple family. + if slot.is_some() { + self.simple_family = None; + return; + } + + slot.replace(added_template); } pub(crate) fn remove_templates_for_stylesheet( @@ -209,6 +321,11 @@ impl FontTemplates { let length_before = self.templates.len(); self.templates .retain(|template| template.borrow().stylesheet.as_ref() != Some(stylesheet)); + + if let Some(simple_family) = self.simple_family.as_mut() { + simple_family.remove_templates_for_stylesheet(stylesheet); + } + length_before != self.templates.len() } } diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs index bfa8bb49fb4..dbe5458b7b4 100644 --- a/components/gfx/font_template.rs +++ b/components/gfx/font_template.rs @@ -48,14 +48,6 @@ impl Default for FontTemplateDescriptor { /// we know they will never be NaN, so we can manually implement Eq. impl Eq for FontTemplateDescriptor {} -fn style_to_number(s: &FontStyle) -> f32 { - match *s { - FontStyle::NORMAL => 0., - FontStyle::ITALIC => FontStyle::DEFAULT_OBLIQUE_DEGREES as f32, - _ => s.oblique_degrees(), - } -} - impl FontTemplateDescriptor { #[inline] pub fn new(weight: FontWeight, stretch: FontStretch, style: FontStyle) -> Self { @@ -67,27 +59,45 @@ impl FontTemplateDescriptor { } } + pub fn is_variation_font(&self) -> bool { + self.weight.0 != self.weight.1 || + self.stretch.0 != self.stretch.1 || + self.style.0 != self.style.1 + } + /// Returns a score indicating how far apart visually the two font descriptors are. This is - /// used for fuzzy font selection. + /// used for implmenting the CSS Font Matching algorithm: + /// . /// /// The smaller the score, the better the fonts match. 0 indicates an exact match. This must /// be commutative (distance(A, B) == distance(B, A)). - /// - /// The policy is to care most about differences in italicness, then weight, then stretch #[inline] - fn distance_from(&self, other: &FontDescriptor) -> f32 { - let weight = self.weight.0; - let style = self.style.0; - let stretch = self.stretch.0; + fn distance_from(&self, target: &FontDescriptor) -> f32 { + let stretch_distance = target.stretch.match_distance(&self.stretch); + let style_distance = target.style.match_distance(&self.style); + let weight_distance = target.weight.match_distance(&self.weight); - // 0 <= style_part <= 180, since font-style obliqueness should be - // between -90 and +90deg. - let style_part = (style_to_number(&style) - style_to_number(&other.style)).abs(); - // 0 <= weightPart <= 800 - let weight_part = (weight.value() - other.weight.value()).abs(); - // 0 <= stretchPart <= 8 - let stretch_part = (stretch.to_percentage().0 - other.stretch.to_percentage().0).abs(); - style_part + weight_part + stretch_part + // Sanity-check that the distances are within the expected range + // (update if implementation of the distance functions is changed). + assert!(stretch_distance >= 0.0 && stretch_distance <= 2000.0); + assert!(style_distance >= 0.0 && style_distance <= 500.0); + assert!(weight_distance >= 0.0 && weight_distance <= 1600.0); + + // Factors used to weight the distances between the available and target font + // properties during font-matching. These ensure that we respect the CSS-fonts + // requirement that font-stretch >> font-style >> font-weight; and in addition, + // a mismatch between the desired and actual glyph presentation (emoji vs text) + // will take precedence over any of the style attributes. + // + // TODO: Take into account Unicode presentation preferences here, in order to properly + // choose a font for emoji clusters that start with non-emoji characters. + const STRETCH_FACTOR: f32 = 1.0e8; + const STYLE_FACTOR: f32 = 1.0e4; + const WEIGHT_FACTOR: f32 = 1.0e0; + + return stretch_distance * STRETCH_FACTOR + + style_distance * STYLE_FACTOR + + weight_distance * WEIGHT_FACTOR; } fn matches(&self, descriptor_to_match: &FontDescriptor) -> bool { @@ -286,3 +296,278 @@ impl FontTemplateRefMethods for FontTemplateRef { }) } } + +/// A trait for implementing the CSS font matching algorithm against various font features. +/// See . +/// +/// This implementation is ported from Gecko at: +/// . +trait FontMatchDistanceMethod: Sized { + fn match_distance(&self, range: &(Self, Self)) -> f32; + fn to_float(&self) -> f32; +} + +impl FontMatchDistanceMethod for FontStretch { + fn match_distance(&self, range: &(Self, Self)) -> f32 { + // stretch distance ==> [0,2000] + const REVERSE_DISTANCE: f32 = 1000.0; + + let min_stretch = range.0; + let max_stretch = range.1; + + // The stretch value is a (non-negative) percentage; currently we support + // values in the range 0 .. 1000. (If the upper limit is ever increased, + // the kReverseDistance value used here may need to be adjusted.) + // If aTargetStretch is >100, we prefer larger values if available; + // if <=100, we prefer smaller values if available. + if *self < min_stretch { + if *self > FontStretch::NORMAL { + return min_stretch.to_float() - self.to_float(); + } + return (min_stretch.to_float() - self.to_float()) + REVERSE_DISTANCE; + } + + if *self > max_stretch { + if *self <= FontStretch::NORMAL { + return self.to_float() - max_stretch.to_float(); + } + return (self.to_float() - max_stretch.to_float()) + REVERSE_DISTANCE; + } + 0.0 + } + + fn to_float(&self) -> f32 { + self.0.to_float() + } +} + +impl FontMatchDistanceMethod for FontWeight { + // Calculate weight distance with values in the range (0..1000). In general, + // heavier weights match towards even heavier weights while lighter weights + // match towards even lighter weights. Target weight values in the range + // [400..500] are special, since they will first match up to 500, then down + // towards 0, then up again towards 999. + // + // Example: with target 600 and font weight 800, distance will be 200. With + // target 300 and font weight 600, distance will be 900, since heavier + // weights are farther away than lighter weights. If the target is 5 and the + // font weight 995, the distance would be 1590 for the same reason. + + fn match_distance(&self, range: &(Self, Self)) -> f32 { + // weight distance ==> [0,1600] + const NOT_WITHIN_CENTRAL_RANGE: f32 = 100.0; + const REVERSE_DISTANCE: f32 = 600.0; + + let min_weight = range.0; + let max_weight = range.1; + + if *self >= min_weight && *self <= max_weight { + // Target is within the face's range, so it's a perfect match + return 0.0; + } + + if *self < FontWeight::NORMAL { + // Requested a lighter-than-400 weight + if max_weight < *self { + return self.to_float() - max_weight.to_float(); + } + + // Add reverse-search penalty for bolder faces + return (min_weight.to_float() - self.to_float()) + REVERSE_DISTANCE; + } + + if *self > FontWeight::from_float(500.) { + // Requested a bolder-than-500 weight + if min_weight > *self { + return min_weight.to_float() - self.to_float(); + } + // Add reverse-search penalty for lighter faces + return (self.to_float() - max_weight.to_float()) + REVERSE_DISTANCE; + } + + // Special case for requested weight in the [400..500] range + if min_weight > *self { + if min_weight <= FontWeight::from_float(500.) { + // Bolder weight up to 500 is first choice + return min_weight.to_float() - self.to_float(); + } + // Other bolder weights get a reverse-search penalty + return (min_weight.to_float() - self.to_float()) + REVERSE_DISTANCE; + } + // Lighter weights are not as good as bolder ones within [400..500] + return (self.to_float() - max_weight.to_float()) + NOT_WITHIN_CENTRAL_RANGE; + } + + fn to_float(&self) -> f32 { + self.value() + } +} + +impl FontMatchDistanceMethod for FontStyle { + fn match_distance(&self, range: &(Self, Self)) -> f32 { + // style distance ==> [0,500] + let min_style = range.0; + if *self == min_style { + return 0.0; // styles match exactly ==> 0 + } + + // bias added to angle difference when searching in the non-preferred + // direction from a target angle + const REVERSE: f32 = 100.0; + + // bias added when we've crossed from positive to negative angles or + // vice versa + const NEGATE: f32 = 200.0; + + if *self == FontStyle::NORMAL { + if min_style.is_oblique() { + // to distinguish oblique 0deg from normal, we add 1.0 to the angle + let min_angle = min_style.oblique_degrees(); + if min_angle >= 0.0 { + return 1.0 + min_angle; + } + let max_style = range.1; + let max_angle = max_style.oblique_degrees(); + if max_angle >= 0.0 { + // [min,max] range includes 0.0, so just return our minimum + return 1.0; + } + // negative oblique is even worse than italic + return NEGATE - max_angle; + } + // must be italic, which is worse than any non-negative oblique; + // treat as a match in the wrong search direction + assert!(min_style == FontStyle::ITALIC); + return REVERSE; + } + + let default_oblique_angle = FontStyle::OBLIQUE.oblique_degrees(); + if *self == FontStyle::ITALIC { + if min_style.is_oblique() { + let min_angle = min_style.oblique_degrees(); + if min_angle >= default_oblique_angle { + return 1.0 + (min_angle - default_oblique_angle); + } + let max_style = range.1; + let max_angle = max_style.oblique_degrees(); + if max_angle >= default_oblique_angle { + return 1.0; + } + if max_angle > 0.0 { + // wrong direction but still > 0, add bias of 100 + return REVERSE + (default_oblique_angle - max_angle); + } + // negative oblique angle, add bias of 300 + return REVERSE + NEGATE + (default_oblique_angle - max_angle); + } + // normal is worse than oblique > 0, but better than oblique <= 0 + assert!(min_style == FontStyle::NORMAL); + return NEGATE; + } + + // target is oblique : four different cases depending on + // the value of the , which determines the preferred direction + // of search + let target_angle = self.oblique_degrees(); + if target_angle >= default_oblique_angle { + if min_style.is_oblique() { + let min_angle = min_style.oblique_degrees(); + if min_angle >= target_angle { + return min_angle - target_angle; + } + let max_style = range.1; + let max_angle = max_style.oblique_degrees(); + if max_angle >= target_angle { + return 0.0; + } + if max_angle > 0.0 { + return REVERSE + (target_angle - max_angle); + } + return REVERSE + NEGATE + (target_angle - max_angle); + } + if min_style == FontStyle::ITALIC { + return REVERSE + NEGATE; + } + return REVERSE + NEGATE + 1.0; + } + + if target_angle <= -default_oblique_angle { + if min_style.is_oblique() { + let max_style = range.1; + let max_angle = max_style.oblique_degrees(); + if max_angle <= target_angle { + return target_angle - max_angle; + } + let min_angle = min_style.oblique_degrees(); + if min_angle <= target_angle { + return 0.0; + } + if min_angle < 0.0 { + return REVERSE + (min_angle - target_angle); + } + return REVERSE + NEGATE + (min_angle - target_angle); + } + if min_style == FontStyle::ITALIC { + return REVERSE + NEGATE; + } + return REVERSE + NEGATE + 1.0; + } + + if target_angle >= 0.0 { + if min_style.is_oblique() { + let min_angle = min_style.oblique_degrees(); + if min_angle > target_angle { + return REVERSE + (min_angle - target_angle); + } + let max_style = range.1; + let max_angle = max_style.oblique_degrees(); + if max_angle >= target_angle { + return 0.0; + } + if max_angle > 0.0 { + return target_angle - max_angle; + } + return REVERSE + NEGATE + (target_angle - max_angle); + } + if min_style == FontStyle::ITALIC { + return REVERSE + NEGATE - 2.0; + } + return REVERSE + NEGATE - 1.0; + } + + // last case: (targetAngle < 0.0 && targetAngle > kDefaultAngle) + if min_style.is_oblique() { + let max_style = range.1; + let max_angle = max_style.oblique_degrees(); + if max_angle < target_angle { + return REVERSE + (target_angle - max_angle); + } + let min_angle = min_style.oblique_degrees(); + if min_angle <= target_angle { + return 0.0; + } + if min_angle < 0.0 { + return min_angle - target_angle; + } + return REVERSE + NEGATE + (min_angle - target_angle); + } + if min_style == FontStyle::ITALIC { + return REVERSE + NEGATE - 2.0; + } + return REVERSE + NEGATE - 1.0; + } + + fn to_float(&self) -> f32 { + unimplemented!("Don't know how to convert FontStyle to float."); + } +} + +pub(crate) trait IsOblique { + fn is_oblique(&self) -> bool; +} + +impl IsOblique for FontStyle { + fn is_oblique(&self) -> bool { + *self != FontStyle::NORMAL && *self != FontStyle::ITALIC + } +} diff --git a/tests/wpt/meta-legacy-layout/css/css-fonts/variations/at-font-face-font-matching.html.ini b/tests/wpt/meta-legacy-layout/css/css-fonts/variations/at-font-face-font-matching.html.ini deleted file mode 100644 index 730bec15805..00000000000 --- a/tests/wpt/meta-legacy-layout/css/css-fonts/variations/at-font-face-font-matching.html.ini +++ /dev/null @@ -1,337 +0,0 @@ -[at-font-face-font-matching.html] - bug: https://github.com/servo/servo/issues/29376 - [Descriptor mathcing priority: Stretch has higher priority than style] - expected: [PASS, FAIL] - - [Descriptor mathcing priority: Stretch has higher priority than weight] - expected: [PASS, FAIL] - - [Matching font-weight: '400' should prefer '500' over '350 399'] - expected: [PASS, FAIL] - - [Matching font-weight: '400' should prefer '350 399' over '351 398'] - expected: [PASS, FAIL] - - [Matching font-weight: '400' should prefer '501 550' over '502 560'] - expected: [PASS, FAIL] - - [Matching font-weight: '500' should prefer '501 550' over '502 560'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 0deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -10deg' over 'oblique -5deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -20deg -15deg' over 'oblique -60deg -30deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'oblique 0deg 10deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Descriptor mathcing priority: Style has higher priority than weight] - expected: [PASS, FAIL] - - [Matching font-stretch: '110%' should prefer '115% 116%' over '105%'] - expected: [PASS, FAIL] - - [Matching font-stretch: '90%' should prefer '50% 80%' over '60% 70%'] - expected: [PASS, FAIL] - - [Descriptor matching priority: Stretch has higher priority than weight] - expected: [PASS, FAIL] - - [Descriptor matching priority: Stretch has higher priority than style] - expected: [PASS, FAIL] - - [Descriptor matching priority: Style has higher priority than weight] - expected: [PASS, FAIL] - - [Matching font-weight: '430' should prefer '420 440' over '450 460'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 15deg 20deg' over 'oblique 30deg 60deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 20deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'italic' over 'oblique 0deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'oblique 20deg' over 'oblique 30deg 60deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'normal' should prefer 'oblique 10deg 40deg' over 'oblique 20deg 30deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '399' should prefer '450 460' over '500 501'] - expected: [PASS, FAIL] - - [Matching font-weight: '500' should prefer '400' over '350 399'] - expected: [PASS, FAIL] - - [Matching font-weight: '501' should prefer '501' over '502 510'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '400' should prefer '450 460' over '500'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 0deg' should prefer 'italic' over 'oblique -50deg -20deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -20deg' should prefer 'oblique -10deg' over 'italic'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -20deg' should prefer 'oblique -20deg' over 'oblique -60deg -40deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 10deg' over 'italic'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 21deg' over 'oblique 30deg 60deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'italic' over 'oblique 0deg 10deg'] - expected: [PASS, FAIL] - - [Matching font-stretch: '100%' should prefer '110% 120%' over '115% 116%'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '501' should prefer '503 520' over '500'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 20deg' over 'oblique 30deg 60deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 5deg' over 'oblique 15deg 20deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '399' should prefer '400' over '450 460'] - expected: [PASS, FAIL] - - [Matching font-weight: '399' should prefer '500 501' over '502 510'] - expected: [PASS, FAIL] - - [Matching font-stretch: '90%' should prefer '110% 140%' over '120% 130%'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: [PASS, FAIL] - - [Matching font-stretch: '110%' should prefer '50% 80%' over '60% 70%'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'oblique -60deg -30deg' over 'oblique -50deg -40deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '430' should prefer '500' over '400 425'] - expected: [PASS, FAIL] - - [Matching font-weight: '400' should prefer '351 398' over '501 550'] - expected: [PASS, FAIL] - - [Matching font-weight: '430' should prefer '400 425' over '350 399'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 20deg' over 'oblique 10deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 20deg' should prefer 'italic' over 'oblique 0deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'italic' over 'oblique 0deg'] - expected: [PASS, FAIL] - - [Matching font-stretch: '110%' should prefer '105%' over '100%'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 40deg 50deg' over 'oblique 10deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '430' should prefer '450 460' over '500'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 0deg' over 'oblique 5deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -5deg' over 'oblique -1deg 0deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -50deg -40deg' over 'italic'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -20deg' should prefer 'oblique -60deg -40deg' over 'oblique -10deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -20deg' should prefer 'italic' over 'oblique 0deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -21deg' should prefer 'oblique -21deg' over 'oblique -60deg -40deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '399' should prefer '340 360' over '200 300'] - expected: [PASS, FAIL] - - [Matching font-stretch: '110%' should prefer '100%' over '50% 80%'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -1deg 0deg' over 'oblique -20deg -15deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 40deg 50deg' over 'oblique 20deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -21deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -20deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 15deg 20deg' over 'oblique 30deg 60deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 40deg 50deg' over 'italic'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -21deg' should prefer 'oblique -60deg -40deg' over 'oblique -10deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -21deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '430' should prefer '350 399' over '340 398'] - expected: [PASS, FAIL] - - [Matching font-weight: '501' should prefer '502 510' over '503 520'] - expected: [PASS, FAIL] - - [Matching font-weight: '501' should prefer '500' over '450 460'] - expected: [PASS, FAIL] - - [Matching font-weight: '501' should prefer '390 410' over '300 350'] - expected: [PASS, FAIL] - - [Matching font-weight: '399' should prefer '350 399' over '340 360'] - expected: [PASS, FAIL] - - [Matching font-stretch: '90%' should prefer '90% 100%' over '50% 80%'] - expected: [PASS, FAIL] - - [Matching font-stretch: '90%' should prefer '60% 70%' over '110% 140%'] - expected: [PASS, FAIL] - - [Matching font-style: 'normal' should prefer 'normal' over 'oblique 0deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'oblique 5deg' over 'normal'] - expected: [PASS, FAIL] - - [Matching font-weight: '400' should prefer '400' over '450 460'] - expected: [PASS, FAIL] - - [Matching font-weight: '399' should prefer '200 300' over '400'] - expected: [PASS, FAIL] - - [Matching font-stretch: '110%' should prefer '110% 120%' over '115% 116%'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 10deg' over 'italic'] - expected: [PASS, FAIL] - - [Matching font-weight: '501' should prefer '450 460' over '390 410'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'oblique 40deg 50deg' over 'oblique 5deg 10deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 5deg' over 'oblique 15deg 20deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -21deg' should prefer 'oblique -10deg' over 'italic'] - expected: [PASS, FAIL] - - [Matching font-stretch: '100%' should prefer '100%' over '110% 120%'] - expected: [PASS, FAIL] - - [Matching font-style: 'normal' should prefer 'oblique 20deg 30deg' over 'oblique -50deg -20deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'oblique 5deg 10deg' over 'oblique 5deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 10deg' over 'oblique 5deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -21deg' should prefer 'italic' over 'oblique 0deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '500' should prefer '450 460' over '400'] - expected: [PASS, FAIL] - - [Matching font-weight: '430' should prefer '340 398' over '501 550'] - expected: [PASS, FAIL] - - [Matching font-weight: '500' should prefer '351 398' over '501 550'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'italic' over 'oblique 20deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '500' should prefer '500' over '450 460'] - expected: [PASS, FAIL] - - [Matching font-style: 'normal' should prefer 'oblique 0deg' over 'oblique 10deg 40deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'normal' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'oblique 0deg' over 'oblique -60deg -30deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -60deg -30deg' over 'oblique -50deg -40deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique -20deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: [PASS, FAIL] - - [Matching font-weight: '430' should prefer '501 550' over '502 560'] - expected: [PASS, FAIL] - - [Matching font-weight: '500' should prefer '350 399' over '351 398'] - expected: [PASS, FAIL] - - [Matching font-style: 'italic' should prefer 'normal' over 'oblique 0deg'] - expected: [PASS, FAIL] - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 40deg 50deg' over 'italic'] - expected: [PASS, FAIL] diff --git a/tests/wpt/meta-legacy-layout/css/css-fonts/variations/font-weight-matching.html.ini b/tests/wpt/meta-legacy-layout/css/css-fonts/variations/font-weight-matching.html.ini deleted file mode 100644 index 8472284bd27..00000000000 --- a/tests/wpt/meta-legacy-layout/css/css-fonts/variations/font-weight-matching.html.ini +++ /dev/null @@ -1,18 +0,0 @@ -[font-weight-matching.html] - [Test @font-face matching for weight 600] - expected: FAIL - - [Test @font-face matching for weight 751] - expected: FAIL - - [Test @font-face matching for weight 399] - expected: FAIL - - [Test @font-face matching for weight 470] - expected: FAIL - - [Test @font-face matching for weight 249] - expected: FAIL - - [Test @font-face matching for weight 420] - expected: FAIL diff --git a/tests/wpt/meta/css/css-fonts/variations/at-font-face-font-matching.html.ini b/tests/wpt/meta/css/css-fonts/variations/at-font-face-font-matching.html.ini deleted file mode 100644 index 51d11a969f2..00000000000 --- a/tests/wpt/meta/css/css-fonts/variations/at-font-face-font-matching.html.ini +++ /dev/null @@ -1,258 +0,0 @@ -[at-font-face-font-matching.html] - [Descriptor matching priority: Stretch has higher priority than style] - expected: FAIL - - [Descriptor matching priority: Stretch has higher priority than weight] - expected: FAIL - - [Descriptor matching priority: Style has higher priority than weight] - expected: FAIL - - [Matching font-weight: '400' should prefer '350 399' over '351 398'] - expected: FAIL - - [Matching font-weight: '500' should prefer '351 398' over '501 550'] - expected: FAIL - - [Matching font-style: 'normal' should prefer 'oblique 0deg' over 'oblique 10deg 40deg'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: FAIL - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 15deg 20deg' over 'oblique 30deg 60deg'] - expected: FAIL - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -1deg 0deg' over 'oblique -20deg -15deg'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 21deg' over 'oblique 30deg 60deg'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: FAIL - - [Matching font-stretch: '110%' should prefer '50% 80%' over '60% 70%'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'oblique -60deg -30deg' over 'oblique -50deg -40deg'] - expected: FAIL - - [Matching font-weight: '430' should prefer '500' over '400 425'] - expected: FAIL - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'] - expected: FAIL - - [Matching font-stretch: '110%' should prefer '100%' over '50% 80%'] - expected: FAIL - - [Matching font-stretch: '90%' should prefer '50% 80%' over '60% 70%'] - expected: FAIL - - [Matching font-weight: '500' should prefer '350 399' over '351 398'] - expected: FAIL - - [Matching font-stretch: '90%' should prefer '90% 100%' over '50% 80%'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 40deg 50deg' over 'italic'] - expected: FAIL - - [Matching font-style: 'normal' should prefer 'normal' over 'oblique 0deg'] - expected: FAIL - - [Matching font-style: 'normal' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: FAIL - - [Matching font-style: 'oblique 20deg' should prefer 'italic' over 'oblique 0deg'] - expected: FAIL - - [Matching font-style: 'oblique -21deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg'] - expected: FAIL - - [Matching font-style: 'oblique -21deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-stretch: '90%' should prefer '110% 140%' over '120% 130%'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'oblique 0deg' over 'oblique -60deg -30deg'] - expected: FAIL - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 40deg 50deg' over 'italic'] - expected: FAIL - - [Matching font-style: 'oblique -20deg' should prefer 'oblique -60deg -40deg' over 'oblique -10deg'] - expected: FAIL - - [Matching font-stretch: '110%' should prefer '110% 120%' over '115% 116%'] - expected: FAIL - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 10deg' over 'italic'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'italic' over 'oblique 0deg'] - expected: FAIL - - [Matching font-weight: '400' should prefer '500' over '350 399'] - expected: FAIL - - [Matching font-weight: '399' should prefer '200 300' over '400'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'oblique 5deg 10deg' over 'oblique 5deg'] - expected: FAIL - - [Matching font-style: 'oblique 0deg' should prefer 'italic' over 'oblique -50deg -20deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -10deg' over 'oblique -5deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -20deg -15deg' over 'oblique -60deg -30deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'italic' over 'oblique 0deg 10deg'] - expected: FAIL - - [Matching font-style: 'oblique -20deg' should prefer 'italic' over 'oblique 0deg'] - expected: FAIL - - [Matching font-style: 'oblique -20deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-style: 'oblique -21deg' should prefer 'oblique -60deg -40deg' over 'oblique -10deg'] - expected: FAIL - - [Matching font-style: 'oblique -21deg' should prefer 'italic' over 'oblique 0deg'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 10deg' over 'italic'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 15deg 20deg' over 'oblique 30deg 60deg'] - expected: FAIL - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 0deg' over 'oblique 5deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -60deg -30deg' over 'oblique -50deg -40deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'oblique 0deg 10deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-weight: '501' should prefer '503 520' over '500'] - expected: FAIL - - [Matching font-stretch: '110%' should prefer '115% 116%' over '105%'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'oblique 20deg' over 'oblique 30deg 60deg'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'] - expected: FAIL - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 20deg' over 'oblique 30deg 60deg'] - expected: FAIL - - [Matching font-style: 'oblique 20deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 20deg' over 'oblique 10deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -5deg' over 'oblique -1deg 0deg'] - expected: FAIL - - [Matching font-style: 'oblique -20deg' should prefer 'oblique -10deg' over 'italic'] - expected: FAIL - - [Matching font-stretch: '90%' should prefer '60% 70%' over '110% 140%'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'normal' over 'oblique 0deg'] - expected: FAIL - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 40deg 50deg' over 'oblique 10deg'] - expected: FAIL - - [Matching font-style: 'oblique 21deg' should prefer 'oblique 40deg 50deg' over 'oblique 20deg'] - expected: FAIL - - [Matching font-style: 'oblique 0deg' should prefer 'oblique 5deg' over 'oblique 15deg 20deg'] - expected: FAIL - - [Matching font-stretch: '110%' should prefer '105%' over '100%'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-style: 'oblique -20deg' should prefer 'oblique -20deg' over 'oblique -60deg -40deg'] - expected: FAIL - - [Matching font-stretch: '100%' should prefer '110% 120%' over '115% 116%'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'italic' over 'oblique 20deg'] - expected: FAIL - - [Matching font-style: 'oblique -21deg' should prefer 'oblique -10deg' over 'italic'] - expected: FAIL - - [Matching font-weight: '430' should prefer '340 398' over '501 550'] - expected: FAIL - - [Matching font-style: 'oblique 20deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 5deg' over 'oblique 15deg 20deg'] - expected: FAIL - - [Matching font-style: 'oblique -20deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg'] - expected: FAIL - - [Matching font-stretch: '100%' should prefer '100%' over '110% 120%'] - expected: FAIL - - [Matching font-style: 'normal' should prefer 'oblique 10deg 40deg' over 'oblique 20deg 30deg'] - expected: FAIL - - [Matching font-style: 'normal' should prefer 'oblique 20deg 30deg' over 'oblique -50deg -20deg'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'oblique 40deg 50deg' over 'oblique 5deg 10deg'] - expected: FAIL - - [Matching font-style: 'italic' should prefer 'oblique 5deg' over 'normal'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'italic' over 'oblique 0deg'] - expected: FAIL - - [Matching font-style: 'oblique 0deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] - expected: FAIL - - [Matching font-style: 'oblique -10deg' should prefer 'oblique -50deg -40deg' over 'italic'] - expected: FAIL - - [Matching font-style: 'oblique 10deg' should prefer 'oblique 10deg' over 'oblique 5deg'] - expected: FAIL - - [Matching font-style: 'oblique -21deg' should prefer 'oblique -21deg' over 'oblique -60deg -40deg'] - expected: FAIL diff --git a/tests/wpt/meta/css/css-fonts/variations/font-weight-matching.html.ini b/tests/wpt/meta/css/css-fonts/variations/font-weight-matching.html.ini deleted file mode 100644 index 18b51d5e7a9..00000000000 --- a/tests/wpt/meta/css/css-fonts/variations/font-weight-matching.html.ini +++ /dev/null @@ -1,18 +0,0 @@ -[font-weight-matching.html] - [Test @font-face matching for weight 600] - expected: FAIL - - [Test @font-face matching for weight 470] - expected: FAIL - - [Test @font-face matching for weight 751] - expected: FAIL - - [Test @font-face matching for weight 399] - expected: FAIL - - [Test @font-face matching for weight 420] - expected: FAIL - - [Test @font-face matching for weight 249] - expected: FAIL