style: De-dup items with the same tag in the computed value of font-feature-settings and font-variation-settings

Differential Revision: https://phabricator.services.mozilla.com/D167012
This commit is contained in:
Jonathan Kew 2023-01-19 16:17:29 +00:00 committed by Martin Robinson
parent 979637de7d
commit d54d9ec25a
3 changed files with 106 additions and 137 deletions

View file

@ -10,7 +10,9 @@ use crate::values::computed::{
Angle, Context, Integer, Length, NonNegativeLength, NonNegativeNumber, Number, Percentage,
ToComputedValue,
};
use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue};
use crate::values::generics::font::{
FeatureTagValue, FontSettings, TaggedFontValue, VariationValue,
};
use crate::values::generics::{font as generics, NonNegative};
use crate::values::specified::font::{
self as specified, KeywordInfo, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT,
@ -26,8 +28,12 @@ use style_traits::{CssWriter, ParseError, ToCss};
pub use crate::values::computed::Length as MozScriptMinSize;
pub use crate::values::specified::font::FontPalette;
pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier};
pub use crate::values::specified::font::{FontVariantAlternates, FontVariantEastAsian, FontVariantLigatures, FontVariantNumeric, XLang, XTextZoom};
pub use crate::values::specified::font::{
FontVariantAlternates, FontVariantEastAsian, FontVariantLigatures, FontVariantNumeric, XLang,
XTextZoom,
};
pub use crate::values::specified::Integer as SpecifiedInteger;
pub use crate::values::specified::Number as SpecifiedNumber;
/// Generic template for font property type classes that use a fixed-point
/// internal representation with `FRACTION_BITS` for the fractional part.
@ -761,6 +767,56 @@ pub type FontFeatureSettings = FontSettings<FeatureTagValue<Integer>>;
/// The computed value for font-variation-settings.
pub type FontVariationSettings = FontSettings<VariationValue<Number>>;
// The computed value of font-{feature,variation}-settings discards values
// with duplicate tags, keeping only the last occurrence of each tag.
fn dedup_font_settings<T>(settings_list: &mut Vec<T>)
where
T: TaggedFontValue,
{
if settings_list.len() > 1 {
settings_list.sort_by_key(|k| k.tag().0);
// dedup() keeps the first of any duplicates, but we want the last,
// so we implement it manually here.
let mut prev_tag = settings_list.last().unwrap().tag();
for i in (0..settings_list.len() - 1).rev() {
let cur_tag = settings_list[i].tag();
if cur_tag == prev_tag {
settings_list.remove(i);
}
prev_tag = cur_tag;
}
}
}
impl<T> ToComputedValue for FontSettings<T>
where
T: ToComputedValue,
<T as ToComputedValue>::ComputedValue: TaggedFontValue,
{
type ComputedValue = FontSettings<T::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
let mut v = self
.0
.iter()
.map(|item| item.to_computed_value(context))
.collect::<Vec<_>>();
dedup_font_settings(&mut v);
FontSettings(v.into_boxed_slice())
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Self(
computed
.0
.iter()
.map(T::from_computed_value)
.collect::<Vec<_>>()
.into_boxed_slice(),
)
}
}
/// font-language-override can only have a single three-letter
/// OpenType "language system" tag, so we should be able to compute
/// it and store it as a 32-bit integer
@ -1008,7 +1064,7 @@ impl ToAnimatedValue for FontStyle {
// This allows us to animate between normal and oblique values. Per spec,
// https://drafts.csswg.org/css-fonts-4/#font-style-prop:
// Animation type: by computed value type; 'normal' animates as 'oblique 0deg'
return generics::FontStyle::Oblique(Angle::from_degrees(0.0))
return generics::FontStyle::Oblique(Angle::from_degrees(0.0));
}
if self == Self::ITALIC {
return generics::FontStyle::Italic;
@ -1021,13 +1077,14 @@ impl ToAnimatedValue for FontStyle {
match animated {
generics::FontStyle::Normal => Self::NORMAL,
generics::FontStyle::Italic => Self::ITALIC,
generics::FontStyle::Oblique(ref angle) =>
generics::FontStyle::Oblique(ref angle) => {
if angle.degrees() == 0.0 {
// Reverse the conversion done in to_animated_value()
Self::NORMAL
} else {
Self::oblique(angle.degrees())
},
}
},
}
}
}