mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Implement Calc for LengthOrPercentage
This commit is contained in:
parent
fa5ad1c6b4
commit
9556141e57
6 changed files with 165 additions and 13 deletions
|
@ -331,9 +331,8 @@ impl CandidateBSizeIterator {
|
||||||
(LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length),
|
(LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length),
|
||||||
};
|
};
|
||||||
let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) {
|
let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) {
|
||||||
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
|
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) =>
|
||||||
Some(block_container_block_size.scale_by(percent))
|
Some(block_container_block_size.scale_by(percent)),
|
||||||
}
|
|
||||||
(LengthOrPercentageOrNone::Percentage(_), None) |
|
(LengthOrPercentageOrNone::Percentage(_), None) |
|
||||||
(LengthOrPercentageOrNone::None, _) => None,
|
(LengthOrPercentageOrNone::None, _) => None,
|
||||||
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
||||||
|
@ -342,6 +341,10 @@ impl CandidateBSizeIterator {
|
||||||
(LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => {
|
(LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => {
|
||||||
block_container_block_size.scale_by(percent)
|
block_container_block_size.scale_by(percent)
|
||||||
}
|
}
|
||||||
|
(LengthOrPercentage::Calc(calc), Some(block_container_block_size)) => {
|
||||||
|
calc.length() + block_container_block_size.scale_by(calc.percentage())
|
||||||
|
}
|
||||||
|
(LengthOrPercentage::Calc(calc), None) => calc.length(),
|
||||||
(LengthOrPercentage::Percentage(_), None) => Au(0),
|
(LengthOrPercentage::Percentage(_), None) => Au(0),
|
||||||
(LengthOrPercentage::Length(length), _) => length,
|
(LengthOrPercentage::Length(length), _) => length,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1955,6 +1955,8 @@ fn position_to_offset(position: LengthOrPercentage, Au(total_length): Au) -> f32
|
||||||
fmin(1.0, (length as f32) / (total_length as f32))
|
fmin(1.0, (length as f32) / (total_length as f32))
|
||||||
}
|
}
|
||||||
LengthOrPercentage::Percentage(percentage) => percentage as f32,
|
LengthOrPercentage::Percentage(percentage) => percentage as f32,
|
||||||
|
LengthOrPercentage::Calc(calc) =>
|
||||||
|
fmin(1.0, calc.percentage() + (calc.length().0 as f32) / (total_length as f32)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -988,7 +988,12 @@ impl InlineFlow {
|
||||||
let percent_offset = line_height.scale_by(p);
|
let percent_offset = line_height.scale_by(p);
|
||||||
offset_from_baseline = offset_from_baseline - percent_offset
|
offset_from_baseline = offset_from_baseline - percent_offset
|
||||||
}
|
}
|
||||||
}
|
vertical_align::T::Calc(calc) => {
|
||||||
|
let line_height = fragment.calculate_line_height(layout_context);
|
||||||
|
let percent_offset = line_height.scale_by(calc.percentage());
|
||||||
|
offset_from_baseline = offset_from_baseline - percent_offset - calc.length()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(offset_from_baseline - ascent, largest_size_updated)
|
(offset_from_baseline - ascent, largest_size_updated)
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,7 +416,9 @@ pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au
|
||||||
pub fn specified(length: LengthOrPercentage, containing_length: Au) -> Au {
|
pub fn specified(length: LengthOrPercentage, containing_length: Au) -> Au {
|
||||||
match length {
|
match length {
|
||||||
LengthOrPercentage::Length(length) => length,
|
LengthOrPercentage::Length(length) => length,
|
||||||
LengthOrPercentage::Percentage(p) => containing_length.scale_by(p)
|
LengthOrPercentage::Percentage(p) => containing_length.scale_by(p),
|
||||||
|
LengthOrPercentage::Calc(calc) =>
|
||||||
|
containing_length.scale_by(calc.percentage()) + calc.length(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -756,7 +756,7 @@ pub mod longhands {
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
use values::CSSFloat;
|
use values::{CSSFloat, computed};
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
|
#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
|
||||||
pub enum T {
|
pub enum T {
|
||||||
|
@ -765,6 +765,7 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
|
Calc(computed::Calc),
|
||||||
}
|
}
|
||||||
impl fmt::Debug for T {
|
impl fmt::Debug for T {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -774,6 +775,8 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
&T::Length(length) => write!(f, "{:?}", length),
|
&T::Length(length) => write!(f, "{:?}", length),
|
||||||
&T::Percentage(number) => write!(f, "{}%", number),
|
&T::Percentage(number) => write!(f, "{}%", number),
|
||||||
|
// XXX HACK WRONG
|
||||||
|
&T::Calc(calc) => write!(f, "{}%", 10.),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -785,6 +788,7 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
T::Length(value) => value.to_css(dest),
|
T::Length(value) => value.to_css(dest),
|
||||||
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
|
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
|
||||||
|
T::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -805,12 +809,12 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
SpecifiedValue::LengthOrPercentage(value) => {
|
SpecifiedValue::LengthOrPercentage(value) => {
|
||||||
match value.to_computed_value(context) {
|
match value.to_computed_value(context) {
|
||||||
computed::LengthOrPercentage::Length(value) => {
|
computed::LengthOrPercentage::Length(value) =>
|
||||||
computed_value::T::Length(value)
|
computed_value::T::Length(value),
|
||||||
}
|
computed::LengthOrPercentage::Percentage(value) =>
|
||||||
computed::LengthOrPercentage::Percentage(value) => {
|
computed_value::T::Percentage(value),
|
||||||
computed_value::T::Percentage(value)
|
computed::LengthOrPercentage::Calc(value) =>
|
||||||
}
|
computed_value::T::Calc(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1909,7 +1913,10 @@ pub mod longhands {
|
||||||
.map(|value| match value {
|
.map(|value| match value {
|
||||||
specified::LengthOrPercentage::Length(value) => value,
|
specified::LengthOrPercentage::Length(value) => value,
|
||||||
specified::LengthOrPercentage::Percentage(value) =>
|
specified::LengthOrPercentage::Percentage(value) =>
|
||||||
specified::Length::FontRelative(specified::FontRelativeLength::Em(value))
|
specified::Length::FontRelative(specified::FontRelativeLength::Em(value)),
|
||||||
|
// XXX WRONG HACK
|
||||||
|
specified::LengthOrPercentage::Calc(calc) =>
|
||||||
|
specified::Length::FontRelative(specified::FontRelativeLength::Em(20.)),
|
||||||
})
|
})
|
||||||
.or_else(|()| {
|
.or_else(|()| {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
|
|
|
@ -353,11 +353,93 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
|
pub struct Calc {
|
||||||
|
pub absolute: Option<Au>,
|
||||||
|
pub font_relative: Option<FontRelativeLength>,
|
||||||
|
pub viewport_percentage: Option<ViewportPercentageLength>,
|
||||||
|
pub percentage: Option<CSSFloat>,
|
||||||
|
}
|
||||||
|
impl Calc {
|
||||||
|
pub fn parse_component(&mut self, input: &mut Parser) -> Result<(), ()> {
|
||||||
|
match try!(input.next()) {
|
||||||
|
Token::Dimension(ref value, ref unit) => {
|
||||||
|
let value = value.value;
|
||||||
|
match_ignore_ascii_case! { unit,
|
||||||
|
"px" => self.absolute =
|
||||||
|
Some(self.absolute.unwrap_or(Au(0)) + Au((value * AU_PER_PX) as i32)),
|
||||||
|
"in" => self.absolute =
|
||||||
|
Some(self.absolute.unwrap_or(Au(0)) + Au((value * AU_PER_IN) as i32)),
|
||||||
|
"cm" => self.absolute =
|
||||||
|
Some(self.absolute.unwrap_or(Au(0)) + Au((value * AU_PER_CM) as i32)),
|
||||||
|
"mm" => self.absolute =
|
||||||
|
Some(self.absolute.unwrap_or(Au(0)) + Au((value * AU_PER_MM) as i32)),
|
||||||
|
"pt" => self.absolute =
|
||||||
|
Some(self.absolute.unwrap_or(Au(0)) + Au((value * AU_PER_PT) as i32)),
|
||||||
|
"pc" => self.absolute =
|
||||||
|
Some(self.absolute.unwrap_or(Au(0)) + Au((value * AU_PER_PC) as i32))
|
||||||
|
// font-relative
|
||||||
|
/*"em" => Ok(Length::FontRelative(FontRelativeLength::Em(value))),
|
||||||
|
"ex" => Ok(Length::FontRelative(FontRelativeLength::Ex(value))),
|
||||||
|
"rem" => Ok(Length::FontRelative(FontRelativeLength::Rem(value))),
|
||||||
|
// viewport percentages
|
||||||
|
"vw" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vw(value))),
|
||||||
|
"vh" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vh(value))),
|
||||||
|
"vmin" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmin(value))),
|
||||||
|
"vmax" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmax(value)))*/
|
||||||
|
// Handle em, ex, rem, vw, vh, vmin, vmax
|
||||||
|
_ => return Err(())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Token::Percentage(ref value) =>
|
||||||
|
self.percentage = Some(self.percentage.unwrap_or(0.) + value.unit_value),
|
||||||
|
Token::Number(ref value) if value.value == 0. =>
|
||||||
|
self.absolute = self.absolute.or(Some(Au(0))),
|
||||||
|
_ => return Err(())
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(input: &mut Parser) -> Result<Calc, ()> {
|
||||||
|
let mut calc = Calc {
|
||||||
|
absolute: None,
|
||||||
|
font_relative: None,
|
||||||
|
viewport_percentage: None,
|
||||||
|
percentage: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
try!(calc.parse_component(input));
|
||||||
|
let operator = try!(input.next());
|
||||||
|
match operator {
|
||||||
|
Token::Delim('+') => (),
|
||||||
|
_ => return Err(())
|
||||||
|
};
|
||||||
|
|
||||||
|
try!(calc.parse_component(input));
|
||||||
|
Ok(calc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for Calc {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
// XXX WRONG HACK
|
||||||
|
try!(write!(dest, "calc("));
|
||||||
|
if let Some(absolute) = self.absolute {
|
||||||
|
try!(write!(dest, "{}px", Au::to_px(absolute)));
|
||||||
|
}
|
||||||
|
if let Some(FontRelativeLength::Em(font_relative)) = self.font_relative {
|
||||||
|
try!(write!(dest, "{}em", font_relative));
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(dest, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||||
|
Calc(Calc),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for LengthOrPercentage {
|
impl ToCss for LengthOrPercentage {
|
||||||
|
@ -366,6 +448,7 @@ pub mod specified {
|
||||||
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
||||||
&LengthOrPercentage::Percentage(percentage)
|
&LengthOrPercentage::Percentage(percentage)
|
||||||
=> write!(dest, "{}%", percentage * 100.),
|
=> write!(dest, "{}%", percentage * 100.),
|
||||||
|
&LengthOrPercentage::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,6 +467,10 @@ pub mod specified {
|
||||||
Ok(LengthOrPercentage::Percentage(value.unit_value)),
|
Ok(LengthOrPercentage::Percentage(value.unit_value)),
|
||||||
Token::Number(ref value) if value.value == 0. =>
|
Token::Number(ref value) if value.value == 0. =>
|
||||||
Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))),
|
Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))),
|
||||||
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
|
let calc = try!(input.parse_nested_block(Calc::parse));
|
||||||
|
Ok(LengthOrPercentage::Calc(calc))
|
||||||
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -938,10 +1025,50 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
|
pub struct Calc {
|
||||||
|
length: Option<Au>,
|
||||||
|
percentage: Option<CSSFloat>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Calc {
|
||||||
|
pub fn length(&self) -> Au {
|
||||||
|
self.length.unwrap_or(Au(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn percentage(&self) -> CSSFloat {
|
||||||
|
self.percentage.unwrap_or(0.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for Calc {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match (self.length, self.percentage) {
|
||||||
|
(None, Some(p)) => write!(dest, "{}%", p),
|
||||||
|
(Some(l), None) => write!(dest, "{}px", Au::to_px(l)),
|
||||||
|
(Some(l), Some(p)) => write!(dest, "calc({}px + {}%)", Au::to_px(l), p * 100.),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for specified::Calc {
|
||||||
|
type ComputedValue = Calc;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Calc {
|
||||||
|
let length = self.absolute;
|
||||||
|
let percentage = self.percentage;
|
||||||
|
|
||||||
|
Calc { length: length, percentage: percentage }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, HeapSizeOf)]
|
#[derive(PartialEq, Clone, Copy, HeapSizeOf)]
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
|
Calc(Calc),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthOrPercentage {
|
impl LengthOrPercentage {
|
||||||
|
@ -955,6 +1082,8 @@ pub mod computed {
|
||||||
match self {
|
match self {
|
||||||
&LengthOrPercentage::Length(length) => write!(f, "{:?}", length),
|
&LengthOrPercentage::Length(length) => write!(f, "{:?}", length),
|
||||||
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
||||||
|
// XXX HACK WRONG
|
||||||
|
&LengthOrPercentage::Calc(calc) => write!(f, "{}%", 100.),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -970,6 +1099,9 @@ pub mod computed {
|
||||||
specified::LengthOrPercentage::Percentage(value) => {
|
specified::LengthOrPercentage::Percentage(value) => {
|
||||||
LengthOrPercentage::Percentage(value)
|
LengthOrPercentage::Percentage(value)
|
||||||
}
|
}
|
||||||
|
specified::LengthOrPercentage::Calc(calc) => {
|
||||||
|
LengthOrPercentage::Calc(calc.to_computed_value(context))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -980,6 +1112,7 @@ pub mod computed {
|
||||||
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
||||||
&LengthOrPercentage::Percentage(percentage)
|
&LengthOrPercentage::Percentage(percentage)
|
||||||
=> write!(dest, "{}%", percentage * 100.),
|
=> write!(dest, "{}%", percentage * 100.),
|
||||||
|
&LengthOrPercentage::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue