mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +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),
|
||||
};
|
||||
let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) {
|
||||
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
|
||||
Some(block_container_block_size.scale_by(percent))
|
||||
}
|
||||
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) =>
|
||||
Some(block_container_block_size.scale_by(percent)),
|
||||
(LengthOrPercentageOrNone::Percentage(_), None) |
|
||||
(LengthOrPercentageOrNone::None, _) => None,
|
||||
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
||||
|
@ -342,6 +341,10 @@ impl CandidateBSizeIterator {
|
|||
(LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => {
|
||||
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::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))
|
||||
}
|
||||
LengthOrPercentage::Percentage(percentage) => percentage as f32,
|
||||
LengthOrPercentage::Calc(calc) =>
|
||||
fmin(1.0, calc.percentage() + (calc.length().0 as f32) / (total_length as f32)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -988,6 +988,11 @@ impl InlineFlow {
|
|||
let percent_offset = line_height.scale_by(p);
|
||||
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)
|
||||
|
|
|
@ -416,7 +416,9 @@ pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au
|
|||
pub fn specified(length: LengthOrPercentage, containing_length: Au) -> Au {
|
||||
match 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 {
|
||||
use std::fmt;
|
||||
use util::geometry::Au;
|
||||
use values::CSSFloat;
|
||||
use values::{CSSFloat, computed};
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
|
||||
pub enum T {
|
||||
|
@ -765,6 +765,7 @@ pub mod longhands {
|
|||
% endfor
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
Calc(computed::Calc),
|
||||
}
|
||||
impl fmt::Debug for T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -774,6 +775,8 @@ pub mod longhands {
|
|||
% endfor
|
||||
&T::Length(length) => write!(f, "{:?}", length),
|
||||
&T::Percentage(number) => write!(f, "{}%", number),
|
||||
// XXX HACK WRONG
|
||||
&T::Calc(calc) => write!(f, "{}%", 10.),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -785,6 +788,7 @@ pub mod longhands {
|
|||
% endfor
|
||||
T::Length(value) => value.to_css(dest),
|
||||
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
|
||||
T::Calc(calc) => calc.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -805,12 +809,12 @@ pub mod longhands {
|
|||
% endfor
|
||||
SpecifiedValue::LengthOrPercentage(value) => {
|
||||
match value.to_computed_value(context) {
|
||||
computed::LengthOrPercentage::Length(value) => {
|
||||
computed_value::T::Length(value)
|
||||
}
|
||||
computed::LengthOrPercentage::Percentage(value) => {
|
||||
computed_value::T::Percentage(value)
|
||||
}
|
||||
computed::LengthOrPercentage::Length(value) =>
|
||||
computed_value::T::Length(value),
|
||||
computed::LengthOrPercentage::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 {
|
||||
specified::LengthOrPercentage::Length(value) => 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(|()| {
|
||||
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)]
|
||||
pub enum LengthOrPercentage {
|
||||
Length(Length),
|
||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
Calc(Calc),
|
||||
}
|
||||
|
||||
impl ToCss for LengthOrPercentage {
|
||||
|
@ -366,6 +448,7 @@ pub mod specified {
|
|||
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
||||
&LengthOrPercentage::Percentage(percentage)
|
||||
=> write!(dest, "{}%", percentage * 100.),
|
||||
&LengthOrPercentage::Calc(calc) => calc.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -384,6 +467,10 @@ pub mod specified {
|
|||
Ok(LengthOrPercentage::Percentage(value.unit_value)),
|
||||
Token::Number(ref value) if value.value == 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(())
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
pub enum LengthOrPercentage {
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
Calc(Calc),
|
||||
}
|
||||
|
||||
impl LengthOrPercentage {
|
||||
|
@ -955,6 +1082,8 @@ pub mod computed {
|
|||
match self {
|
||||
&LengthOrPercentage::Length(length) => write!(f, "{:?}", length),
|
||||
&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) => {
|
||||
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::Percentage(percentage)
|
||||
=> write!(dest, "{}%", percentage * 100.),
|
||||
&LengthOrPercentage::Calc(calc) => calc.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue