diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 658d3412475..6867f582d7d 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -21,7 +21,6 @@ use crate::values::specified::font::{ use crate::values::specified::length::{FontBaseSize, NoCalcLength}; use crate::values::CSSFloat; use crate::Atom; -use byteorder::{BigEndian, ByteOrder}; use cssparser::{serialize_identifier, CssStringWriter, Parser}; #[cfg(feature = "gecko")] use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; @@ -676,7 +675,7 @@ pub type FontVariationSettings = FontSettings>; /// (see http://www.microsoft.com/typography/otspec/languagetags.htm). #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToResolvedValue)] #[repr(C)] -pub struct FontLanguageOverride(pub u32); +pub struct FontLanguageOverride(u32); impl FontLanguageOverride { #[inline] @@ -684,6 +683,46 @@ impl FontLanguageOverride { pub fn zero() -> FontLanguageOverride { FontLanguageOverride(0) } + + /// Returns this value as a `&str`, backed by `storage`. + #[inline] + pub fn to_str(self, storage: &mut [u8; 4]) -> &str { + if self.0 == 0 { + return "normal"; + } + *storage = u32::to_be_bytes(self.0); + // Safe because we ensure it's ASCII during computing + let slice = if cfg!(debug_assertions) { + std::str::from_utf8(&storage[..]).unwrap() + } else { + unsafe { std::str::from_utf8_unchecked(&storage[..]) } + }; + 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] + pub unsafe fn from_u32(value: u32) -> Self { + Self(value) + } } impl ToCss for FontLanguageOverride { @@ -691,27 +730,7 @@ impl ToCss for FontLanguageOverride { where W: fmt::Write, { - use std::str; - - if self.0 == 0 { - return dest.write_str("normal"); - } - let mut buf = [0; 4]; - BigEndian::write_u32(&mut buf, self.0); - // Safe because we ensure it's ASCII during computing - let slice = if cfg!(debug_assertions) { - str::from_utf8(&buf).unwrap() - } else { - unsafe { str::from_utf8_unchecked(&buf) } - }; - slice.trim_end().to_css(dest) - } -} - -#[cfg(feature = "gecko")] -impl From for FontLanguageOverride { - fn from(bits: u32) -> FontLanguageOverride { - FontLanguageOverride(bits) + self.to_str(&mut [0; 4]).to_css(dest) } } diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index f7823e5f9ff..94c28d068f9 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -20,7 +20,6 @@ use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage}; use crate::values::specified::{NoCalcLength, NonNegativeNumber, Number, Percentage}; use crate::values::CustomIdent; use crate::Atom; -use byteorder::{BigEndian, ByteOrder}; use cssparser::{Parser, Token}; #[cfg(feature = "gecko")] use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; @@ -2057,19 +2056,9 @@ impl FontLanguageOverride { #[inline] pub fn compute_non_system(&self) -> computed::FontLanguageOverride { match *self { - FontLanguageOverride::Normal => computed::FontLanguageOverride(0), + FontLanguageOverride::Normal => computed::FontLanguageOverride::zero(), FontLanguageOverride::Override(ref lang) => { - if lang.is_empty() || lang.len() > 4 { - return computed::FontLanguageOverride(0); - } - let mut bytes = [b' '; 4]; - for (byte, lang_byte) in bytes.iter_mut().zip(lang.as_bytes()) { - if !lang_byte.is_ascii() { - return computed::FontLanguageOverride(0); - } - *byte = *lang_byte; - } - computed::FontLanguageOverride(BigEndian::read_u32(&bytes)) + computed::FontLanguageOverride::from_str(lang) }, FontLanguageOverride::System(..) => unreachable!(), } @@ -2090,19 +2079,10 @@ impl ToComputedValue for FontLanguageOverride { } #[inline] fn from_computed_value(computed: &computed::FontLanguageOverride) -> Self { - if computed.0 == 0 { + if *computed == computed::FontLanguageOverride::zero() { return FontLanguageOverride::Normal; } - let mut buf = [0; 4]; - BigEndian::write_u32(&mut buf, computed.0); - FontLanguageOverride::Override( - if cfg!(debug_assertions) { - String::from_utf8(buf.to_vec()).unwrap() - } else { - unsafe { String::from_utf8_unchecked(buf.to_vec()) } - } - .into_boxed_str(), - ) + FontLanguageOverride::Override(computed.to_str(&mut [0; 4]).into()) } }