mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #17122 - servo:derive-all-the-things, r=emilio
Continue to slim down the code for CSS properties <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17122) <!-- Reviewable:end -->
This commit is contained in:
commit
028908ee26
26 changed files with 549 additions and 597 deletions
|
@ -23,11 +23,12 @@ use std::borrow::ToOwned;
|
|||
use std::collections::LinkedList;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use style::computed_values::{line_height, text_rendering, text_transform};
|
||||
use style::computed_values::{text_rendering, text_transform};
|
||||
use style::computed_values::{word_break, white_space};
|
||||
use style::logical_geometry::{LogicalSize, WritingMode};
|
||||
use style::properties::ServoComputedValues;
|
||||
use style::properties::style_structs;
|
||||
use style::values::generics::text::LineHeight;
|
||||
use unicode_bidi as bidi;
|
||||
use unicode_script::{Script, get_script};
|
||||
|
||||
|
@ -165,8 +166,8 @@ impl TextRunScanner {
|
|||
white_space::T::pre_line => CompressionMode::CompressWhitespace,
|
||||
};
|
||||
text_transform = inherited_text_style.text_transform;
|
||||
letter_spacing = inherited_text_style.letter_spacing.0;
|
||||
word_spacing = inherited_text_style.word_spacing.0
|
||||
letter_spacing = inherited_text_style.letter_spacing;
|
||||
word_spacing = inherited_text_style.word_spacing.value()
|
||||
.map(|lop| lop.to_hash_key())
|
||||
.unwrap_or((Au(0), NotNaN::new(0.0).unwrap()));
|
||||
text_rendering = inherited_text_style.text_rendering;
|
||||
|
@ -288,8 +289,8 @@ impl TextRunScanner {
|
|||
// example, `finally` with a wide `letter-spacing` renders as `f i n a l l y` and not
|
||||
// `fi n a l l y`.
|
||||
let mut flags = ShapingFlags::empty();
|
||||
match letter_spacing {
|
||||
Some(Au(0)) | None => {}
|
||||
match letter_spacing.value() {
|
||||
Some(&Au(0)) | None => {}
|
||||
Some(_) => flags.insert(IGNORE_LIGATURES_SHAPING_FLAG),
|
||||
}
|
||||
if text_rendering == text_rendering::T::optimizespeed {
|
||||
|
@ -300,7 +301,7 @@ impl TextRunScanner {
|
|||
flags.insert(KEEP_ALL_FLAG);
|
||||
}
|
||||
let options = ShapingOptions {
|
||||
letter_spacing: letter_spacing,
|
||||
letter_spacing: letter_spacing.value().cloned(),
|
||||
word_spacing: word_spacing,
|
||||
script: Script::Common,
|
||||
flags: flags,
|
||||
|
@ -447,9 +448,9 @@ pub fn font_metrics_for_style(font_context: &mut FontContext, font_style: ::Styl
|
|||
pub fn line_height_from_style(style: &ServoComputedValues, metrics: &FontMetrics) -> Au {
|
||||
let font_size = style.get_font().font_size;
|
||||
match style.get_inheritedtext().line_height {
|
||||
line_height::T::Normal => metrics.line_gap,
|
||||
line_height::T::Number(l) => font_size.scale_by(l),
|
||||
line_height::T::Length(l) => l
|
||||
LineHeight::Normal => metrics.line_gap,
|
||||
LineHeight::Number(l) => font_size.scale_by(l),
|
||||
LineHeight::Length(l) => l
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -646,7 +646,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
|||
};
|
||||
|
||||
if let Some(border) = border {
|
||||
let width_value = specified::BorderWidth::from_length(specified::Length::from_px(border as f32));
|
||||
let width_value = specified::BorderSideWidth::Length(specified::Length::from_px(border as f32));
|
||||
hints.push(from_declaration(
|
||||
shared_lock,
|
||||
PropertyDeclaration::BorderTopWidth(width_value.clone())));
|
||||
|
|
|
@ -998,17 +998,17 @@ fn static_assert() {
|
|||
}
|
||||
|
||||
pub fn set_border_image_width(&mut self, v: longhands::border_image_width::computed_value::T) {
|
||||
use values::generics::border::BorderImageWidthSide;
|
||||
use values::generics::border::BorderImageSideWidth;
|
||||
|
||||
% for side in SIDES:
|
||||
match v.${side.index} {
|
||||
BorderImageWidthSide::Auto => {
|
||||
BorderImageSideWidth::Auto => {
|
||||
self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Auto)
|
||||
},
|
||||
BorderImageWidthSide::Length(l) => {
|
||||
BorderImageSideWidth::Length(l) => {
|
||||
l.to_gecko_style_coord(&mut self.gecko.mBorderImageWidth.data_at_mut(${side.index}))
|
||||
},
|
||||
BorderImageWidthSide::Number(n) => {
|
||||
BorderImageSideWidth::Number(n) => {
|
||||
self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Factor(n))
|
||||
},
|
||||
}
|
||||
|
@ -3637,65 +3637,64 @@ fn static_assert() {
|
|||
}
|
||||
|
||||
pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
|
||||
use properties::longhands::line_height::computed_value::T;
|
||||
use values::generics::text::LineHeight;
|
||||
// FIXME: Align binary representations and ditch |match| for cast + static_asserts
|
||||
let en = match v {
|
||||
T::Normal => CoordDataValue::Normal,
|
||||
T::Length(val) => CoordDataValue::Coord(val.0),
|
||||
T::Number(val) => CoordDataValue::Factor(val),
|
||||
T::MozBlockHeight =>
|
||||
LineHeight::Normal => CoordDataValue::Normal,
|
||||
LineHeight::Length(val) => CoordDataValue::Coord(val.0),
|
||||
LineHeight::Number(val) => CoordDataValue::Factor(val),
|
||||
LineHeight::MozBlockHeight =>
|
||||
CoordDataValue::Enumerated(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT),
|
||||
};
|
||||
self.gecko.mLineHeight.set_value(en);
|
||||
}
|
||||
|
||||
pub fn clone_line_height(&self) -> longhands::line_height::computed_value::T {
|
||||
use properties::longhands::line_height::computed_value::T;
|
||||
use values::generics::text::LineHeight;
|
||||
return match self.gecko.mLineHeight.as_value() {
|
||||
CoordDataValue::Normal => T::Normal,
|
||||
CoordDataValue::Coord(coord) => T::Length(Au(coord)),
|
||||
CoordDataValue::Factor(n) => T::Number(n),
|
||||
CoordDataValue::Normal => LineHeight::Normal,
|
||||
CoordDataValue::Coord(coord) => LineHeight::Length(Au(coord)),
|
||||
CoordDataValue::Factor(n) => LineHeight::Number(n),
|
||||
CoordDataValue::Enumerated(val) if val == structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT =>
|
||||
T::MozBlockHeight,
|
||||
_ => {
|
||||
debug_assert!(false);
|
||||
T::MozBlockHeight
|
||||
}
|
||||
LineHeight::MozBlockHeight,
|
||||
_ => panic!("this should not happen"),
|
||||
}
|
||||
}
|
||||
|
||||
<%call expr="impl_coord_copy('line_height', 'mLineHeight')"></%call>
|
||||
|
||||
pub fn set_letter_spacing(&mut self, v: longhands::letter_spacing::computed_value::T) {
|
||||
match v.0 {
|
||||
Some(au) => self.gecko.mLetterSpacing.set(au),
|
||||
None => self.gecko.mLetterSpacing.set_value(CoordDataValue::Normal)
|
||||
use values::generics::text::Spacing;
|
||||
match v {
|
||||
Spacing::Value(value) => self.gecko.mLetterSpacing.set(value),
|
||||
Spacing::Normal => self.gecko.mLetterSpacing.set_value(CoordDataValue::Normal)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_letter_spacing(&self) -> longhands::letter_spacing::computed_value::T {
|
||||
use properties::longhands::letter_spacing::computed_value::T;
|
||||
use values::generics::text::Spacing;
|
||||
debug_assert!(
|
||||
matches!(self.gecko.mLetterSpacing.as_value(),
|
||||
CoordDataValue::Normal |
|
||||
CoordDataValue::Coord(_)),
|
||||
"Unexpected computed value for letter-spacing");
|
||||
T(Au::from_gecko_style_coord(&self.gecko.mLetterSpacing))
|
||||
Au::from_gecko_style_coord(&self.gecko.mLetterSpacing).map_or(Spacing::Normal, Spacing::Value)
|
||||
}
|
||||
|
||||
<%call expr="impl_coord_copy('letter_spacing', 'mLetterSpacing')"></%call>
|
||||
|
||||
pub fn set_word_spacing(&mut self, v: longhands::word_spacing::computed_value::T) {
|
||||
match v.0 {
|
||||
Some(lop) => self.gecko.mWordSpacing.set(lop),
|
||||
use values::generics::text::Spacing;
|
||||
match v {
|
||||
Spacing::Value(lop) => self.gecko.mWordSpacing.set(lop),
|
||||
// https://drafts.csswg.org/css-text-3/#valdef-word-spacing-normal
|
||||
None => self.gecko.mWordSpacing.set_value(CoordDataValue::Coord(0)),
|
||||
Spacing::Normal => self.gecko.mWordSpacing.set_value(CoordDataValue::Coord(0)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_word_spacing(&self) -> longhands::word_spacing::computed_value::T {
|
||||
use properties::longhands::word_spacing::computed_value::T;
|
||||
use values::computed::LengthOrPercentage;
|
||||
use values::generics::text::Spacing;
|
||||
debug_assert!(
|
||||
matches!(self.gecko.mWordSpacing.as_value(),
|
||||
CoordDataValue::Normal |
|
||||
|
@ -3703,7 +3702,7 @@ fn static_assert() {
|
|||
CoordDataValue::Percent(_) |
|
||||
CoordDataValue::Calc(_)),
|
||||
"Unexpected computed value for word-spacing");
|
||||
T(LengthOrPercentage::from_gecko_style_coord(&self.gecko.mWordSpacing))
|
||||
LengthOrPercentage::from_gecko_style_coord(&self.gecko.mWordSpacing).map_or(Spacing::Normal, Spacing::Value)
|
||||
}
|
||||
|
||||
<%call expr="impl_coord_copy('word_spacing', 'mWordSpacing')"></%call>
|
||||
|
|
|
@ -18,7 +18,6 @@ use properties::longhands;
|
|||
use properties::longhands::background_size::computed_value::T as BackgroundSizeList;
|
||||
use properties::longhands::font_weight::computed_value::T as FontWeight;
|
||||
use properties::longhands::font_stretch::computed_value::T as FontStretch;
|
||||
use properties::longhands::line_height::computed_value::T as LineHeight;
|
||||
use properties::longhands::text_shadow::computed_value::T as TextShadowList;
|
||||
use properties::longhands::text_shadow::computed_value::TextShadow;
|
||||
use properties::longhands::box_shadow::computed_value::T as BoxShadowList;
|
||||
|
@ -1300,43 +1299,6 @@ impl Animatable for MaxLength {
|
|||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-number
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-length
|
||||
impl Animatable for LineHeight {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
match (*self, *other) {
|
||||
(LineHeight::Length(ref this),
|
||||
LineHeight::Length(ref other)) => {
|
||||
this.add_weighted(other, self_portion, other_portion).map(LineHeight::Length)
|
||||
}
|
||||
(LineHeight::Number(ref this),
|
||||
LineHeight::Number(ref other)) => {
|
||||
this.add_weighted(other, self_portion, other_portion).map(LineHeight::Number)
|
||||
}
|
||||
(LineHeight::Normal, LineHeight::Normal) => {
|
||||
Ok(LineHeight::Normal)
|
||||
}
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(LineHeight::Length(ref this),
|
||||
LineHeight::Length(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(LineHeight::Number(ref this),
|
||||
LineHeight::Number(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// http://dev.w3.org/csswg/css-transitions/#animtype-font-weight
|
||||
impl Animatable for FontWeight {
|
||||
#[inline]
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
spec=maybe_logical_spec(side, "style"),
|
||||
animation_value_type="none", logical=side[1])}
|
||||
|
||||
${helpers.predefined_type("border-%s-width" % side[0], "BorderWidth", "Au::from_px(3)",
|
||||
${helpers.predefined_type("border-%s-width" % side[0],
|
||||
"BorderSideWidth",
|
||||
"Au::from_px(3)",
|
||||
computed_type="::app_units::Au",
|
||||
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-width"),
|
||||
spec=maybe_logical_spec(side, "width"),
|
||||
|
@ -287,8 +289,8 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
|
|||
</%helpers:longhand>
|
||||
|
||||
${helpers.predefined_type("border-image-width", "BorderImageWidth",
|
||||
initial_value="computed::BorderImageWidthSide::one().into()",
|
||||
initial_specified_value="specified::BorderImageWidthSide::one().into()",
|
||||
initial_value="computed::BorderImageSideWidth::one().into()",
|
||||
initial_specified_value="specified::BorderImageSideWidth::one().into()",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-width",
|
||||
animation_value_type="none",
|
||||
boxed=True)}
|
||||
|
|
|
@ -40,11 +40,15 @@ ${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
|
|||
products="gecko", animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}
|
||||
|
||||
${helpers.predefined_type("column-rule-width", "BorderWidth", "Au::from_px(3)",
|
||||
initial_specified_value="specified::BorderWidth::Medium",
|
||||
products="gecko", computed_type="::app_units::Au",
|
||||
${helpers.predefined_type("column-rule-width",
|
||||
"BorderSideWidth",
|
||||
"Au::from_px(3)",
|
||||
initial_specified_value="specified::BorderSideWidth::Medium",
|
||||
computed_type="::app_units::Au",
|
||||
products="gecko",
|
||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
|
||||
animation_value_type="ComputedValue", extra_prefixes="moz")}
|
||||
animation_value_type="ComputedValue",
|
||||
extra_prefixes="moz")}
|
||||
|
||||
// https://drafts.csswg.org/css-multicol-1/#crc
|
||||
${helpers.predefined_type("column-rule-color", "CSSColor",
|
||||
|
|
|
@ -6,148 +6,11 @@
|
|||
<% from data import Keyword %>
|
||||
<% data.new_style_struct("InheritedText", inherited=True, gecko_name="Text") %>
|
||||
|
||||
<%helpers:longhand name="line-height" animation_value_type="ComputedValue"
|
||||
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height">
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum SpecifiedValue {
|
||||
Normal,
|
||||
% if product == "gecko":
|
||||
MozBlockHeight,
|
||||
% endif
|
||||
Number(specified::Number),
|
||||
LengthOrPercentage(specified::LengthOrPercentage),
|
||||
}
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
SpecifiedValue::Normal => dest.write_str("normal"),
|
||||
% if product == "gecko":
|
||||
SpecifiedValue::MozBlockHeight => dest.write_str("-moz-block-height"),
|
||||
% endif
|
||||
SpecifiedValue::LengthOrPercentage(ref value) => value.to_css(dest),
|
||||
SpecifiedValue::Number(number) => number.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
/// normal | <number> | <length> | <percentage>
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
use cssparser::Token;
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
// We try to parse as a Number first because, for 'line-height', we want
|
||||
// "0" to be parsed as a plain Number rather than a Length (0px); this
|
||||
// matches the behaviour of all major browsers
|
||||
if let Ok(number) = input.try(|i| specified::Number::parse_non_negative(context, i)) {
|
||||
return Ok(SpecifiedValue::Number(number))
|
||||
}
|
||||
|
||||
if let Ok(lop) = input.try(|i| specified::LengthOrPercentage::parse_non_negative(context, i)) {
|
||||
return Ok(SpecifiedValue::LengthOrPercentage(lop))
|
||||
}
|
||||
|
||||
|
||||
match try!(input.next()) {
|
||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
|
||||
Ok(SpecifiedValue::Normal)
|
||||
}
|
||||
% if product == "gecko":
|
||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("-moz-block-height") => {
|
||||
Ok(SpecifiedValue::MozBlockHeight)
|
||||
}
|
||||
% endif
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
pub mod computed_value {
|
||||
use app_units::Au;
|
||||
use values::CSSFloat;
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum T {
|
||||
Normal,
|
||||
% if product == "gecko":
|
||||
MozBlockHeight,
|
||||
% endif
|
||||
Length(Au),
|
||||
Number(CSSFloat),
|
||||
}
|
||||
}
|
||||
impl ToCss for computed_value::T {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
computed_value::T::Normal => dest.write_str("normal"),
|
||||
% if product == "gecko":
|
||||
computed_value::T::MozBlockHeight => dest.write_str("-moz-block-height"),
|
||||
% endif
|
||||
computed_value::T::Length(length) => length.to_css(dest),
|
||||
computed_value::T::Number(number) => write!(dest, "{}", number),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T { computed_value::T::Normal }
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||
SpecifiedValue::Normal
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
match *self {
|
||||
SpecifiedValue::Normal => computed_value::T::Normal,
|
||||
% if product == "gecko":
|
||||
SpecifiedValue::MozBlockHeight => computed_value::T::MozBlockHeight,
|
||||
% endif
|
||||
SpecifiedValue::Number(value) => computed_value::T::Number(value.to_computed_value(context)),
|
||||
SpecifiedValue::LengthOrPercentage(ref value) => {
|
||||
match *value {
|
||||
specified::LengthOrPercentage::Length(ref value) =>
|
||||
computed_value::T::Length(value.to_computed_value(context)),
|
||||
specified::LengthOrPercentage::Percentage(specified::Percentage(value)) => {
|
||||
let fr = specified::Length::NoCalc(specified::NoCalcLength::FontRelative(
|
||||
specified::FontRelativeLength::Em(value)));
|
||||
computed_value::T::Length(fr.to_computed_value(context))
|
||||
},
|
||||
specified::LengthOrPercentage::Calc(ref calc) => {
|
||||
let calc = calc.to_computed_value(context);
|
||||
let fr = specified::FontRelativeLength::Em(calc.percentage());
|
||||
let fr = specified::Length::NoCalc(specified::NoCalcLength::FontRelative(fr));
|
||||
let length = calc.unclamped_length();
|
||||
computed_value::T::Length(calc.clamping_mode.clamp(length + fr.to_computed_value(context)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
match *computed {
|
||||
computed_value::T::Normal => SpecifiedValue::Normal,
|
||||
% if product == "gecko":
|
||||
computed_value::T::MozBlockHeight => SpecifiedValue::MozBlockHeight,
|
||||
% endif
|
||||
computed_value::T::Number(ref value) => {
|
||||
SpecifiedValue::Number(specified::Number::from_computed_value(value))
|
||||
},
|
||||
computed_value::T::Length(au) => {
|
||||
SpecifiedValue::LengthOrPercentage(specified::LengthOrPercentage::Length(
|
||||
ToComputedValue::from_computed_value(&au)
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
${helpers.predefined_type("line-height",
|
||||
"LineHeight",
|
||||
"computed::LineHeight::normal()",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height")}
|
||||
|
||||
// CSS Text Module Level 3
|
||||
|
||||
|
@ -395,157 +258,17 @@ ${helpers.single_keyword("text-align-last",
|
|||
% endif
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:longhand name="letter-spacing" animation_value_type="ComputedValue"
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing">
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::specified::AllowQuirks;
|
||||
${helpers.predefined_type("letter-spacing",
|
||||
"LetterSpacing",
|
||||
"computed::LetterSpacing::normal()",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing")}
|
||||
|
||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum SpecifiedValue {
|
||||
Normal,
|
||||
Specified(specified::Length),
|
||||
}
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
SpecifiedValue::Normal => dest.write_str("normal"),
|
||||
SpecifiedValue::Specified(ref l) => l.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use app_units::Au;
|
||||
use properties::animated_properties::Animatable;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct T(pub Option<Au>);
|
||||
|
||||
${helpers.impl_animatable_for_option_tuple('Au(0)')}
|
||||
}
|
||||
|
||||
impl ToCss for computed_value::T {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match self.0 {
|
||||
None => dest.write_str("normal"),
|
||||
Some(l) => l.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T(None)
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
match *self {
|
||||
SpecifiedValue::Normal => computed_value::T(None),
|
||||
SpecifiedValue::Specified(ref l) =>
|
||||
computed_value::T(Some(l.to_computed_value(context)))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
computed.0.map(|ref au| {
|
||||
SpecifiedValue::Specified(ToComputedValue::from_computed_value(au))
|
||||
}).unwrap_or(SpecifiedValue::Normal)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
Ok(SpecifiedValue::Normal)
|
||||
} else {
|
||||
specified::Length::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue::Specified)
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:longhand name="word-spacing" animation_value_type="ComputedValue"
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing">
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::specified::AllowQuirks;
|
||||
|
||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum SpecifiedValue {
|
||||
Normal,
|
||||
Specified(specified::LengthOrPercentage),
|
||||
}
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
SpecifiedValue::Normal => dest.write_str("normal"),
|
||||
SpecifiedValue::Specified(ref l) => l.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::computed::LengthOrPercentage;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct T(pub Option<LengthOrPercentage>);
|
||||
|
||||
${helpers.impl_animatable_for_option_tuple('LengthOrPercentage::zero()')}
|
||||
}
|
||||
|
||||
impl ToCss for computed_value::T {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match self.0 {
|
||||
None => dest.write_str("normal"),
|
||||
Some(l) => l.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T(None)
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
match *self {
|
||||
SpecifiedValue::Normal => computed_value::T(None),
|
||||
SpecifiedValue::Specified(ref l) =>
|
||||
computed_value::T(Some(l.to_computed_value(context))),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
computed.0.map(|ref lop| {
|
||||
SpecifiedValue::Specified(ToComputedValue::from_computed_value(lop))
|
||||
}).unwrap_or(SpecifiedValue::Normal)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
Ok(SpecifiedValue::Normal)
|
||||
} else {
|
||||
specified::LengthOrPercentage::parse_quirky(context, input, AllowQuirks::Yes)
|
||||
.map(SpecifiedValue::Specified)
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
${helpers.predefined_type("word-spacing",
|
||||
"WordSpacing",
|
||||
"computed::WordSpacing::normal()",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing")}
|
||||
|
||||
<%helpers:longhand name="-servo-text-decorations-in-effect"
|
||||
derived_from="display text-decoration"
|
||||
|
@ -1149,13 +872,15 @@ ${helpers.predefined_type(
|
|||
ignored_when_colors_disabled=True,
|
||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")}
|
||||
|
||||
${helpers.predefined_type("-webkit-text-stroke-width", "BorderWidth", "Au::from_px(0)",
|
||||
initial_specified_value="specified::BorderWidth::from_length(specified::Length::zero())",
|
||||
computed_type="::app_units::Au", products="gecko",
|
||||
${helpers.predefined_type("-webkit-text-stroke-width",
|
||||
"BorderSideWidth",
|
||||
"Au::from_px(0)",
|
||||
initial_specified_value="specified::BorderSideWidth::Length(specified::Length::zero())",
|
||||
computed_type="::app_units::Au",
|
||||
products="gecko",
|
||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width",
|
||||
animation_value_type="none")}
|
||||
|
||||
|
||||
// CSS Ruby Layout Module Level 1
|
||||
// https://drafts.csswg.org/css-ruby/
|
||||
${helpers.single_keyword("ruby-align", "space-around start center space-between",
|
||||
|
|
|
@ -61,50 +61,13 @@ ${helpers.predefined_type("outline-color", "CSSColor", "computed::CSSColor::Curr
|
|||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:longhand name="outline-width" animation_value_type="ComputedValue"
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-outline-width">
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
self.0.to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
specified::parse_border_width(context, input).map(SpecifiedValue)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct SpecifiedValue(pub specified::Length);
|
||||
|
||||
pub mod computed_value {
|
||||
use app_units::Au;
|
||||
pub type T = Au;
|
||||
}
|
||||
|
||||
pub use super::border_top_width::get_initial_value;
|
||||
#[inline]
|
||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||
SpecifiedValue(specified::Length::NoCalc(specified::NoCalcLength::medium()))
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
self.0.to_computed_value(context)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
SpecifiedValue(ToComputedValue::from_computed_value(computed))
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
${helpers.predefined_type("outline-width",
|
||||
"BorderSideWidth",
|
||||
"Au::from_px(3)",
|
||||
initial_specified_value="specified::BorderSideWidth::Medium",
|
||||
computed_type="::app_units::Au",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-outline-width")}
|
||||
|
||||
// The -moz-outline-radius-* properties are non-standard and not on a standards track.
|
||||
// TODO: Should they animate?
|
||||
|
|
|
@ -38,8 +38,9 @@ use shared_lock::StylesheetGuards;
|
|||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData};
|
||||
#[cfg(feature = "servo")] use values::Either;
|
||||
use values::specified::Color;
|
||||
use values::generics::text::LineHeight;
|
||||
use values::computed;
|
||||
use values::specified::Color;
|
||||
use cascade_info::CascadeInfo;
|
||||
use rule_tree::{CascadeLevel, StrongRuleNode};
|
||||
use style_adjuster::StyleAdjuster;
|
||||
|
@ -1262,11 +1263,9 @@ impl PropertyDeclaration {
|
|||
}
|
||||
|
||||
/// Is it the default value of line-height?
|
||||
///
|
||||
/// (using match because it generates less code than)
|
||||
pub fn is_default_line_height(&self) -> bool {
|
||||
match *self {
|
||||
PropertyDeclaration::LineHeight(longhands::line_height::SpecifiedValue::Normal) => true,
|
||||
PropertyDeclaration::LineHeight(LineHeight::Normal) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
|||
for side in PHYSICAL_SIDES)}"
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-width">
|
||||
use values::generics::rect::Rect;
|
||||
use values::specified::{AllowQuirks, BorderWidth};
|
||||
use values::specified::{AllowQuirks, BorderSideWidth};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
let rect = Rect::parse_with(context, input, |_, i| {
|
||||
BorderWidth::parse_quirky(context, i, AllowQuirks::Yes)
|
||||
BorderSideWidth::parse_quirky(context, i, AllowQuirks::Yes)
|
||||
})?;
|
||||
Ok(expanded! {
|
||||
border_top_width: rect.0,
|
||||
|
@ -46,8 +46,8 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
|||
pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<(specified::CSSColor,
|
||||
specified::BorderStyle,
|
||||
specified::BorderWidth), ()> {
|
||||
use values::specified::{CSSColor, BorderStyle, BorderWidth};
|
||||
specified::BorderSideWidth), ()> {
|
||||
use values::specified::{CSSColor, BorderStyle, BorderSideWidth};
|
||||
let _unused = context;
|
||||
let mut color = None;
|
||||
let mut style = None;
|
||||
|
@ -69,7 +69,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
}
|
||||
}
|
||||
if width.is_none() {
|
||||
if let Ok(value) = input.try(|i| BorderWidth::parse(context, i)) {
|
||||
if let Ok(value) = input.try(|i| BorderSideWidth::parse(context, i)) {
|
||||
width = Some(value);
|
||||
any = true;
|
||||
continue
|
||||
|
@ -80,7 +80,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
if any {
|
||||
Ok((color.unwrap_or_else(|| CSSColor::currentcolor()),
|
||||
style.unwrap_or(BorderStyle::none),
|
||||
width.unwrap_or(BorderWidth::Medium)))
|
||||
width.unwrap_or(BorderSideWidth::Medium)))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
${'font-language-override' if product == 'gecko' or data.testing else ''}
|
||||
${'font-feature-settings' if product == 'gecko' or data.testing else ''}"
|
||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
|
||||
use parser::Parse;
|
||||
use properties::longhands::{font_family, font_style, font_weight, font_stretch};
|
||||
use properties::longhands::{font_size, line_height, font_variant_caps};
|
||||
use properties::longhands::{font_size, font_variant_caps};
|
||||
#[cfg(feature = "gecko")]
|
||||
use properties::longhands::system_font::SystemFont;
|
||||
use values::specified::text::LineHeight;
|
||||
|
||||
<%
|
||||
gecko_sub_properties = "kerning language_override size_adjust \
|
||||
|
@ -50,7 +52,7 @@
|
|||
${name}: ${name}::SpecifiedValue::system_font(sys),
|
||||
% endfor
|
||||
// line-height is just reset to initial
|
||||
line_height: line_height::get_initial_specified_value(),
|
||||
line_height: LineHeight::normal(),
|
||||
})
|
||||
}
|
||||
% endif
|
||||
|
@ -98,7 +100,7 @@
|
|||
return Err(())
|
||||
}
|
||||
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
|
||||
Some(try!(line_height::parse(context, input)))
|
||||
Some(try!(LineHeight::parse(context, input)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -107,7 +109,7 @@
|
|||
% for name in "style weight stretch size variant_caps".split():
|
||||
font_${name}: unwrap_or_initial!(font_${name}, ${name}),
|
||||
% endfor
|
||||
line_height: unwrap_or_initial!(line_height),
|
||||
line_height: line_height.unwrap_or(LineHeight::normal()),
|
||||
font_family: family,
|
||||
% if product == "gecko" or data.testing:
|
||||
% for name in gecko_sub_properties:
|
||||
|
@ -169,12 +171,9 @@
|
|||
|
||||
self.font_size.to_css(dest)?;
|
||||
|
||||
match *self.line_height {
|
||||
line_height::SpecifiedValue::Normal => {},
|
||||
_ => {
|
||||
dest.write_str("/")?;
|
||||
self.line_height.to_css(dest)?;
|
||||
}
|
||||
if *self.line_height != LineHeight::normal() {
|
||||
dest.write_str("/")?;
|
||||
self.line_height.to_css(dest)?;
|
||||
}
|
||||
|
||||
dest.write_str(" ")?;
|
||||
|
@ -197,7 +196,7 @@
|
|||
all = false;
|
||||
}
|
||||
% endfor
|
||||
if self.line_height != &line_height::get_initial_specified_value() {
|
||||
if self.line_height != &LineHeight::normal() {
|
||||
all = false
|
||||
}
|
||||
if all {
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
use values::computed::{Number, NumberOrPercentage};
|
||||
use values::computed::length::LengthOrPercentage;
|
||||
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
||||
use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
|
||||
use values::generics::border::BorderImageSlice as GenericBorderImageSlice;
|
||||
use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide;
|
||||
use values::generics::border::BorderRadius as GenericBorderRadius;
|
||||
use values::generics::rect::Rect;
|
||||
|
||||
/// A computed value for the `border-image-width` property.
|
||||
pub type BorderImageWidth = Rect<BorderImageWidthSide>;
|
||||
pub type BorderImageWidth = Rect<BorderImageSideWidth>;
|
||||
|
||||
/// A computed value for a single side of a `border-image-width` property.
|
||||
pub type BorderImageWidthSide = GenericBorderImageWidthSide<LengthOrPercentage, Number>;
|
||||
pub type BorderImageSideWidth = GenericBorderImageSideWidth<LengthOrPercentage, Number>;
|
||||
|
||||
/// A computed value for the `border-image-slice` property.
|
||||
pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>;
|
||||
|
@ -27,10 +27,10 @@ pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
|
|||
/// A computed value for the `border-*-radius` longhand properties.
|
||||
pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
|
||||
|
||||
impl BorderImageWidthSide {
|
||||
impl BorderImageSideWidth {
|
||||
/// Returns `1`.
|
||||
#[inline]
|
||||
pub fn one() -> Self {
|
||||
GenericBorderImageWidthSide::Number(1.)
|
||||
GenericBorderImageSideWidth::Number(1.)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,6 +222,13 @@ pub enum LengthOrPercentage {
|
|||
Calc(CalcLengthOrPercentage),
|
||||
}
|
||||
|
||||
impl From<Au> for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn from(length: Au) -> Self {
|
||||
LengthOrPercentage::Length(length)
|
||||
}
|
||||
}
|
||||
|
||||
impl LengthOrPercentage {
|
||||
#[inline]
|
||||
#[allow(missing_docs)]
|
||||
|
|
|
@ -24,7 +24,7 @@ use super::specified;
|
|||
pub use app_units::Au;
|
||||
pub use cssparser::Color as CSSColor;
|
||||
pub use self::background::BackgroundSize;
|
||||
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageWidthSide};
|
||||
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
||||
pub use self::border::{BorderRadius, BorderCornerRadius};
|
||||
pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect};
|
||||
pub use self::rect::LengthOrNumberRect;
|
||||
|
@ -38,6 +38,7 @@ pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrP
|
|||
pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone};
|
||||
pub use self::length::{MaxLength, MozLength};
|
||||
pub use self::position::Position;
|
||||
pub use self::text::{LetterSpacing, LineHeight, WordSpacing};
|
||||
pub use self::transform::TransformOrigin;
|
||||
|
||||
pub mod background;
|
||||
|
@ -47,6 +48,7 @@ pub mod image;
|
|||
pub mod length;
|
||||
pub mod position;
|
||||
pub mod rect;
|
||||
pub mod text;
|
||||
pub mod transform;
|
||||
|
||||
/// A `Context` is all the data a specified value could ever need to compute
|
||||
|
|
58
components/style/values/computed/text.rs
Normal file
58
components/style/values/computed/text.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! Computed types for text properties.
|
||||
|
||||
use app_units::Au;
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::CSSFloat;
|
||||
use values::computed::length::{Length, LengthOrPercentage};
|
||||
use values::generics::text::{LineHeight as GenericLineHeight, Spacing};
|
||||
|
||||
/// A computed value for the `letter-spacing` property.
|
||||
pub type LetterSpacing = Spacing<Length>;
|
||||
|
||||
/// A computed value for the `word-spacing` property.
|
||||
pub type WordSpacing = Spacing<LengthOrPercentage>;
|
||||
|
||||
/// A computed value for the `line-height` property.
|
||||
pub type LineHeight = GenericLineHeight<CSSFloat, Au>;
|
||||
|
||||
impl Animatable for LineHeight {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
match (*self, *other) {
|
||||
(GenericLineHeight::Length(ref this), GenericLineHeight::Length(ref other)) => {
|
||||
this.add_weighted(other, self_portion, other_portion).map(GenericLineHeight::Length)
|
||||
},
|
||||
(GenericLineHeight::Number(ref this), GenericLineHeight::Number(ref other)) => {
|
||||
this.add_weighted(other, self_portion, other_portion).map(GenericLineHeight::Number)
|
||||
},
|
||||
(GenericLineHeight::Normal, GenericLineHeight::Normal) => {
|
||||
Ok(GenericLineHeight::Normal)
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
(GenericLineHeight::MozBlockHeight, GenericLineHeight::MozBlockHeight) => {
|
||||
Ok(GenericLineHeight::MozBlockHeight)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
match (*self, *other) {
|
||||
(GenericLineHeight::Length(ref this), GenericLineHeight::Length(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(GenericLineHeight::Number(ref this), GenericLineHeight::Number(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
(GenericLineHeight::Normal, GenericLineHeight::Normal) => Ok(0.),
|
||||
#[cfg(feature = "gecko")]
|
||||
(GenericLineHeight::MozBlockHeight, GenericLineHeight::MozBlockHeight) => Ok(0.),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ use values::generics::rect::Rect;
|
|||
/// A generic value for a single side of a `border-image-width` property.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
|
||||
pub enum BorderImageWidthSide<LengthOrPercentage, Number> {
|
||||
pub enum BorderImageSideWidth<LengthOrPercentage, Number> {
|
||||
/// `<length-or-percentage>`
|
||||
Length(LengthOrPercentage),
|
||||
/// `<number>`
|
||||
|
@ -52,16 +52,16 @@ pub struct BorderRadius<LengthOrPercentage> {
|
|||
/// A generic value for `border-*-radius` longhand properties.
|
||||
pub struct BorderCornerRadius<L>(pub Size2D<L>);
|
||||
|
||||
impl<L, N> ToCss for BorderImageWidthSide<L, N>
|
||||
impl<L, N> ToCss for BorderImageSideWidth<L, N>
|
||||
where L: ToCss, N: ToCss,
|
||||
{
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write
|
||||
{
|
||||
match *self {
|
||||
BorderImageWidthSide::Length(ref length) => length.to_css(dest),
|
||||
BorderImageWidthSide::Number(ref number) => number.to_css(dest),
|
||||
BorderImageWidthSide::Auto => dest.write_str("auto"),
|
||||
BorderImageSideWidth::Length(ref length) => length.to_css(dest),
|
||||
BorderImageSideWidth::Number(ref number) => number.to_css(dest),
|
||||
BorderImageSideWidth::Auto => dest.write_str("auto"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ pub mod grid;
|
|||
pub mod image;
|
||||
pub mod position;
|
||||
pub mod rect;
|
||||
pub mod text;
|
||||
pub mod transform;
|
||||
|
||||
// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
|
||||
|
|
129
components/style/values/generics/text.rs
Normal file
129
components/style/values/generics/text.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! Generic types for text properties.
|
||||
|
||||
use app_units::Au;
|
||||
use cssparser::Parser;
|
||||
use parser::ParserContext;
|
||||
use properties::animated_properties::Animatable;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
/// A generic spacing value for the `letter-spacing` and `word-spacing` properties.alloc
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
|
||||
pub enum Spacing<Value> {
|
||||
/// `normal`
|
||||
Normal,
|
||||
/// `<value>`
|
||||
Value(Value),
|
||||
}
|
||||
|
||||
impl<Value> Spacing<Value> {
|
||||
/// Returns `normal`.
|
||||
#[inline]
|
||||
pub fn normal() -> Self {
|
||||
Spacing::Normal
|
||||
}
|
||||
|
||||
/// Parses.
|
||||
#[inline]
|
||||
pub fn parse_with<F>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
parse: F)
|
||||
-> Result<Self, ()>
|
||||
where F: FnOnce(&ParserContext, &mut Parser) -> Result<Value, ()>
|
||||
{
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(Spacing::Normal);
|
||||
}
|
||||
parse(context, input).map(Spacing::Value)
|
||||
}
|
||||
|
||||
/// Returns the spacing value, if not `normal`.
|
||||
#[inline]
|
||||
pub fn value(&self) -> Option<&Value> {
|
||||
match *self {
|
||||
Spacing::Normal => None,
|
||||
Spacing::Value(ref value) => Some(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Value> Animatable for Spacing<Value>
|
||||
where Value: Animatable + From<Au>,
|
||||
{
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
if let (&Spacing::Normal, &Spacing::Normal) = (self, other) {
|
||||
return Ok(Spacing::Normal);
|
||||
}
|
||||
let zero = Value::from(Au(0));
|
||||
let this = self.value().unwrap_or(&zero);
|
||||
let other = other.value().unwrap_or(&zero);
|
||||
this.add_weighted(other, self_portion, other_portion).map(Spacing::Value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||
let zero = Value::from(Au(0));
|
||||
let this = self.value().unwrap_or(&zero);
|
||||
let other = other.value().unwrap_or(&zero);
|
||||
this.compute_distance(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Value> ToCss for Spacing<Value>
|
||||
where Value: ToCss,
|
||||
{
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write
|
||||
{
|
||||
match *self {
|
||||
Spacing::Normal => dest.write_str("normal"),
|
||||
Spacing::Value(ref value) => value.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic value for the `line-height` property.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)]
|
||||
pub enum LineHeight<Number, LengthOrPercentage> {
|
||||
/// `normal`
|
||||
Normal,
|
||||
/// `-moz-block-height`
|
||||
#[cfg(feature = "gecko")]
|
||||
MozBlockHeight,
|
||||
/// `<number>`
|
||||
Number(Number),
|
||||
/// `<length-or-percentage>`
|
||||
Length(LengthOrPercentage),
|
||||
}
|
||||
|
||||
impl<N, L> LineHeight<N, L> {
|
||||
/// Returns `normal`.
|
||||
#[inline]
|
||||
pub fn normal() -> Self {
|
||||
LineHeight::Normal
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, L> ToCss for LineHeight<N, L>
|
||||
where N: ToCss, L: ToCss,
|
||||
{
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
match *self {
|
||||
LineHeight::Normal => dest.write_str("normal"),
|
||||
#[cfg(feature = "gecko")]
|
||||
LineHeight::MozBlockHeight => dest.write_str("-moz-block-height"),
|
||||
LineHeight::Number(ref number) => number.to_css(dest),
|
||||
LineHeight::Length(ref value) => value.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,21 +4,39 @@
|
|||
|
||||
//! Specified types for CSS values related to borders.
|
||||
|
||||
use app_units::Au;
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
||||
use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
|
||||
use values::generics::border::BorderImageSlice as GenericBorderImageSlice;
|
||||
use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide;
|
||||
use values::generics::border::BorderRadius as GenericBorderRadius;
|
||||
use values::generics::rect::Rect;
|
||||
use values::specified::{Number, NumberOrPercentage};
|
||||
use values::specified::length::LengthOrPercentage;
|
||||
use values::specified::{AllowQuirks, Number, NumberOrPercentage};
|
||||
use values::specified::length::{Length, LengthOrPercentage};
|
||||
|
||||
/// A specified value for a single side of the `border-width` property.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
||||
pub enum BorderSideWidth {
|
||||
/// `thin`
|
||||
Thin,
|
||||
/// `medium`
|
||||
Medium,
|
||||
/// `thick`
|
||||
Thick,
|
||||
/// `<length>`
|
||||
Length(Length),
|
||||
}
|
||||
|
||||
/// A specified value for the `border-image-width` property.
|
||||
pub type BorderImageWidth = Rect<BorderImageWidthSide>;
|
||||
pub type BorderImageWidth = Rect<BorderImageSideWidth>;
|
||||
|
||||
/// A specified value for a single side of a `border-image-width` property.
|
||||
pub type BorderImageWidthSide = GenericBorderImageWidthSide<LengthOrPercentage, Number>;
|
||||
pub type BorderImageSideWidth = GenericBorderImageSideWidth<LengthOrPercentage, Number>;
|
||||
|
||||
/// A specified value for the `border-image-slice` property.
|
||||
pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>;
|
||||
|
@ -29,26 +47,85 @@ pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
|
|||
/// A specified value for the `border-*-radius` longhand properties.
|
||||
pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
|
||||
|
||||
impl BorderImageWidthSide {
|
||||
/// Returns `1`.
|
||||
#[inline]
|
||||
pub fn one() -> Self {
|
||||
GenericBorderImageWidthSide::Number(Number::new(1.))
|
||||
impl BorderSideWidth {
|
||||
/// Parses, with quirks.
|
||||
pub fn parse_quirky(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()>
|
||||
{
|
||||
if let Ok(length) = input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) {
|
||||
return Ok(BorderSideWidth::Length(length));
|
||||
}
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
"thin" => Ok(BorderSideWidth::Thin),
|
||||
"medium" => Ok(BorderSideWidth::Medium),
|
||||
"thick" => Ok(BorderSideWidth::Thick),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for BorderImageWidthSide {
|
||||
impl Parse for BorderSideWidth {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for BorderSideWidth {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
BorderSideWidth::Thin => dest.write_str("thin"),
|
||||
BorderSideWidth::Medium => dest.write_str("medium"),
|
||||
BorderSideWidth::Thick => dest.write_str("thick"),
|
||||
BorderSideWidth::Length(ref length) => length.to_css(dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for BorderSideWidth {
|
||||
type ComputedValue = Au;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
// We choose the pixel length of the keyword values the same as both spec and gecko.
|
||||
// Spec: https://drafts.csswg.org/css-backgrounds-3/#line-width
|
||||
// Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=1312155#c0
|
||||
match *self {
|
||||
BorderSideWidth::Thin => Length::from_px(1.).to_computed_value(context),
|
||||
BorderSideWidth::Medium => Length::from_px(3.).to_computed_value(context),
|
||||
BorderSideWidth::Thick => Length::from_px(5.).to_computed_value(context),
|
||||
BorderSideWidth::Length(ref length) => length.to_computed_value(context)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
BorderSideWidth::Length(ToComputedValue::from_computed_value(computed))
|
||||
}
|
||||
}
|
||||
|
||||
impl BorderImageSideWidth {
|
||||
/// Returns `1`.
|
||||
#[inline]
|
||||
pub fn one() -> Self {
|
||||
GenericBorderImageSideWidth::Number(Number::new(1.))
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for BorderImageSideWidth {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
||||
return Ok(GenericBorderImageWidthSide::Auto);
|
||||
return Ok(GenericBorderImageSideWidth::Auto);
|
||||
}
|
||||
|
||||
if let Ok(len) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||
return Ok(GenericBorderImageWidthSide::Length(len));
|
||||
return Ok(GenericBorderImageSideWidth::Length(len));
|
||||
}
|
||||
|
||||
let num = Number::parse_non_negative(context, input)?;
|
||||
Ok(GenericBorderImageWidthSide::Number(num))
|
||||
Ok(GenericBorderImageSideWidth::Number(num))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
//! TODO(emilio): Enhance docs.
|
||||
|
||||
use Namespace;
|
||||
use app_units::Au;
|
||||
use context::QuirksMode;
|
||||
use cssparser::{self, Parser, Token, serialize_identifier};
|
||||
use itoa;
|
||||
|
@ -32,7 +31,7 @@ use values::specified::calc::CalcNode;
|
|||
pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
|
||||
pub use self::background::BackgroundSize;
|
||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||
pub use self::border::{BorderImageWidthSide, BorderRadius};
|
||||
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth};
|
||||
pub use self::color::Color;
|
||||
pub use self::rect::LengthOrNumberRect;
|
||||
pub use super::generics::grid::GridLine;
|
||||
|
@ -44,6 +43,7 @@ pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercent
|
|||
pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength};
|
||||
pub use self::length::{MaxLength, MozLength};
|
||||
pub use self::position::{Position, PositionComponent};
|
||||
pub use self::text::{LetterSpacing, LineHeight, WordSpacing};
|
||||
pub use self::transform::TransformOrigin;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -58,6 +58,7 @@ pub mod image;
|
|||
pub mod length;
|
||||
pub mod position;
|
||||
pub mod rect;
|
||||
pub mod text;
|
||||
pub mod transform;
|
||||
|
||||
/// Common handling for the specified value CSS url() values.
|
||||
|
@ -432,92 +433,6 @@ impl Angle {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_border_width(context: &ParserContext, input: &mut Parser) -> Result<Length, ()> {
|
||||
input.try(|i| Length::parse_non_negative(context, i)).or_else(|()| {
|
||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
"thin" => Ok(Length::from_px(1.)),
|
||||
"medium" => Ok(Length::from_px(3.)),
|
||||
"thick" => Ok(Length::from_px(5.)),
|
||||
_ => Err(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[allow(missing_docs)]
|
||||
pub enum BorderWidth {
|
||||
Thin,
|
||||
Medium,
|
||||
Thick,
|
||||
Width(Length),
|
||||
}
|
||||
|
||||
impl Parse for BorderWidth {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<BorderWidth, ()> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl BorderWidth {
|
||||
/// Parses a border width, allowing quirks.
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<BorderWidth, ()> {
|
||||
match input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) {
|
||||
Ok(length) => Ok(BorderWidth::Width(length)),
|
||||
Err(_) => match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
"thin" => Ok(BorderWidth::Thin),
|
||||
"medium" => Ok(BorderWidth::Medium),
|
||||
"thick" => Ok(BorderWidth::Thick),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BorderWidth {
|
||||
#[allow(missing_docs)]
|
||||
pub fn from_length(length: Length) -> Self {
|
||||
BorderWidth::Width(length)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for BorderWidth {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
BorderWidth::Thin => dest.write_str("thin"),
|
||||
BorderWidth::Medium => dest.write_str("medium"),
|
||||
BorderWidth::Thick => dest.write_str("thick"),
|
||||
BorderWidth::Width(ref length) => length.to_css(dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for BorderWidth {
|
||||
type ComputedValue = Au;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
// We choose the pixel length of the keyword values the same as both spec and gecko.
|
||||
// Spec: https://drafts.csswg.org/css-backgrounds-3/#line-width
|
||||
// Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=1312155#c0
|
||||
match *self {
|
||||
BorderWidth::Thin => Length::from_px(1.).to_computed_value(context),
|
||||
BorderWidth::Medium => Length::from_px(3.).to_computed_value(context),
|
||||
BorderWidth::Thick => Length::from_px(5.).to_computed_value(context),
|
||||
BorderWidth::Width(ref length) => length.to_computed_value(context)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
BorderWidth::Width(ToComputedValue::from_computed_value(computed))
|
||||
}
|
||||
}
|
||||
|
||||
// The integer values here correspond to the border conflict resolution rules in CSS 2.1 §
|
||||
// 17.6.2.1. Higher values override lower values.
|
||||
define_numbered_css_keyword_enum! { BorderStyle:
|
||||
|
|
119
components/style/values/specified/text.rs
Normal file
119
components/style/values/specified/text.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! Specified types for text properties.
|
||||
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::ascii::AsciiExt;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::text::LineHeight as ComputedLineHeight;
|
||||
use values::generics::text::{LineHeight as GenericLineHeight, Spacing};
|
||||
use values::specified::{AllowQuirks, Number};
|
||||
use values::specified::length::{FontRelativeLength, Length, LengthOrPercentage, NoCalcLength};
|
||||
|
||||
/// A specified value for the `letter-spacing` property.
|
||||
pub type LetterSpacing = Spacing<Length>;
|
||||
|
||||
/// A specified value for the `word-spacing` property.
|
||||
pub type WordSpacing = Spacing<LengthOrPercentage>;
|
||||
|
||||
/// A specified value for the `line-height` property.
|
||||
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;
|
||||
|
||||
impl Parse for LetterSpacing {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
Spacing::parse_with(context, input, |c, i| {
|
||||
Length::parse_quirky(c, i, AllowQuirks::Yes)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for WordSpacing {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
Spacing::parse_with(context, input, |c, i| {
|
||||
LengthOrPercentage::parse_quirky(c, i, AllowQuirks::Yes)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for LineHeight {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) {
|
||||
return Ok(GenericLineHeight::Number(number))
|
||||
}
|
||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||
return Ok(GenericLineHeight::Length(lop))
|
||||
}
|
||||
match &input.expect_ident()? {
|
||||
ident if ident.eq_ignore_ascii_case("normal") => {
|
||||
Ok(GenericLineHeight::Normal)
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
|
||||
Ok(GenericLineHeight::MozBlockHeight)
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for LineHeight {
|
||||
type ComputedValue = ComputedLineHeight;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
GenericLineHeight::Normal => {
|
||||
GenericLineHeight::Normal
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
GenericLineHeight::MozBlockHeight => {
|
||||
GenericLineHeight::MozBlockHeight
|
||||
},
|
||||
GenericLineHeight::Number(number) => {
|
||||
GenericLineHeight::Number(number.to_computed_value(context))
|
||||
},
|
||||
GenericLineHeight::Length(LengthOrPercentage::Length(ref length)) => {
|
||||
GenericLineHeight::Length(length.to_computed_value(context))
|
||||
},
|
||||
GenericLineHeight::Length(LengthOrPercentage::Percentage(p)) => {
|
||||
let font_relative_length =
|
||||
Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(p.0)));
|
||||
GenericLineHeight::Length(font_relative_length.to_computed_value(context))
|
||||
},
|
||||
GenericLineHeight::Length(LengthOrPercentage::Calc(ref calc)) => {
|
||||
let computed_calc = calc.to_computed_value(context);
|
||||
let font_relative_length =
|
||||
Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(computed_calc.percentage())));
|
||||
let absolute_length = computed_calc.unclamped_length();
|
||||
let computed_length = computed_calc.clamping_mode.clamp(
|
||||
absolute_length + font_relative_length.to_computed_value(context)
|
||||
);
|
||||
GenericLineHeight::Length(computed_length)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
match *computed {
|
||||
GenericLineHeight::Normal => {
|
||||
GenericLineHeight::Normal
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
GenericLineHeight::MozBlockHeight => {
|
||||
GenericLineHeight::MozBlockHeight
|
||||
},
|
||||
GenericLineHeight::Number(ref number) => {
|
||||
GenericLineHeight::Number(Number::from_computed_value(number))
|
||||
},
|
||||
GenericLineHeight::Length(ref length) => {
|
||||
GenericLineHeight::Length(LengthOrPercentage::Length(
|
||||
NoCalcLength::from_computed_value(length)
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1946,7 +1946,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(declarations:
|
|||
use style::properties::longhands::border_spacing::SpecifiedValue as BorderSpacing;
|
||||
use style::properties::longhands::height::SpecifiedValue as Height;
|
||||
use style::properties::longhands::width::SpecifiedValue as Width;
|
||||
use style::values::specified::BorderWidth;
|
||||
use style::values::specified::BorderSideWidth;
|
||||
use style::values::specified::MozLength;
|
||||
use style::values::specified::length::{NoCalcLength, LengthOrPercentage};
|
||||
|
||||
|
@ -1956,10 +1956,10 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(declarations:
|
|||
let prop = match_wrap_declared! { long,
|
||||
Height => Height(MozLength::LengthOrPercentageOrAuto(nocalc.into())),
|
||||
Width => Width(MozLength::LengthOrPercentageOrAuto(nocalc.into())),
|
||||
BorderTopWidth => BorderWidth::Width(nocalc.into()),
|
||||
BorderRightWidth => BorderWidth::Width(nocalc.into()),
|
||||
BorderBottomWidth => BorderWidth::Width(nocalc.into()),
|
||||
BorderLeftWidth => BorderWidth::Width(nocalc.into()),
|
||||
BorderTopWidth => BorderSideWidth::Length(nocalc.into()),
|
||||
BorderRightWidth => BorderSideWidth::Length(nocalc.into()),
|
||||
BorderBottomWidth => BorderSideWidth::Length(nocalc.into()),
|
||||
BorderLeftWidth => BorderSideWidth::Length(nocalc.into()),
|
||||
MarginTop => nocalc.into(),
|
||||
MarginRight => nocalc.into(),
|
||||
MarginBottom => nocalc.into(),
|
||||
|
|
|
@ -3,27 +3,27 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use parsing::parse;
|
||||
use style::values::generics::text::Spacing;
|
||||
|
||||
#[test]
|
||||
fn negative_letter_spacing_should_parse_properly() {
|
||||
use style::properties::longhands::letter_spacing;
|
||||
use style::properties::longhands::letter_spacing::SpecifiedValue;
|
||||
use style::values::specified::length::{Length, NoCalcLength, FontRelativeLength};
|
||||
|
||||
let negative_value = parse_longhand!(letter_spacing, "-0.5em");
|
||||
let expected = SpecifiedValue::Specified(Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(-0.5))));
|
||||
let expected = Spacing::Value(Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(-0.5))));
|
||||
assert_eq!(negative_value, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_word_spacing_should_parse_properly() {
|
||||
use style::properties::longhands::word_spacing;
|
||||
use style::properties::longhands::word_spacing::SpecifiedValue;
|
||||
use style::values::specified::length::{NoCalcLength, LengthOrPercentage, FontRelativeLength};
|
||||
|
||||
let negative_value = parse_longhand!(word_spacing, "-0.5em");
|
||||
let expected = SpecifiedValue::Specified(LengthOrPercentage::Length(NoCalcLength::FontRelative(
|
||||
FontRelativeLength::Em(-0.5))));
|
||||
let expected = Spacing::Value(LengthOrPercentage::Length(
|
||||
NoCalcLength::FontRelative(FontRelativeLength::Em(-0.5))
|
||||
));
|
||||
assert_eq!(negative_value, expected);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use style::properties::longhands::outline_color::computed_value::T as ComputedCo
|
|||
use style::properties::parse_property_declaration_list;
|
||||
use style::values::{RGBA, Auto};
|
||||
use style::values::CustomIdent;
|
||||
use style::values::specified::{BorderStyle, BorderWidth, CSSColor, Length, LengthOrPercentage};
|
||||
use style::values::specified::{BorderStyle, BorderSideWidth, CSSColor, Length, LengthOrPercentage};
|
||||
use style::values::specified::{LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent};
|
||||
use style::values::specified::{NoCalcLength, PositionComponent};
|
||||
use style::values::specified::position::Y;
|
||||
|
@ -221,8 +221,8 @@ mod shorthand_serialization {
|
|||
properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
|
||||
|
||||
let px_30 = BorderWidth::from_length(Length::from_px(30f32));
|
||||
let px_10 = BorderWidth::from_length(Length::from_px(10f32));
|
||||
let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
|
||||
let px_10 = BorderSideWidth::Length(Length::from_px(10f32));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
|
||||
|
@ -255,7 +255,7 @@ mod shorthand_serialization {
|
|||
properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
|
||||
|
||||
let px_30 = BorderWidth::from_length(Length::from_px(30f32));
|
||||
let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
|
||||
|
@ -295,11 +295,11 @@ mod shorthand_serialization {
|
|||
fn border_width_should_serialize_correctly() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let top_px = BorderWidth::from_length(Length::from_px(10f32));
|
||||
let bottom_px = BorderWidth::from_length(Length::from_px(10f32));
|
||||
let top_px = BorderSideWidth::Length(Length::from_px(10f32));
|
||||
let bottom_px = BorderSideWidth::Length(Length::from_px(10f32));
|
||||
|
||||
let right_px = BorderWidth::from_length(Length::from_px(15f32));
|
||||
let left_px = BorderWidth::from_length(Length::from_px(15f32));
|
||||
let right_px = BorderSideWidth::Length(Length::from_px(15f32));
|
||||
let left_px = BorderSideWidth::Length(Length::from_px(15f32));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(top_px));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(right_px));
|
||||
|
@ -314,10 +314,10 @@ mod shorthand_serialization {
|
|||
fn border_width_with_keywords_should_serialize_correctly() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let top_px = BorderWidth::Thin;
|
||||
let right_px = BorderWidth::Medium;
|
||||
let bottom_px = BorderWidth::Thick;
|
||||
let left_px = BorderWidth::from_length(Length::from_px(15f32));
|
||||
let top_px = BorderSideWidth::Thin;
|
||||
let right_px = BorderSideWidth::Medium;
|
||||
let bottom_px = BorderSideWidth::Thick;
|
||||
let left_px = BorderSideWidth::Length(Length::from_px(15f32));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(top_px));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(right_px));
|
||||
|
@ -403,7 +403,7 @@ mod shorthand_serialization {
|
|||
fn directional_border_should_show_all_properties_when_values_are_set() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let width = BorderWidth::from_length(Length::from_px(4f32));
|
||||
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
||||
let style = BorderStyle::solid;
|
||||
let color = CSSColor {
|
||||
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)),
|
||||
|
@ -418,8 +418,8 @@ mod shorthand_serialization {
|
|||
assert_eq!(serialization, "border-top: 4px solid rgb(255, 0, 0);");
|
||||
}
|
||||
|
||||
fn get_border_property_values() -> (BorderWidth, BorderStyle, CSSColor) {
|
||||
(BorderWidth::from_length(Length::from_px(4f32)),
|
||||
fn get_border_property_values() -> (BorderSideWidth, BorderStyle, CSSColor) {
|
||||
(BorderSideWidth::Length(Length::from_px(4f32)),
|
||||
BorderStyle::solid,
|
||||
CSSColor::currentcolor())
|
||||
}
|
||||
|
@ -523,7 +523,6 @@ mod shorthand_serialization {
|
|||
}
|
||||
|
||||
mod outline {
|
||||
use style::properties::longhands::outline_width::SpecifiedValue as WidthContainer;
|
||||
use style::values::Either;
|
||||
use super::*;
|
||||
|
||||
|
@ -531,7 +530,7 @@ mod shorthand_serialization {
|
|||
fn outline_should_show_all_properties_when_set() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let width = WidthContainer(Length::from_px(4f32));
|
||||
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
||||
let style = Either::Second(BorderStyle::solid);
|
||||
let color = CSSColor {
|
||||
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)),
|
||||
|
@ -550,7 +549,7 @@ mod shorthand_serialization {
|
|||
fn outline_should_serialize_correctly_when_style_is_auto() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let width = WidthContainer(Length::from_px(4f32));
|
||||
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
||||
let style = Either::First(Auto);
|
||||
let color = CSSColor {
|
||||
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)),
|
||||
|
|
|
@ -4,22 +4,22 @@
|
|||
|
||||
use app_units::Au;
|
||||
use style::properties::PropertyDeclaration;
|
||||
use style::properties::longhands::border_top_width;
|
||||
use style::values::specified::{AbsoluteLength, Length, NoCalcLength, ViewportPercentageLength};
|
||||
use style::values::specified::border::BorderSideWidth;
|
||||
use style_traits::HasViewportPercentage;
|
||||
|
||||
#[test]
|
||||
fn has_viewport_percentage_for_specified_value() {
|
||||
//TODO: test all specified value with a HasViewportPercentage impl
|
||||
let pvw = PropertyDeclaration::BorderTopWidth(
|
||||
border_top_width::SpecifiedValue::from_length(
|
||||
BorderSideWidth::Length(
|
||||
Length::NoCalc(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(100.)))
|
||||
)
|
||||
);
|
||||
assert!(pvw.has_viewport_percentage());
|
||||
|
||||
let pabs = PropertyDeclaration::BorderTopWidth(
|
||||
border_top_width::SpecifiedValue::from_length(
|
||||
BorderSideWidth::Length(
|
||||
Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(Au(100).to_f32_px())))
|
||||
)
|
||||
);
|
||||
|
|
|
@ -45,15 +45,6 @@
|
|||
[outline-color: invert]
|
||||
expected: FAIL
|
||||
|
||||
[outline-width: thin]
|
||||
expected: FAIL
|
||||
|
||||
[outline-width: medium]
|
||||
expected: FAIL
|
||||
|
||||
[outline-width: thick]
|
||||
expected: FAIL
|
||||
|
||||
[page-break-after: auto]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue