mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
style: Implement ToCss for CalcNode.
We'll use `CalcNode` as the specified value representation for <length> and <length-percentage> values, so they'll have to implement ToCss. There's one minor issue (two calls to to_css() instead of to_css_impl() which are addressed later in the series). Differential Revision: https://phabricator.services.mozilla.com/D63395
This commit is contained in:
parent
c52bae1923
commit
869553357d
3 changed files with 144 additions and 5 deletions
|
@ -287,6 +287,19 @@ impl PartialOrd for CalcNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CalcNode {
|
impl CalcNode {
|
||||||
|
fn is_simple_negative(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Self::Length(ref l) => l.is_negative(),
|
||||||
|
Self::Percentage(n) |
|
||||||
|
Self::Number(n) => n < 0.,
|
||||||
|
Self::Angle(ref a) => a.degrees() < 0.,
|
||||||
|
Self::Time(ref t) => t.seconds() < 0.,
|
||||||
|
Self::MinMax(..) |
|
||||||
|
Self::Sum(..) |
|
||||||
|
Self::Clamp { .. } => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn negate(&mut self) {
|
fn negate(&mut self) {
|
||||||
self.mul_by(-1.);
|
self.mul_by(-1.);
|
||||||
}
|
}
|
||||||
|
@ -1022,4 +1035,93 @@ impl CalcNode {
|
||||||
Err(()) => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
Err(()) => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_css_impl<W>(&self, dest: &mut CssWriter<W>, is_outermost: bool) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
let write_closing_paren = match *self {
|
||||||
|
Self::MinMax(_, op) => {
|
||||||
|
dest.write_str(match op {
|
||||||
|
MinMaxOp::Max => "max(",
|
||||||
|
MinMaxOp::Min => "min(",
|
||||||
|
})?;
|
||||||
|
true
|
||||||
|
},
|
||||||
|
Self::Clamp { .. } => {
|
||||||
|
dest.write_str("clamp(")?;
|
||||||
|
true
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
if is_outermost {
|
||||||
|
dest.write_str("calc(")?;
|
||||||
|
}
|
||||||
|
is_outermost
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Self::MinMax(ref children, _) => {
|
||||||
|
let mut first = true;
|
||||||
|
for child in &**children {
|
||||||
|
if !first {
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
child.to_css_impl(dest, false)?;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Self::Sum(ref children) => {
|
||||||
|
let mut first = true;
|
||||||
|
for child in &**children {
|
||||||
|
if !first {
|
||||||
|
if child.is_simple_negative() {
|
||||||
|
dest.write_str(" - ")?;
|
||||||
|
let mut c = child.clone();
|
||||||
|
c.negate();
|
||||||
|
c.to_css(dest)?;
|
||||||
|
} else {
|
||||||
|
dest.write_str(" + ")?;
|
||||||
|
child.to_css(dest)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
child.to_css_impl(dest, false)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Self::Clamp {
|
||||||
|
ref min,
|
||||||
|
ref center,
|
||||||
|
ref max,
|
||||||
|
} => {
|
||||||
|
min.to_css_impl(dest, false)?;
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
center.to_css_impl(dest, false)?;
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
max.to_css_impl(dest, false)?;
|
||||||
|
},
|
||||||
|
Self::Length(ref l) => l.to_css(dest)?,
|
||||||
|
Self::Number(ref n) => n.to_css(dest)?,
|
||||||
|
Self::Percentage(p) => crate::values::serialize_percentage(p, dest)?,
|
||||||
|
Self::Angle(ref a) => a.to_css(dest)?,
|
||||||
|
Self::Time(ref t) => t.to_css(dest)?,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if write_closing_paren {
|
||||||
|
dest.write_str(")")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for CalcNode {
|
||||||
|
/// <https://drafts.csswg.org/css-values/#calc-serialize>
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
self.to_css_impl(dest, /* is_outermost = */ true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,16 @@ impl FontRelativeLength {
|
||||||
FontRelativeLength::Em(v) |
|
FontRelativeLength::Em(v) |
|
||||||
FontRelativeLength::Ex(v) |
|
FontRelativeLength::Ex(v) |
|
||||||
FontRelativeLength::Ch(v) |
|
FontRelativeLength::Ch(v) |
|
||||||
FontRelativeLength::Rem(v) => v == 0.0,
|
FontRelativeLength::Rem(v) => v == 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_negative(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
FontRelativeLength::Em(v) |
|
||||||
|
FontRelativeLength::Ex(v) |
|
||||||
|
FontRelativeLength::Ch(v) |
|
||||||
|
FontRelativeLength::Rem(v) => v < 0.,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +275,16 @@ impl ViewportPercentageLength {
|
||||||
ViewportPercentageLength::Vw(v) |
|
ViewportPercentageLength::Vw(v) |
|
||||||
ViewportPercentageLength::Vh(v) |
|
ViewportPercentageLength::Vh(v) |
|
||||||
ViewportPercentageLength::Vmin(v) |
|
ViewportPercentageLength::Vmin(v) |
|
||||||
ViewportPercentageLength::Vmax(v) => v == 0.0,
|
ViewportPercentageLength::Vmax(v) => v == 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_negative(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
ViewportPercentageLength::Vw(v) |
|
||||||
|
ViewportPercentageLength::Vh(v) |
|
||||||
|
ViewportPercentageLength::Vmin(v) |
|
||||||
|
ViewportPercentageLength::Vmax(v) => v < 0.,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,6 +388,18 @@ impl AbsoluteLength {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_negative(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
AbsoluteLength::Px(v) |
|
||||||
|
AbsoluteLength::In(v) |
|
||||||
|
AbsoluteLength::Cm(v) |
|
||||||
|
AbsoluteLength::Mm(v) |
|
||||||
|
AbsoluteLength::Q(v) |
|
||||||
|
AbsoluteLength::Pt(v) |
|
||||||
|
AbsoluteLength::Pc(v) => v < 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert this into a pixel value.
|
/// Convert this into a pixel value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_px(&self) -> CSSFloat {
|
pub fn to_px(&self) -> CSSFloat {
|
||||||
|
@ -484,6 +514,16 @@ impl Mul<CSSFloat> for NoCalcLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoCalcLength {
|
impl NoCalcLength {
|
||||||
|
/// Returns whether the value of this length without unit is less than zero.
|
||||||
|
pub fn is_negative(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
NoCalcLength::Absolute(v) => v.is_negative(),
|
||||||
|
NoCalcLength::FontRelative(v) => v.is_negative(),
|
||||||
|
NoCalcLength::ViewportPercentage(v) => v.is_negative(),
|
||||||
|
NoCalcLength::ServoCharacterWidth(c) => c.0 < 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a given absolute or relative dimension.
|
/// Parse a given absolute or relative dimension.
|
||||||
pub fn parse_dimension(
|
pub fn parse_dimension(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
|
|
|
@ -120,9 +120,6 @@ impl Percentage {
|
||||||
Token::Function(ref name) => {
|
Token::Function(ref name) => {
|
||||||
let function = CalcNode::math_function(name, location)?;
|
let function = CalcNode::math_function(name, location)?;
|
||||||
let value = CalcNode::parse_percentage(context, input, function)?;
|
let value = CalcNode::parse_percentage(context, input, function)?;
|
||||||
|
|
||||||
// TODO(emilio): -moz-image-rect is the only thing that uses
|
|
||||||
// the clamping mode... I guess we could disallow it...
|
|
||||||
Ok(Percentage {
|
Ok(Percentage {
|
||||||
value,
|
value,
|
||||||
calc_clamping_mode: Some(num_context),
|
calc_clamping_mode: Some(num_context),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue