mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
style: Move fixed-point font types to Rust
Now that cbindgen and rust support const generics, it seems more simple. This centralizes all the relevant font constants etc in rust and avoids conversions when going from rust to C++ and vice versa. Differential Revision: https://phabricator.services.mozilla.com/D148847
This commit is contained in:
parent
48749641d3
commit
dcafbde256
10 changed files with 401 additions and 326 deletions
|
@ -143,7 +143,10 @@ pub fn fmap_trait_output(input: &DeriveInput, trait_path: &Path, trait_output: &
|
||||||
let ident = &data.ident;
|
let ident = &data.ident;
|
||||||
GenericArgument::Type(parse_quote!(<#ident as #trait_path>::#trait_output))
|
GenericArgument::Type(parse_quote!(<#ident as #trait_path>::#trait_output))
|
||||||
},
|
},
|
||||||
ref arg => panic!("arguments {:?} cannot be mapped yet", arg),
|
&GenericParam::Const(ref inner) => {
|
||||||
|
let ident = &inner.ident;
|
||||||
|
GenericArgument::Const(parse_quote!(#ident))
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
colon2_token: Default::default(),
|
colon2_token: Default::default(),
|
||||||
|
|
|
@ -12,14 +12,14 @@ use crate::parser::{Parse, ParserContext};
|
||||||
use crate::properties::longhands::font_language_override;
|
use crate::properties::longhands::font_language_override;
|
||||||
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use crate::str::CssStringWriter;
|
use crate::str::CssStringWriter;
|
||||||
use crate::values::computed::font::FamilyName;
|
use crate::values::computed::font::{FamilyName, FontStretch};
|
||||||
use crate::values::generics::font::FontStyle as GenericFontStyle;
|
use crate::values::generics::font::FontStyle as GenericFontStyle;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::specified::font::SpecifiedFontFeatureSettings;
|
use crate::values::specified::font::SpecifiedFontFeatureSettings;
|
||||||
use crate::values::specified::font::SpecifiedFontStyle;
|
use crate::values::specified::font::SpecifiedFontStyle;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::specified::font::SpecifiedFontVariationSettings;
|
use crate::values::specified::font::SpecifiedFontVariationSettings;
|
||||||
use crate::values::specified::font::{AbsoluteFontWeight, FontStretch};
|
use crate::values::specified::font::{AbsoluteFontWeight, FontStretch as SpecifiedFontStretch};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::specified::font::MetricsOverride;
|
use crate::values::specified::font::MetricsOverride;
|
||||||
use crate::values::specified::url::SpecifiedUrl;
|
use crate::values::specified::url::SpecifiedUrl;
|
||||||
|
@ -174,7 +174,7 @@ fn sort_range<T: PartialOrd>(a: T, b: T) -> (T, T) {
|
||||||
impl FontWeightRange {
|
impl FontWeightRange {
|
||||||
/// Returns a computed font-stretch range.
|
/// Returns a computed font-stretch range.
|
||||||
pub fn compute(&self) -> ComputedFontWeightRange {
|
pub fn compute(&self) -> ComputedFontWeightRange {
|
||||||
let (min, max) = sort_range(self.0.compute().0, self.1.compute().0);
|
let (min, max) = sort_range(self.0.compute().value(), self.1.compute().value());
|
||||||
ComputedFontWeightRange(min, max)
|
ComputedFontWeightRange(min, max)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,23 +183,23 @@ impl FontWeightRange {
|
||||||
///
|
///
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-stretch
|
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-stretch
|
||||||
#[derive(Clone, Debug, PartialEq, ToShmem)]
|
#[derive(Clone, Debug, PartialEq, ToShmem)]
|
||||||
pub struct FontStretchRange(pub FontStretch, pub FontStretch);
|
pub struct FontStretchRange(pub SpecifiedFontStretch, pub SpecifiedFontStretch);
|
||||||
impl_range!(FontStretchRange, FontStretch);
|
impl_range!(FontStretchRange, SpecifiedFontStretch);
|
||||||
|
|
||||||
/// The computed representation of the above, so that
|
/// The computed representation of the above, so that Gecko can read them
|
||||||
/// Gecko can read them easily.
|
/// easily.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub struct ComputedFontStretchRange(f32, f32);
|
pub struct ComputedFontStretchRange(FontStretch, FontStretch);
|
||||||
|
|
||||||
impl FontStretchRange {
|
impl FontStretchRange {
|
||||||
/// Returns a computed font-stretch range.
|
/// Returns a computed font-stretch range.
|
||||||
pub fn compute(&self) -> ComputedFontStretchRange {
|
pub fn compute(&self) -> ComputedFontStretchRange {
|
||||||
fn compute_stretch(s: &FontStretch) -> f32 {
|
fn compute_stretch(s: &SpecifiedFontStretch) -> FontStretch {
|
||||||
match *s {
|
match *s {
|
||||||
FontStretch::Keyword(ref kw) => kw.compute().0,
|
SpecifiedFontStretch::Keyword(ref kw) => kw.compute(),
|
||||||
FontStretch::Stretch(ref p) => p.0.get(),
|
SpecifiedFontStretch::Stretch(ref p) => FontStretch::from_percentage(p.0.get()),
|
||||||
FontStretch::System(..) => unreachable!(),
|
SpecifiedFontStretch::System(..) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -895,57 +895,9 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_font_weight(&mut self, v: longhands::font_weight::computed_value::T) {
|
${impl_simple('font_weight', 'mFont.weight')}
|
||||||
unsafe { bindings::Gecko_FontWeight_SetFloat(&mut self.gecko.mFont.weight, v.0) };
|
${impl_simple('font_stretch', 'mFont.stretch')}
|
||||||
}
|
${impl_simple('font_style', 'mFont.style')}
|
||||||
${impl_simple_copy('font_weight', 'mFont.weight')}
|
|
||||||
|
|
||||||
pub fn clone_font_weight(&self) -> longhands::font_weight::computed_value::T {
|
|
||||||
let weight: f32 = unsafe {
|
|
||||||
bindings::Gecko_FontWeight_ToFloat(self.gecko.mFont.weight)
|
|
||||||
};
|
|
||||||
longhands::font_weight::computed_value::T(weight)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_font_stretch(&mut self, v: longhands::font_stretch::computed_value::T) {
|
|
||||||
unsafe {
|
|
||||||
bindings::Gecko_FontStretch_SetFloat(
|
|
||||||
&mut self.gecko.mFont.stretch,
|
|
||||||
v.value(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
${impl_simple_copy('font_stretch', 'mFont.stretch')}
|
|
||||||
pub fn clone_font_stretch(&self) -> longhands::font_stretch::computed_value::T {
|
|
||||||
use crate::values::computed::font::FontStretch;
|
|
||||||
use crate::values::computed::Percentage;
|
|
||||||
use crate::values::generics::NonNegative;
|
|
||||||
|
|
||||||
let stretch =
|
|
||||||
unsafe { bindings::Gecko_FontStretch_ToFloat(self.gecko.mFont.stretch) };
|
|
||||||
debug_assert!(stretch >= 0.);
|
|
||||||
|
|
||||||
FontStretch(NonNegative(Percentage(stretch)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_font_style(&mut self, v: longhands::font_style::computed_value::T) {
|
|
||||||
use crate::values::generics::font::FontStyle;
|
|
||||||
let s = &mut self.gecko.mFont.style;
|
|
||||||
unsafe {
|
|
||||||
match v {
|
|
||||||
FontStyle::Normal => bindings::Gecko_FontSlantStyle_SetNormal(s),
|
|
||||||
FontStyle::Italic => bindings::Gecko_FontSlantStyle_SetItalic(s),
|
|
||||||
FontStyle::Oblique(ref angle) => {
|
|
||||||
bindings::Gecko_FontSlantStyle_SetOblique(s, angle.0.degrees())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
${impl_simple_copy('font_style', 'mFont.style')}
|
|
||||||
pub fn clone_font_style(&self) -> longhands::font_style::computed_value::T {
|
|
||||||
use crate::values::computed::font::FontStyle;
|
|
||||||
FontStyle::from_gecko(self.gecko.mFont.style)
|
|
||||||
}
|
|
||||||
|
|
||||||
${impl_simple_type_with_conversion("font_synthesis", "mFont.synthesis")}
|
${impl_simple_type_with_conversion("font_synthesis", "mFont.synthesis")}
|
||||||
|
|
||||||
|
|
|
@ -352,11 +352,10 @@ pub mod system_font {
|
||||||
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
|
||||||
use crate::gecko_bindings::bindings;
|
use crate::gecko_bindings::bindings;
|
||||||
use crate::gecko_bindings::structs::nsFont;
|
use crate::gecko_bindings::structs::nsFont;
|
||||||
use std::mem;
|
use crate::values::computed::font::FontSize;
|
||||||
use crate::values::computed::Percentage;
|
|
||||||
use crate::values::specified::font::KeywordInfo;
|
use crate::values::specified::font::KeywordInfo;
|
||||||
use crate::values::computed::font::{FontSize, FontStretch, FontStyle};
|
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
let mut system = mem::MaybeUninit::<nsFont>::uninit();
|
let mut system = mem::MaybeUninit::<nsFont>::uninit();
|
||||||
let system = unsafe {
|
let system = unsafe {
|
||||||
|
@ -368,20 +367,15 @@ pub mod system_font {
|
||||||
);
|
);
|
||||||
&mut *system.as_mut_ptr()
|
&mut *system.as_mut_ptr()
|
||||||
};
|
};
|
||||||
let font_weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight);
|
|
||||||
let font_stretch = FontStretch(NonNegative(Percentage(unsafe {
|
|
||||||
bindings::Gecko_FontStretch_ToFloat(system.stretch)
|
|
||||||
})));
|
|
||||||
let font_style = FontStyle::from_gecko(system.style);
|
|
||||||
let ret = ComputedSystemFont {
|
let ret = ComputedSystemFont {
|
||||||
font_family: system.family.clone(),
|
font_family: system.family.clone(),
|
||||||
font_size: FontSize {
|
font_size: FontSize {
|
||||||
size: NonNegative(cx.maybe_zoom_text(system.size.0)),
|
size: NonNegative(cx.maybe_zoom_text(system.size.0)),
|
||||||
keyword_info: KeywordInfo::none()
|
keyword_info: KeywordInfo::none()
|
||||||
},
|
},
|
||||||
font_weight,
|
font_weight: system.weight,
|
||||||
font_stretch,
|
font_stretch: system.stretch,
|
||||||
font_style,
|
font_style: system.style,
|
||||||
font_size_adjust: system.sizeAdjust,
|
font_size_adjust: system.sizeAdjust,
|
||||||
% for kwprop in kw_font_props:
|
% for kwprop in kw_font_props:
|
||||||
${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword(
|
${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword(
|
||||||
|
|
|
@ -353,12 +353,11 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
fn adjust_for_mathvariant(&mut self) {
|
fn adjust_for_mathvariant(&mut self) {
|
||||||
use crate::properties::longhands::_moz_math_variant::computed_value::T as MozMathVariant;
|
use crate::properties::longhands::_moz_math_variant::computed_value::T as MozMathVariant;
|
||||||
use crate::properties::longhands::font_weight::computed_value::T as FontWeight;
|
use crate::values::computed::font::{FontWeight, FontStyle};
|
||||||
use crate::values::generics::font::FontStyle;
|
|
||||||
if self.style.get_font().clone__moz_math_variant() != MozMathVariant::None {
|
if self.style.get_font().clone__moz_math_variant() != MozMathVariant::None {
|
||||||
let font_style = self.style.mutate_font();
|
let font_style = self.style.mutate_font();
|
||||||
font_style.set_font_weight(FontWeight::normal());
|
font_style.set_font_weight(FontWeight::NORMAL);
|
||||||
font_style.set_font_style(FontStyle::Normal);
|
font_style.set_font_style(FontStyle::NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,18 +5,11 @@
|
||||||
//! Animation implementation for various font-related types.
|
//! Animation implementation for various font-related types.
|
||||||
|
|
||||||
use super::{Animate, Procedure, ToAnimatedZero};
|
use super::{Animate, Procedure, ToAnimatedZero};
|
||||||
use crate::values::computed::font::{FontVariationSettings, FontWeight};
|
use crate::values::computed::font::FontVariationSettings;
|
||||||
use crate::values::computed::Number;
|
use crate::values::computed::Number;
|
||||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use crate::values::generics::font::{FontSettings as GenericFontSettings, FontTag, VariationValue};
|
use crate::values::generics::font::{FontSettings as GenericFontSettings, FontTag, VariationValue};
|
||||||
|
|
||||||
impl ToAnimatedZero for FontWeight {
|
|
||||||
#[inline]
|
|
||||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
|
||||||
Ok(FontWeight::normal())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def>
|
/// <https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def>
|
||||||
impl Animate for FontVariationSettings {
|
impl Animate for FontVariationSettings {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -4,27 +4,23 @@
|
||||||
|
|
||||||
//! Computed values for font properties
|
//! Computed values for font properties
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
use crate::gecko_bindings::{bindings, structs};
|
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::animated::ToAnimatedValue;
|
use crate::values::animated::ToAnimatedValue;
|
||||||
use crate::values::computed::{
|
use crate::values::computed::{
|
||||||
Angle, Context, Integer, Length, NonNegativeLength, NonNegativeNumber, NonNegativePercentage,
|
Angle, Context, Integer, Length, NonNegativeLength, NonNegativeNumber,
|
||||||
|
Number, Percentage, ToComputedValue
|
||||||
};
|
};
|
||||||
use crate::values::computed::{Number, Percentage, ToComputedValue};
|
|
||||||
use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue};
|
use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue};
|
||||||
use crate::values::generics::{font as generics, NonNegative};
|
use crate::values::generics::{font as generics, NonNegative};
|
||||||
use crate::values::specified::font::{
|
use crate::values::specified::font::{
|
||||||
self as specified, KeywordInfo, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT,
|
self as specified, KeywordInfo, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT,
|
||||||
};
|
};
|
||||||
use crate::values::specified::length::{FontBaseSize, NoCalcLength};
|
use crate::values::specified::length::{FontBaseSize, NoCalcLength};
|
||||||
use crate::values::CSSFloat;
|
|
||||||
use crate::Atom;
|
use crate::Atom;
|
||||||
use cssparser::{serialize_identifier, CssStringWriter, Parser};
|
use cssparser::{serialize_identifier, CssStringWriter, Parser};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
use style_traits::{CssWriter, ParseError, ToCss};
|
use style_traits::{CssWriter, ParseError, ToCss};
|
||||||
|
|
||||||
pub use crate::values::computed::Length as MozScriptMinSize;
|
pub use crate::values::computed::Length as MozScriptMinSize;
|
||||||
|
@ -32,34 +28,159 @@ pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier}
|
||||||
pub use crate::values::specified::font::{XLang, XTextZoom};
|
pub use crate::values::specified::font::{XLang, XTextZoom};
|
||||||
pub use crate::values::specified::Integer as SpecifiedInteger;
|
pub use crate::values::specified::Integer as SpecifiedInteger;
|
||||||
|
|
||||||
|
/// Generic template for font property type classes that use a fixed-point
|
||||||
|
/// internal representation with `FRACTION_BITS` for the fractional part.
|
||||||
|
///
|
||||||
|
/// Values are constructed from and exposed as floating-point, but stored
|
||||||
|
/// internally as fixed point, so there will be a quantization effect on
|
||||||
|
/// fractional values, depending on the number of fractional bits used.
|
||||||
|
///
|
||||||
|
/// Using (16-bit) fixed-point types rather than floats for these style
|
||||||
|
/// attributes reduces the memory footprint of gfxFontEntry and gfxFontStyle; it
|
||||||
|
/// will also tend to reduce the number of distinct font instances that get
|
||||||
|
/// created, particularly when styles are animated or set to arbitrary values
|
||||||
|
/// (e.g. by sliders in the UI), which should reduce pressure on graphics
|
||||||
|
/// resources and improve cache hit rates.
|
||||||
|
///
|
||||||
|
/// cbindgen:derive-lt
|
||||||
|
/// cbindgen:derive-lte
|
||||||
|
/// cbindgen:derive-gt
|
||||||
|
/// cbindgen:derive-gte
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(
|
||||||
|
Clone, ComputeSquaredDistance, Copy, Debug, Hash, MallocSizeOf, PartialEq, PartialOrd, ToResolvedValue,
|
||||||
|
)]
|
||||||
|
pub struct FixedPoint<T, const FRACTION_BITS: u16> {
|
||||||
|
value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, const FRACTION_BITS: u16> FixedPoint<T, FRACTION_BITS>
|
||||||
|
where
|
||||||
|
T: num_traits::cast::AsPrimitive<f32>,
|
||||||
|
f32: num_traits::cast::AsPrimitive<T>,
|
||||||
|
{
|
||||||
|
const SCALE: u16 = 1 << FRACTION_BITS;
|
||||||
|
const INVERSE_SCALE: f32 = 1.0 / Self::SCALE as f32;
|
||||||
|
|
||||||
|
/// Returns a fixed-point bit from a floating-point context.
|
||||||
|
fn from_float(v: f32) -> Self {
|
||||||
|
use num_traits::cast::AsPrimitive;
|
||||||
|
Self {
|
||||||
|
value: (v * Self::SCALE as f32).round().as_(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the floating-point representation.
|
||||||
|
fn to_float(&self) -> f32 {
|
||||||
|
self.value.as_() * Self::INVERSE_SCALE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// font-weight: range 1..1000, fractional values permitted; keywords
|
||||||
|
/// 'normal', 'bold' aliased to 400, 700 respectively.
|
||||||
|
///
|
||||||
|
/// We use an unsigned 10.6 fixed-point value (range 0.0 - 1023.984375)
|
||||||
|
pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6;
|
||||||
|
|
||||||
|
/// This is an alias which is useful mostly as a cbindgen / C++ inference
|
||||||
|
/// workaround.
|
||||||
|
pub type FontWeightFixedPoint = FixedPoint<u16, FONT_WEIGHT_FRACTION_BITS>;
|
||||||
|
|
||||||
/// A value for the font-weight property per:
|
/// A value for the font-weight property per:
|
||||||
///
|
///
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight
|
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight
|
||||||
///
|
///
|
||||||
/// This is effectively just a `Number`.
|
/// cbindgen:derive-lt
|
||||||
|
/// cbindgen:derive-lte
|
||||||
|
/// cbindgen:derive-gt
|
||||||
|
/// cbindgen:derive-gte
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue,
|
Clone, ComputeSquaredDistance, Copy, Debug, Hash, MallocSizeOf, PartialEq, PartialOrd, ToResolvedValue,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||||
pub struct FontWeight(pub Number);
|
#[repr(C)]
|
||||||
|
pub struct FontWeight(FontWeightFixedPoint);
|
||||||
impl Hash for FontWeight {
|
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
||||||
hasher.write_u64((self.0 * 10000.).trunc() as u64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToAnimatedValue for FontWeight {
|
impl ToAnimatedValue for FontWeight {
|
||||||
type AnimatedValue = Number;
|
type AnimatedValue = Number;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||||
self.0
|
self.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
FontWeight(animated.max(MIN_FONT_WEIGHT).min(MAX_FONT_WEIGHT))
|
FontWeight::from_float(animated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for FontWeight {
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: fmt::Write,
|
||||||
|
{
|
||||||
|
self.value().to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontWeight {
|
||||||
|
/// The `normal` keyword.
|
||||||
|
pub const NORMAL: FontWeight = FontWeight(FontWeightFixedPoint { value: 400 << FONT_WEIGHT_FRACTION_BITS });
|
||||||
|
|
||||||
|
/// The `bold` value.
|
||||||
|
pub const BOLD: FontWeight = FontWeight(FontWeightFixedPoint { value: 700 << FONT_WEIGHT_FRACTION_BITS });
|
||||||
|
|
||||||
|
/// The threshold from which we consider a font bold.
|
||||||
|
pub const BOLD_THRESHOLD: FontWeight = FontWeight(FontWeightFixedPoint { value: 600 << FONT_WEIGHT_FRACTION_BITS });
|
||||||
|
|
||||||
|
/// Returns the `normal` keyword value.
|
||||||
|
pub fn normal() -> Self {
|
||||||
|
Self::NORMAL
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Weither this weight is bold
|
||||||
|
pub fn is_bold(&self) -> bool {
|
||||||
|
*self >= Self::BOLD_THRESHOLD
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the value as a float.
|
||||||
|
pub fn value(&self) -> f32 {
|
||||||
|
self.0.to_float()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a valid weight from a float value.
|
||||||
|
pub fn from_float(v: f32) -> Self {
|
||||||
|
Self(FixedPoint::from_float(v.max(MIN_FONT_WEIGHT).min(MAX_FONT_WEIGHT)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the bolder weight.
|
||||||
|
///
|
||||||
|
/// See the table in:
|
||||||
|
/// https://drafts.csswg.org/css-fonts-4/#font-weight-numeric-values
|
||||||
|
pub fn bolder(self) -> Self {
|
||||||
|
let value = self.value();
|
||||||
|
if value < 350. {
|
||||||
|
return Self::NORMAL;
|
||||||
|
}
|
||||||
|
if value < 550. {
|
||||||
|
return Self::BOLD;
|
||||||
|
}
|
||||||
|
Self::from_float(value.max(900.))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the lighter weight.
|
||||||
|
///
|
||||||
|
/// See the table in:
|
||||||
|
/// https://drafts.csswg.org/css-fonts-4/#font-weight-numeric-values
|
||||||
|
pub fn lighter(self) -> Self {
|
||||||
|
let value = self.value();
|
||||||
|
if value < 550. {
|
||||||
|
return Self::from_float(value.min(100.))
|
||||||
|
}
|
||||||
|
if value < 750. {
|
||||||
|
return Self::NORMAL;
|
||||||
|
}
|
||||||
|
Self::BOLD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,60 +206,6 @@ pub struct FontSize {
|
||||||
pub keyword_info: KeywordInfo,
|
pub keyword_info: KeywordInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontWeight {
|
|
||||||
/// Value for normal
|
|
||||||
pub fn normal() -> Self {
|
|
||||||
FontWeight(400.)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Value for bold
|
|
||||||
pub fn bold() -> Self {
|
|
||||||
FontWeight(700.)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert from an Gecko weight
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
pub fn from_gecko_weight(weight: structs::FontWeight) -> Self {
|
|
||||||
// we allow a wider range of weights than is parseable
|
|
||||||
// because system fonts may provide custom values
|
|
||||||
let weight = unsafe { bindings::Gecko_FontWeight_ToFloat(weight) };
|
|
||||||
FontWeight(weight)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Weither this weight is bold
|
|
||||||
pub fn is_bold(&self) -> bool {
|
|
||||||
self.0 > 500.
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the bolder weight.
|
|
||||||
///
|
|
||||||
/// See the table in:
|
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#font-weight-numeric-values
|
|
||||||
pub fn bolder(self) -> Self {
|
|
||||||
if self.0 < 350. {
|
|
||||||
FontWeight(400.)
|
|
||||||
} else if self.0 < 550. {
|
|
||||||
FontWeight(700.)
|
|
||||||
} else {
|
|
||||||
FontWeight(self.0.max(900.))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the lighter weight.
|
|
||||||
///
|
|
||||||
/// See the table in:
|
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#font-weight-numeric-values
|
|
||||||
pub fn lighter(self) -> Self {
|
|
||||||
if self.0 < 550. {
|
|
||||||
FontWeight(self.0.min(100.))
|
|
||||||
} else if self.0 < 750. {
|
|
||||||
FontWeight(400.)
|
|
||||||
} else {
|
|
||||||
FontWeight(700.)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FontSize {
|
impl FontSize {
|
||||||
/// The actual computed font size.
|
/// The actual computed font size.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -812,76 +879,66 @@ impl ToComputedValue for specified::MathDepth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper over an `Angle`, that handles clamping to the appropriate range
|
/// - Use a signed 8.8 fixed-point value (representable range -128.0..128)
|
||||||
/// for `font-style` animation.
|
///
|
||||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
|
/// Values of <angle> below -90 or above 90 not permitted, so we use out of
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
/// range values to represent normal | oblique
|
||||||
pub struct FontStyleAngle(pub Angle);
|
pub const FONT_STYLE_FRACTION_BITS: u16 = 8;
|
||||||
|
|
||||||
impl ToAnimatedValue for FontStyleAngle {
|
/// This is an alias which is useful mostly as a cbindgen / C++ inference
|
||||||
type AnimatedValue = Angle;
|
/// workaround.
|
||||||
|
pub type FontStyleFixedPoint = FixedPoint<i16, FONT_STYLE_FRACTION_BITS>;
|
||||||
#[inline]
|
|
||||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
|
||||||
FontStyleAngle(Angle::from_degrees(
|
|
||||||
animated
|
|
||||||
.degrees()
|
|
||||||
.min(specified::FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES)
|
|
||||||
.max(specified::FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash for FontStyleAngle {
|
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
||||||
hasher.write_u64((self.0.degrees() * 10000.).trunc() as u64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The computed value of `font-style`.
|
/// The computed value of `font-style`.
|
||||||
///
|
///
|
||||||
/// FIXME(emilio): Angle should be a custom type to handle clamping during
|
/// - Define out of range values min value (-128.0) as meaning 'normal'
|
||||||
/// animation.
|
/// - Define max value (127.99609375) as 'italic'
|
||||||
pub type FontStyle = generics::FontStyle<FontStyleAngle>;
|
/// - Other values represent 'oblique <angle>'
|
||||||
|
/// - Note that 'oblique 0deg' is distinct from 'normal' (should it be?)
|
||||||
|
///
|
||||||
|
/// cbindgen:derive-lt
|
||||||
|
/// cbindgen:derive-lte
|
||||||
|
/// cbindgen:derive-gt
|
||||||
|
/// cbindgen:derive-gte
|
||||||
|
#[derive(
|
||||||
|
Clone, ComputeSquaredDistance, Copy, Debug, Hash, MallocSizeOf, PartialEq, PartialOrd, ToResolvedValue,
|
||||||
|
)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FontStyle(FontStyleFixedPoint);
|
||||||
|
|
||||||
impl FontStyle {
|
impl FontStyle {
|
||||||
|
/// The normal keyword.
|
||||||
|
pub const NORMAL: FontStyle = FontStyle(FontStyleFixedPoint { value: 100 << FONT_STYLE_FRACTION_BITS });
|
||||||
|
/// The italic keyword.
|
||||||
|
pub const ITALIC: FontStyle = FontStyle(FontStyleFixedPoint { value: 101 << FONT_STYLE_FRACTION_BITS });
|
||||||
|
|
||||||
|
/// The default angle for `font-style: oblique`.
|
||||||
|
/// See also https://github.com/w3c/csswg-drafts/issues/2295
|
||||||
|
pub const DEFAULT_OBLIQUE_DEGREES: i16 = 14;
|
||||||
|
|
||||||
|
/// The `oblique` keyword with the default degrees.
|
||||||
|
pub const OBLIQUE: FontStyle = FontStyle(FontStyleFixedPoint { value: Self::DEFAULT_OBLIQUE_DEGREES << FONT_STYLE_FRACTION_BITS });
|
||||||
|
|
||||||
/// The `normal` value.
|
/// The `normal` value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn normal() -> Self {
|
pub fn normal() -> Self {
|
||||||
generics::FontStyle::Normal
|
Self::NORMAL
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The default angle for font-style: oblique. This is 20deg per spec:
|
/// Returns the oblique angle for this style.
|
||||||
///
|
pub fn oblique(degrees: f32) -> Self {
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle
|
Self(FixedPoint::from_float(
|
||||||
#[inline]
|
degrees
|
||||||
pub fn default_angle() -> FontStyleAngle {
|
.max(specified::FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES)
|
||||||
FontStyleAngle(Angle::from_degrees(
|
.min(specified::FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES)
|
||||||
specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the font style from Gecko's nsFont struct.
|
/// Returns the oblique angle for this style.
|
||||||
#[cfg(feature = "gecko")]
|
pub fn oblique_degrees(&self) -> f32 {
|
||||||
pub fn from_gecko(style: structs::FontSlantStyle) -> Self {
|
debug_assert_ne!(*self, Self::NORMAL);
|
||||||
let mut angle = 0.;
|
debug_assert_ne!(*self, Self::ITALIC);
|
||||||
let mut italic = false;
|
self.0.to_float()
|
||||||
let mut normal = false;
|
|
||||||
unsafe {
|
|
||||||
bindings::Gecko_FontSlantStyle_Get(style, &mut normal, &mut italic, &mut angle);
|
|
||||||
}
|
|
||||||
if normal {
|
|
||||||
return generics::FontStyle::Normal;
|
|
||||||
}
|
|
||||||
if italic {
|
|
||||||
return generics::FontStyle::Italic;
|
|
||||||
}
|
|
||||||
generics::FontStyle::Oblique(FontStyleAngle(Angle::from_degrees(angle)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -890,43 +947,173 @@ impl ToCss for FontStyle {
|
||||||
where
|
where
|
||||||
W: fmt::Write,
|
W: fmt::Write,
|
||||||
{
|
{
|
||||||
match *self {
|
if *self == Self::NORMAL {
|
||||||
generics::FontStyle::Normal => dest.write_str("normal"),
|
return dest.write_str("normal")
|
||||||
generics::FontStyle::Italic => dest.write_str("italic"),
|
}
|
||||||
generics::FontStyle::Oblique(ref angle) => {
|
if *self == Self::ITALIC {
|
||||||
dest.write_str("oblique")?;
|
return dest.write_str("italic")
|
||||||
// Use `degrees` instead of just comparing Angle because
|
}
|
||||||
// `degrees` can return slightly different values due to
|
if *self == Self::OBLIQUE {
|
||||||
// floating point conversions.
|
return dest.write_str("oblique");
|
||||||
if angle.0.degrees() != Self::default_angle().0.degrees() {
|
}
|
||||||
dest.write_char(' ')?;
|
dest.write_str("oblique ")?;
|
||||||
angle.to_css(dest)?;
|
let angle = Angle::from_degrees(self.oblique_degrees());
|
||||||
}
|
angle.to_css(dest)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToAnimatedValue for FontStyle {
|
||||||
|
type AnimatedValue = generics::FontStyle<Angle>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||||
|
if self == Self::NORMAL {
|
||||||
|
return generics::FontStyle::Normal
|
||||||
|
}
|
||||||
|
if self == Self::ITALIC {
|
||||||
|
return generics::FontStyle::Italic
|
||||||
|
}
|
||||||
|
generics::FontStyle::Oblique(Angle::from_degrees(self.oblique_degrees()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
|
match animated {
|
||||||
|
generics::FontStyle::Normal => Self::NORMAL,
|
||||||
|
generics::FontStyle::Italic => Self::ITALIC,
|
||||||
|
generics::FontStyle::Oblique(ref angle) => Self::oblique(angle.degrees()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// font-stretch is a percentage relative to normal.
|
||||||
|
///
|
||||||
|
/// We use an unsigned 10.6 fixed-point value (range 0.0 - 1023.984375)
|
||||||
|
///
|
||||||
|
/// We arbitrarily limit here to 1000%. (If that becomes a problem, we could
|
||||||
|
/// reduce the number of fractional bits and increase the limit.)
|
||||||
|
pub const FONT_STRETCH_FRACTION_BITS: u16 = 6;
|
||||||
|
|
||||||
|
/// This is an alias which is useful mostly as a cbindgen / C++ inference
|
||||||
|
/// workaround.
|
||||||
|
pub type FontStretchFixedPoint = FixedPoint<u16, FONT_STRETCH_FRACTION_BITS>;
|
||||||
|
|
||||||
|
|
||||||
/// A value for the font-stretch property per:
|
/// A value for the font-stretch property per:
|
||||||
///
|
///
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-stretch
|
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-stretch
|
||||||
|
///
|
||||||
|
/// cbindgen:derive-lt
|
||||||
|
/// cbindgen:derive-lte
|
||||||
|
/// cbindgen:derive-gt
|
||||||
|
/// cbindgen:derive-gte
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue,
|
Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToResolvedValue,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
#[repr(C)]
|
||||||
pub struct FontStretch(pub NonNegativePercentage);
|
pub struct FontStretch(pub FontStretchFixedPoint);
|
||||||
|
|
||||||
impl FontStretch {
|
impl FontStretch {
|
||||||
|
/// The fraction bits, as an easy-to-access-constant.
|
||||||
|
pub const FRACTION_BITS: u16 = FONT_STRETCH_FRACTION_BITS;
|
||||||
|
/// 0.5 in our floating point representation.
|
||||||
|
pub const HALF: u16 = 1 << (Self::FRACTION_BITS - 1);
|
||||||
|
|
||||||
|
/// The `ultra-condensed` keyword.
|
||||||
|
pub const ULTRA_CONDENSED: FontStretch = FontStretch(FontStretchFixedPoint { value: 50 << Self::FRACTION_BITS });
|
||||||
|
/// The `extra-condensed` keyword.
|
||||||
|
pub const EXTRA_CONDENSED: FontStretch = FontStretch(FontStretchFixedPoint { value: (62 << Self::FRACTION_BITS) + Self::HALF });
|
||||||
|
/// The `condensed` keyword.
|
||||||
|
pub const CONDENSED: FontStretch = FontStretch(FontStretchFixedPoint { value: 75 << Self::FRACTION_BITS });
|
||||||
|
/// The `semi-condensed` keyword.
|
||||||
|
pub const SEMI_CONDENSED: FontStretch = FontStretch(FontStretchFixedPoint { value: (87 << Self::FRACTION_BITS) + Self::HALF });
|
||||||
|
/// The `normal` keyword.
|
||||||
|
pub const NORMAL: FontStretch = FontStretch(FontStretchFixedPoint { value: 100 << Self::FRACTION_BITS });
|
||||||
|
/// The `semi-expanded` keyword.
|
||||||
|
pub const SEMI_EXPANDED: FontStretch = FontStretch(FontStretchFixedPoint { value: (112 << Self::FRACTION_BITS) + Self::HALF });
|
||||||
|
/// The `expanded` keyword.
|
||||||
|
pub const EXPANDED: FontStretch = FontStretch(FontStretchFixedPoint { value: 125 << Self::FRACTION_BITS });
|
||||||
|
/// The `extra-expanded` keyword.
|
||||||
|
pub const EXTRA_EXPANDED: FontStretch = FontStretch(FontStretchFixedPoint { value: 150 << Self::FRACTION_BITS });
|
||||||
|
/// The `ultra-expanded` keyword.
|
||||||
|
pub const ULTRA_EXPANDED: FontStretch = FontStretch(FontStretchFixedPoint { value: 200 << Self::FRACTION_BITS });
|
||||||
|
|
||||||
/// 100%
|
/// 100%
|
||||||
pub fn hundred() -> Self {
|
pub fn hundred() -> Self {
|
||||||
FontStretch(NonNegativePercentage::hundred())
|
Self::NORMAL
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The float value of the percentage
|
/// Converts to a computed percentage.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn value(&self) -> CSSFloat {
|
pub fn to_percentage(&self) -> Percentage {
|
||||||
((self.0).0).0
|
Percentage(self.0.to_float() / 100.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts from a computed percentage value.
|
||||||
|
pub fn from_percentage(p: f32) -> Self {
|
||||||
|
Self(FixedPoint::from_float((p * 100.).max(0.0).min(1000.0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a relevant stretch value from a keyword.
|
||||||
|
/// https://drafts.csswg.org/css-fonts-4/#font-stretch-prop
|
||||||
|
pub fn from_keyword(kw: specified::FontStretchKeyword) -> Self {
|
||||||
|
use specified::FontStretchKeyword::*;
|
||||||
|
match kw {
|
||||||
|
UltraCondensed => Self::ULTRA_CONDENSED,
|
||||||
|
ExtraCondensed => Self::EXTRA_CONDENSED,
|
||||||
|
Condensed => Self::CONDENSED,
|
||||||
|
SemiCondensed => Self::SEMI_CONDENSED,
|
||||||
|
Normal => Self::NORMAL,
|
||||||
|
SemiExpanded => Self::SEMI_EXPANDED,
|
||||||
|
Expanded => Self::EXPANDED,
|
||||||
|
ExtraExpanded => Self::EXTRA_EXPANDED,
|
||||||
|
UltraExpanded => Self::ULTRA_EXPANDED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the stretch keyword if we map to one of the relevant values.
|
||||||
|
pub fn as_keyword(&self) -> Option<specified::FontStretchKeyword> {
|
||||||
|
use specified::FontStretchKeyword::*;
|
||||||
|
// TODO: Can we use match here?
|
||||||
|
if *self == Self::ULTRA_CONDENSED {
|
||||||
|
return Some(UltraCondensed);
|
||||||
|
}
|
||||||
|
if *self == Self::EXTRA_CONDENSED {
|
||||||
|
return Some(ExtraCondensed);
|
||||||
|
}
|
||||||
|
if *self == Self::CONDENSED {
|
||||||
|
return Some(Condensed);
|
||||||
|
}
|
||||||
|
if *self == Self::SEMI_CONDENSED {
|
||||||
|
return Some(SemiCondensed);
|
||||||
|
}
|
||||||
|
if *self == Self::NORMAL {
|
||||||
|
return Some(Normal);
|
||||||
|
}
|
||||||
|
if *self == Self::SEMI_EXPANDED {
|
||||||
|
return Some(SemiExpanded);
|
||||||
|
}
|
||||||
|
if *self == Self::EXPANDED {
|
||||||
|
return Some(Expanded);
|
||||||
|
}
|
||||||
|
if *self == Self::EXTRA_EXPANDED {
|
||||||
|
return Some(ExtraExpanded);
|
||||||
|
}
|
||||||
|
if *self == Self::ULTRA_EXPANDED {
|
||||||
|
return Some(UltraExpanded);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for FontStretch {
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: fmt::Write,
|
||||||
|
{
|
||||||
|
self.to_percentage().to_css(dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,17 +1122,11 @@ impl ToAnimatedValue for FontStretch {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||||
self.0.to_animated_value()
|
self.to_percentage()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
FontStretch(NonNegativePercentage::from_animated_value(animated))
|
Self::from_percentage(animated.0)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash for FontStretch {
|
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
||||||
hasher.write_u64((self.value() * 10000.).trunc() as u64);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,13 @@ impl ComputeSquaredDistance for u16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ComputeSquaredDistance for i16 {
|
||||||
|
#[inline]
|
||||||
|
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||||
|
Ok(SquaredDistance::from_sqrt((*self - *other).abs() as f64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ComputeSquaredDistance for i32 {
|
impl ComputeSquaredDistance for i32 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||||
|
|
|
@ -63,11 +63,12 @@ macro_rules! trivial_to_resolved_value {
|
||||||
trivial_to_resolved_value!(());
|
trivial_to_resolved_value!(());
|
||||||
trivial_to_resolved_value!(bool);
|
trivial_to_resolved_value!(bool);
|
||||||
trivial_to_resolved_value!(f32);
|
trivial_to_resolved_value!(f32);
|
||||||
trivial_to_resolved_value!(i32);
|
|
||||||
trivial_to_resolved_value!(u8);
|
trivial_to_resolved_value!(u8);
|
||||||
trivial_to_resolved_value!(i8);
|
trivial_to_resolved_value!(i8);
|
||||||
trivial_to_resolved_value!(u16);
|
trivial_to_resolved_value!(u16);
|
||||||
|
trivial_to_resolved_value!(i16);
|
||||||
trivial_to_resolved_value!(u32);
|
trivial_to_resolved_value!(u32);
|
||||||
|
trivial_to_resolved_value!(i32);
|
||||||
trivial_to_resolved_value!(usize);
|
trivial_to_resolved_value!(usize);
|
||||||
trivial_to_resolved_value!(String);
|
trivial_to_resolved_value!(String);
|
||||||
trivial_to_resolved_value!(Box<str>);
|
trivial_to_resolved_value!(Box<str>);
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::context::QuirksMode;
|
use crate::context::QuirksMode;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily};
|
use crate::values::computed::font::{FamilyName, FontFamilyList, SingleFontFamily};
|
||||||
use crate::values::computed::FontSizeAdjust as ComputedFontSizeAdjust;
|
use crate::values::computed::FontSizeAdjust as ComputedFontSizeAdjust;
|
||||||
use crate::values::computed::{font as computed, Length, NonNegativeLength};
|
use crate::values::computed::{font as computed, Length, NonNegativeLength};
|
||||||
use crate::values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage};
|
use crate::values::computed::{Percentage as ComputedPercentage};
|
||||||
use crate::values::computed::{CSSPixelLength, Context, ToComputedValue};
|
use crate::values::computed::{CSSPixelLength, Context, ToComputedValue};
|
||||||
use crate::values::generics::font::VariationValue;
|
use crate::values::generics::font::VariationValue;
|
||||||
use crate::values::generics::font::{
|
use crate::values::generics::font::{
|
||||||
|
@ -185,7 +185,7 @@ impl ToComputedValue for FontWeight {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_computed_value(computed: &computed::FontWeight) -> Self {
|
fn from_computed_value(computed: &computed::FontWeight) -> Self {
|
||||||
FontWeight::Absolute(AbsoluteFontWeight::Weight(Number::from_computed_value(
|
FontWeight::Absolute(AbsoluteFontWeight::Weight(Number::from_computed_value(
|
||||||
&computed.0,
|
&computed.value(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,10 +210,10 @@ impl AbsoluteFontWeight {
|
||||||
pub fn compute(&self) -> computed::FontWeight {
|
pub fn compute(&self) -> computed::FontWeight {
|
||||||
match *self {
|
match *self {
|
||||||
AbsoluteFontWeight::Weight(weight) => {
|
AbsoluteFontWeight::Weight(weight) => {
|
||||||
computed::FontWeight(weight.get().max(MIN_FONT_WEIGHT).min(MAX_FONT_WEIGHT))
|
computed::FontWeight::from_float(weight.get())
|
||||||
},
|
},
|
||||||
AbsoluteFontWeight::Normal => computed::FontWeight::normal(),
|
AbsoluteFontWeight::Normal => computed::FontWeight::NORMAL,
|
||||||
AbsoluteFontWeight::Bold => computed::FontWeight::bold(),
|
AbsoluteFontWeight::Bold => computed::FontWeight::BOLD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,33 +289,24 @@ impl ToComputedValue for SpecifiedFontStyle {
|
||||||
|
|
||||||
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
|
||||||
match *self {
|
match *self {
|
||||||
generics::FontStyle::Normal => generics::FontStyle::Normal,
|
Self::Normal => computed::FontStyle::NORMAL,
|
||||||
generics::FontStyle::Italic => generics::FontStyle::Italic,
|
Self::Italic => computed::FontStyle::ITALIC,
|
||||||
generics::FontStyle::Oblique(ref angle) => {
|
Self::Oblique(ref angle) => computed::FontStyle::oblique(angle.degrees()),
|
||||||
generics::FontStyle::Oblique(FontStyleAngle(Self::compute_angle(angle)))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
match *computed {
|
if *computed == computed::FontStyle::NORMAL {
|
||||||
generics::FontStyle::Normal => generics::FontStyle::Normal,
|
return Self::Normal;
|
||||||
generics::FontStyle::Italic => generics::FontStyle::Italic,
|
|
||||||
generics::FontStyle::Oblique(ref angle) => {
|
|
||||||
generics::FontStyle::Oblique(Angle::from_computed_value(&angle.0))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
if *computed == computed::FontStyle::ITALIC {
|
||||||
|
return Self::Italic;
|
||||||
|
}
|
||||||
|
let degrees = computed.oblique_degrees();
|
||||||
|
generics::FontStyle::Oblique(Angle::from_degrees(degrees, /* was_calc = */ false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The default angle for `font-style: oblique`.
|
|
||||||
///
|
|
||||||
/// NOTE(emilio): As of right now this diverges from the spec, which specifies
|
|
||||||
/// 20, because it's not updated yet to account for the resolution in:
|
|
||||||
///
|
|
||||||
/// https://github.com/w3c/csswg-drafts/issues/2295
|
|
||||||
pub const DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES: f32 = 14.;
|
|
||||||
|
|
||||||
/// From https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle:
|
/// From https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle:
|
||||||
///
|
///
|
||||||
/// Values less than -90deg or values greater than 90deg are
|
/// Values less than -90deg or values greater than 90deg are
|
||||||
|
@ -336,10 +327,6 @@ impl SpecifiedFontStyle {
|
||||||
.min(FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES)
|
.min(FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_angle(angle: &Angle) -> ComputedAngle {
|
|
||||||
ComputedAngle::from_degrees(Self::compute_angle_degrees(angle))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a suitable angle for font-style: oblique.
|
/// Parse a suitable angle for font-style: oblique.
|
||||||
pub fn parse_angle<'i, 't>(
|
pub fn parse_angle<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
|
@ -362,7 +349,7 @@ impl SpecifiedFontStyle {
|
||||||
/// The default angle for `font-style: oblique`.
|
/// The default angle for `font-style: oblique`.
|
||||||
pub fn default_angle() -> Angle {
|
pub fn default_angle() -> Angle {
|
||||||
Angle::from_degrees(
|
Angle::from_degrees(
|
||||||
DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES,
|
computed::FontStyle::DEFAULT_OBLIQUE_DEGREES as f32,
|
||||||
/* was_calc = */ false,
|
/* was_calc = */ false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -411,7 +398,6 @@ impl ToComputedValue for FontStyle {
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
|
Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
|
||||||
)]
|
)]
|
||||||
#[repr(u8)]
|
|
||||||
pub enum FontStretch {
|
pub enum FontStretch {
|
||||||
Stretch(NonNegativePercentage),
|
Stretch(NonNegativePercentage),
|
||||||
Keyword(FontStretchKeyword),
|
Keyword(FontStretchKeyword),
|
||||||
|
@ -437,57 +423,15 @@ pub enum FontStretchKeyword {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontStretchKeyword {
|
impl FontStretchKeyword {
|
||||||
/// Resolves the value of the keyword as specified in:
|
/// Turns the keyword into a computed value.
|
||||||
///
|
pub fn compute(&self) -> computed::FontStretch {
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#font-stretch-prop
|
computed::FontStretch::from_keyword(*self)
|
||||||
pub fn compute(&self) -> ComputedPercentage {
|
|
||||||
use self::FontStretchKeyword::*;
|
|
||||||
ComputedPercentage(match *self {
|
|
||||||
UltraCondensed => 0.5,
|
|
||||||
ExtraCondensed => 0.625,
|
|
||||||
Condensed => 0.75,
|
|
||||||
SemiCondensed => 0.875,
|
|
||||||
Normal => 1.,
|
|
||||||
SemiExpanded => 1.125,
|
|
||||||
Expanded => 1.25,
|
|
||||||
ExtraExpanded => 1.5,
|
|
||||||
UltraExpanded => 2.,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does the opposite operation to `compute`, in order to serialize keywords
|
/// Does the opposite operation to `compute`, in order to serialize keywords
|
||||||
/// if possible.
|
/// if possible.
|
||||||
pub fn from_percentage(percentage: f32) -> Option<Self> {
|
pub fn from_percentage(p: f32) -> Option<Self> {
|
||||||
use self::FontStretchKeyword::*;
|
computed::FontStretch::from_percentage(p).as_keyword()
|
||||||
// NOTE(emilio): Can't use `match` because of rust-lang/rust#41620.
|
|
||||||
if percentage == 0.5 {
|
|
||||||
return Some(UltraCondensed);
|
|
||||||
}
|
|
||||||
if percentage == 0.625 {
|
|
||||||
return Some(ExtraCondensed);
|
|
||||||
}
|
|
||||||
if percentage == 0.75 {
|
|
||||||
return Some(Condensed);
|
|
||||||
}
|
|
||||||
if percentage == 0.875 {
|
|
||||||
return Some(SemiCondensed);
|
|
||||||
}
|
|
||||||
if percentage == 1. {
|
|
||||||
return Some(Normal);
|
|
||||||
}
|
|
||||||
if percentage == 1.125 {
|
|
||||||
return Some(SemiExpanded);
|
|
||||||
}
|
|
||||||
if percentage == 1.25 {
|
|
||||||
return Some(Expanded);
|
|
||||||
}
|
|
||||||
if percentage == 1.5 {
|
|
||||||
return Some(ExtraExpanded);
|
|
||||||
}
|
|
||||||
if percentage == 2. {
|
|
||||||
return Some(UltraExpanded);
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,16 +450,17 @@ impl ToComputedValue for FontStretch {
|
||||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
match *self {
|
match *self {
|
||||||
FontStretch::Stretch(ref percentage) => {
|
FontStretch::Stretch(ref percentage) => {
|
||||||
computed::FontStretch(percentage.to_computed_value(context))
|
let percentage = percentage.to_computed_value(context).0;
|
||||||
|
computed::FontStretch::from_percentage(percentage.0)
|
||||||
},
|
},
|
||||||
FontStretch::Keyword(ref kw) => computed::FontStretch(NonNegative(kw.compute())),
|
FontStretch::Keyword(ref kw) => kw.compute(),
|
||||||
FontStretch::System(_) => self.compute_system(context),
|
FontStretch::System(_) => self.compute_system(context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
FontStretch::Stretch(NonNegativePercentage::from_computed_value(&NonNegative(
|
FontStretch::Stretch(NonNegativePercentage::from_computed_value(&NonNegative(
|
||||||
(computed.0).0,
|
computed.to_percentage()
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue