mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #16229 - tomhoule:fix-lengths, r=emilio
style: Do not immediately convert absolute specified lengths <!-- Please describe your changes on the following line: --> This PR aims to solve issue #15729. I tried to follow the recommendations there as much as possible. This is my first attempt at contributing to Servo, so this will probably need a lot of input, although I'm eager to make it as polished as possible. - The base inaccuracy issue seems solved, as can be easily verified with the `console.log` based example in the issue. - Very basic unit tests were added. I have doubts mainly about the right way to represent these new enum variants for the various length units: 1. With new enum variants in `NoCalcLength` *and* newtypes (current solution) 2. With a `NoCalcLength::Absolute` variant that contains a new `AbsoluteLength` enum, but without newtypes 3. Same as solution 2 but with newtypes - I mostly cared about unit tests until now but will investigate other types of tests - Tests to check the clamping - Write a proper commit message Thanks for your time and feedback :) --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #15729. <!-- Either: --> - [X] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/16229) <!-- Reviewable:end -->
This commit is contained in:
commit
c8cd70f333
12 changed files with 161 additions and 51 deletions
|
@ -16,7 +16,7 @@ use std::ascii::AsciiExt;
|
|||
use std::ops::Mul;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
use super::{Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time};
|
||||
use super::{Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time, ToComputedValue};
|
||||
use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, HasViewportPercentage, None_, Normal};
|
||||
use values::ExtremumLength;
|
||||
use values::computed::{ComputedValueAsSpecified, Context};
|
||||
|
@ -202,14 +202,122 @@ impl CharacterWidth {
|
|||
}
|
||||
}
|
||||
|
||||
/// Same as Gecko
|
||||
const ABSOLUTE_LENGTH_MAX: i32 = (1 << 30);
|
||||
const ABSOLUTE_LENGTH_MIN: i32 = - (1 << 30);
|
||||
|
||||
/// Helper to convert a floating point length to application units
|
||||
fn to_au_round(length: CSSFloat, au_per_unit: CSSFloat) -> Au {
|
||||
Au(
|
||||
(length * au_per_unit)
|
||||
.min(ABSOLUTE_LENGTH_MAX as f32)
|
||||
.max(ABSOLUTE_LENGTH_MIN as f32)
|
||||
.round() as i32
|
||||
)
|
||||
}
|
||||
|
||||
/// Represents an absolute length with its unit
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum AbsoluteLength {
|
||||
/// An absolute length in pixels (px)
|
||||
Px(CSSFloat),
|
||||
/// An absolute length in inches (in)
|
||||
In(CSSFloat),
|
||||
/// An absolute length in centimeters (cm)
|
||||
Cm(CSSFloat),
|
||||
/// An absolute length in millimeters (mm)
|
||||
Mm(CSSFloat),
|
||||
/// An absolute length in quarter-millimeters (q)
|
||||
Q(CSSFloat),
|
||||
/// An absolute length in points (pt)
|
||||
Pt(CSSFloat),
|
||||
/// An absolute length in pica (pc)
|
||||
Pc(CSSFloat),
|
||||
}
|
||||
|
||||
impl AbsoluteLength {
|
||||
fn is_zero(&self) -> bool {
|
||||
match *self {
|
||||
AbsoluteLength::Px(0.)
|
||||
| AbsoluteLength::In(0.)
|
||||
| AbsoluteLength::Cm(0.)
|
||||
| AbsoluteLength::Mm(0.)
|
||||
| AbsoluteLength::Q(0.)
|
||||
| AbsoluteLength::Pt(0.)
|
||||
| AbsoluteLength::Pc(0.) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for AbsoluteLength {
|
||||
type ComputedValue = Au;
|
||||
|
||||
fn to_computed_value(&self, _: &Context) -> Au {
|
||||
Au::from(*self)
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &Au) -> AbsoluteLength {
|
||||
AbsoluteLength::Px(computed.to_f32_px())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AbsoluteLength> for Au {
|
||||
fn from(length: AbsoluteLength) -> Au {
|
||||
match length {
|
||||
AbsoluteLength::Px(value) => to_au_round(value, AU_PER_PX),
|
||||
AbsoluteLength::In(value) => to_au_round(value, AU_PER_IN),
|
||||
AbsoluteLength::Cm(value) => to_au_round(value, AU_PER_CM),
|
||||
AbsoluteLength::Mm(value) => to_au_round(value, AU_PER_MM),
|
||||
AbsoluteLength::Q(value) => to_au_round(value, AU_PER_Q),
|
||||
AbsoluteLength::Pt(value) => to_au_round(value, AU_PER_PT),
|
||||
AbsoluteLength::Pc(value) => to_au_round(value, AU_PER_PC),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for AbsoluteLength {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
AbsoluteLength::Px(length) => write!(dest, "{}px", length),
|
||||
AbsoluteLength::In(length) => write!(dest, "{}in", length),
|
||||
AbsoluteLength::Cm(length) => write!(dest, "{}cm", length),
|
||||
AbsoluteLength::Mm(length) => write!(dest, "{}mm", length),
|
||||
AbsoluteLength::Q(length) => write!(dest, "{}q", length),
|
||||
AbsoluteLength::Pt(length) => write!(dest, "{}pt", length),
|
||||
AbsoluteLength::Pc(length) => write!(dest, "{}pc", length),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<CSSFloat> for AbsoluteLength {
|
||||
type Output = AbsoluteLength;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, scalar: CSSFloat) -> AbsoluteLength {
|
||||
match self {
|
||||
AbsoluteLength::Px(v) => AbsoluteLength::Px(v * scalar),
|
||||
AbsoluteLength::In(v) => AbsoluteLength::In(v * scalar),
|
||||
AbsoluteLength::Cm(v) => AbsoluteLength::Cm(v * scalar),
|
||||
AbsoluteLength::Mm(v) => AbsoluteLength::Mm(v * scalar),
|
||||
AbsoluteLength::Q(v) => AbsoluteLength::Q(v * scalar),
|
||||
AbsoluteLength::Pt(v) => AbsoluteLength::Pt(v * scalar),
|
||||
AbsoluteLength::Pc(v) => AbsoluteLength::Pc(v * scalar),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A `<length>` without taking `calc` expressions into account
|
||||
///
|
||||
/// https://drafts.csswg.org/css-values/#lengths
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum NoCalcLength {
|
||||
/// An absolute length: https://drafts.csswg.org/css-values/#absolute-length
|
||||
Absolute(Au), // application units
|
||||
/// An absolute length
|
||||
///
|
||||
/// https://drafts.csswg.org/css-values/#absolute-length
|
||||
Absolute(AbsoluteLength),
|
||||
|
||||
/// A font-relative length:
|
||||
///
|
||||
|
@ -240,7 +348,7 @@ impl HasViewportPercentage for NoCalcLength {
|
|||
impl ToCss for NoCalcLength {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
NoCalcLength::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
|
||||
NoCalcLength::Absolute(length) => length.to_css(dest),
|
||||
NoCalcLength::FontRelative(length) => length.to_css(dest),
|
||||
NoCalcLength::ViewportPercentage(length) => length.to_css(dest),
|
||||
/* This should only be reached from style dumping code */
|
||||
|
@ -255,7 +363,7 @@ impl Mul<CSSFloat> for NoCalcLength {
|
|||
#[inline]
|
||||
fn mul(self, scalar: CSSFloat) -> NoCalcLength {
|
||||
match self {
|
||||
NoCalcLength::Absolute(Au(v)) => NoCalcLength::Absolute(Au(((v as f32) * scalar) as i32)),
|
||||
NoCalcLength::Absolute(v) => NoCalcLength::Absolute(v * scalar),
|
||||
NoCalcLength::FontRelative(v) => NoCalcLength::FontRelative(v * scalar),
|
||||
NoCalcLength::ViewportPercentage(v) => NoCalcLength::ViewportPercentage(v * scalar),
|
||||
NoCalcLength::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
||||
|
@ -267,13 +375,13 @@ impl NoCalcLength {
|
|||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
||||
match_ignore_ascii_case! { unit,
|
||||
"px" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PX) as i32))),
|
||||
"in" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_IN) as i32))),
|
||||
"cm" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_CM) as i32))),
|
||||
"mm" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_MM) as i32))),
|
||||
"q" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_Q) as i32))),
|
||||
"pt" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PT) as i32))),
|
||||
"pc" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PC) as i32))),
|
||||
"px" => Ok(NoCalcLength::Absolute(AbsoluteLength::Px(value))),
|
||||
"in" => Ok(NoCalcLength::Absolute(AbsoluteLength::In(value))),
|
||||
"cm" => Ok(NoCalcLength::Absolute(AbsoluteLength::Cm(value))),
|
||||
"mm" => Ok(NoCalcLength::Absolute(AbsoluteLength::Mm(value))),
|
||||
"q" => Ok(NoCalcLength::Absolute(AbsoluteLength::Q(value))),
|
||||
"pt" => Ok(NoCalcLength::Absolute(AbsoluteLength::Pt(value))),
|
||||
"pc" => Ok(NoCalcLength::Absolute(AbsoluteLength::Pc(value))),
|
||||
// font-relative
|
||||
"em" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Em(value))),
|
||||
"ex" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Ex(value))),
|
||||
|
@ -291,25 +399,28 @@ impl NoCalcLength {
|
|||
#[inline]
|
||||
/// Returns a `zero` length.
|
||||
pub fn zero() -> NoCalcLength {
|
||||
NoCalcLength::Absolute(Au(0))
|
||||
NoCalcLength::Absolute(AbsoluteLength::Px(0.))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Checks whether the length value is zero.
|
||||
pub fn is_zero(&self) -> bool {
|
||||
*self == NoCalcLength::Absolute(Au(0))
|
||||
match *self {
|
||||
NoCalcLength::Absolute(length) => length.is_zero(),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns a `medium` length.
|
||||
pub fn medium() -> NoCalcLength {
|
||||
NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX))
|
||||
NoCalcLength::Absolute(AbsoluteLength::Px(FONT_MEDIUM_PX as f32))
|
||||
}
|
||||
|
||||
/// Get an absolute length from a px value.
|
||||
#[inline]
|
||||
pub fn from_px(px_value: CSSFloat) -> NoCalcLength {
|
||||
NoCalcLength::Absolute(Au((px_value * AU_PER_PX) as i32))
|
||||
NoCalcLength::Absolute(AbsoluteLength::Px(px_value))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -738,8 +849,8 @@ impl CalcLengthOrPercentage {
|
|||
match value {
|
||||
SimplifiedValueNode::Percentage(p) =>
|
||||
percentage = Some(percentage.unwrap_or(0.) + p),
|
||||
SimplifiedValueNode::Length(NoCalcLength::Absolute(Au(au))) =>
|
||||
absolute = Some(absolute.unwrap_or(0) + au),
|
||||
SimplifiedValueNode::Length(NoCalcLength::Absolute(length)) =>
|
||||
absolute = Some(absolute.unwrap_or(0.) + Au::from(length).to_f32_px()),
|
||||
SimplifiedValueNode::Length(NoCalcLength::ViewportPercentage(v)) =>
|
||||
match v {
|
||||
ViewportPercentageLength::Vw(val) =>
|
||||
|
@ -768,7 +879,7 @@ impl CalcLengthOrPercentage {
|
|||
}
|
||||
|
||||
Ok(CalcLengthOrPercentage {
|
||||
absolute: absolute.map(Au),
|
||||
absolute: absolute.map(Au::from_f32_px),
|
||||
vw: vw,
|
||||
vh: vh,
|
||||
vmax: vmax,
|
||||
|
@ -1043,7 +1154,7 @@ impl LengthOrPercentage {
|
|||
// TODO(emilio): Probably should use Number::parse_non_negative to
|
||||
// handle calc()?
|
||||
let num = input.expect_number()?;
|
||||
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(Au((AU_PER_PX * num) as i32))))
|
||||
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(num))))
|
||||
}
|
||||
|
||||
/// Parse a non-negative length, treating dimensionless numbers as pixels
|
||||
|
@ -1058,7 +1169,7 @@ impl LengthOrPercentage {
|
|||
// handle calc()?
|
||||
let num = input.expect_number()?;
|
||||
if num >= 0. {
|
||||
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(Au((AU_PER_PX * num) as i32))))
|
||||
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(num))))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue