style: Fixes for font-language-override parsing and tests

Differential Revision: https://phabricator.services.mozilla.com/D168555
This commit is contained in:
Jonathan Kew 2023-02-02 11:53:59 +00:00 committed by Martin Robinson
parent 2d441672be
commit 816a0f960b
4 changed files with 34 additions and 75 deletions

View file

@ -442,6 +442,7 @@ class Longhand(Property):
"Display",
"FillRule",
"Float",
"FontLanguageOverride",
"FontSizeAdjust",
"FontStretch",
"FontStyle",

View file

@ -223,7 +223,7 @@ ${helpers.predefined_type(
"font-language-override",
"FontLanguageOverride",
engines="gecko",
initial_value="computed::FontLanguageOverride::zero()",
initial_value="computed::FontLanguageOverride::normal()",
initial_specified_value="specified::FontLanguageOverride::normal()",
animation_value_type="discrete",
extra_prefixes="moz:layout.css.prefixes.font-features",

View file

@ -855,18 +855,30 @@ where
}
}
/// font-language-override can only have a single three-letter
/// font-language-override can only have a single 1-4 ASCII character
/// OpenType "language system" tag, so we should be able to compute
/// it and store it as a 32-bit integer
/// (see http://www.microsoft.com/typography/otspec/languagetags.htm).
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToResolvedValue)]
#[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToResolvedValue,
ToShmem
)]
#[repr(C)]
#[value_info(other_values = "normal")]
pub struct FontLanguageOverride(pub u32);
impl FontLanguageOverride {
#[inline]
/// Get computed default value of `font-language-override` with 0
pub fn zero() -> FontLanguageOverride {
pub fn normal() -> FontLanguageOverride {
FontLanguageOverride(0)
}
@ -874,7 +886,7 @@ impl FontLanguageOverride {
#[inline]
pub(crate) fn to_str(self, storage: &mut [u8; 4]) -> &str {
*storage = u32::to_be_bytes(self.0);
// Safe because we ensure it's ASCII during computing
// Safe because we ensure it's ASCII during parsing
let slice = if cfg!(debug_assertions) {
std::str::from_utf8(&storage[..]).unwrap()
} else {
@ -883,23 +895,6 @@ impl FontLanguageOverride {
slice.trim_end()
}
/// Parses a str, return `Self::zero()` if the input isn't a valid OpenType
/// "language system" tag.
#[inline]
pub fn from_str(lang: &str) -> Self {
if lang.is_empty() || lang.len() > 4 {
return Self::zero();
}
let mut bytes = [b' '; 4];
for (byte, lang_byte) in bytes.iter_mut().zip(lang.as_bytes()) {
if !lang_byte.is_ascii() {
return Self::zero();
}
*byte = *lang_byte;
}
Self(u32::from_be_bytes(bytes))
}
/// Unsafe because `Self::to_str` requires the value to represent a UTF-8
/// string.
#[inline]

View file

@ -1743,55 +1743,8 @@ impl Parse for FontVariantNumeric {
/// This property provides low-level control over OpenType or TrueType font features.
pub type FontFeatureSettings = FontSettings<FeatureTagValue<Integer>>;
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
/// Allows authors to explicitly specify the language system of the font,
/// overriding the language system implied by the content language
pub enum FontLanguageOverride {
/// When rendering with OpenType fonts,
/// the content language of the element is
/// used to infer the OpenType language system
Normal,
/// Single three-letter case-sensitive OpenType language system tag,
/// specifies the OpenType language system to be used instead of
/// the language system implied by the language of the element
Override(Box<str>),
}
impl FontLanguageOverride {
#[inline]
/// Get default value with `normal`
pub fn normal() -> FontLanguageOverride {
FontLanguageOverride::Normal
}
/// The ToComputedValue implementation for non-system-font
/// FontLanguageOverride, used for @font-face descriptors.
#[inline]
pub fn compute_non_system(&self) -> computed::FontLanguageOverride {
match *self {
FontLanguageOverride::Normal => computed::FontLanguageOverride::zero(),
FontLanguageOverride::Override(ref lang) => {
computed::FontLanguageOverride::from_str(lang)
},
}
}
}
impl ToComputedValue for FontLanguageOverride {
type ComputedValue = computed::FontLanguageOverride;
#[inline]
fn to_computed_value(&self, _: &Context) -> computed::FontLanguageOverride {
self.compute_non_system()
}
#[inline]
fn from_computed_value(computed: &computed::FontLanguageOverride) -> Self {
if *computed == computed::FontLanguageOverride::zero() {
return FontLanguageOverride::Normal;
}
FontLanguageOverride::Override(computed.to_str(&mut [0; 4]).into())
}
}
/// For font-language-override, use the same representation as the computed value.
pub use crate::values::computed::font::FontLanguageOverride;
impl Parse for FontLanguageOverride {
/// normal | <string>
@ -1803,13 +1756,23 @@ impl Parse for FontLanguageOverride {
.try_parse(|input| input.expect_ident_matching("normal"))
.is_ok()
{
return Ok(FontLanguageOverride::Normal);
return Ok(FontLanguageOverride::normal());
}
let string = input.expect_string()?;
Ok(FontLanguageOverride::Override(
string.as_ref().to_owned().into_boxed_str(),
))
// The OpenType spec requires tags to be 1 to 4 ASCII characters:
// https://learn.microsoft.com/en-gb/typography/opentype/spec/otff#data-types
if string.is_empty() || string.len() > 4 || !string.is_ascii() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
let mut bytes = [b' '; 4];
for (byte, str_byte) in bytes.iter_mut().zip(string.as_bytes()) {
*byte = *str_byte;
}
Ok(FontLanguageOverride(u32::from_be_bytes(bytes)))
}
}