From bc1c44bbc2245d84e1b948506a1024ab1308ab8d Mon Sep 17 00:00:00 2001 From: James Gilbertson Date: Thu, 5 Mar 2015 07:04:27 -0700 Subject: [PATCH] Implement viewport percentage length units ('vw', 'vh', 'vmin', 'vmax') --- components/style/media_queries.rs | 2 + components/style/properties.mako.rs | 2 + components/style/values.rs | 60 +++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs index f856db6a21ed..97f75104c402 100644 --- a/components/style/media_queries.rs +++ b/components/style/media_queries.rs @@ -34,6 +34,8 @@ impl Range { let initial_font_size = longhands::font_size::get_initial_value(); value.to_computed_value(initial_font_size, initial_font_size) } + &specified::Length::ViewportPercentage(value) => + value.to_computed_value(viewport_size), _ => unreachable!() } }; diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 2975f33dbd7b..f0215854a164 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -19,6 +19,7 @@ use cssparser::{Parser, Color, RGBA, AtRuleParser, DeclarationParser, DeclarationListParser, parse_important, ToCss}; use geom::num::Zero; use geom::SideOffsets2D; +use geom::size::Size2D; use values::specified::BorderStyle; use values::computed::{self, ToComputedValue}; @@ -3732,6 +3733,7 @@ pub fn cascade(viewport_size: Size2D, let inherited_font_style = inherited_style.get_font(); computed::Context { is_root_element: is_root_element, + viewport_size: viewport_size, inherited_font_weight: inherited_font_style.font_weight, inherited_font_size: inherited_font_style.font_size, inherited_height: inherited_style.get_box().height, diff --git a/components/style/values.rs b/components/style/values.rs index c53f2ec86c04..5195f8065639 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -52,11 +52,14 @@ pub type CSSFloat = f64; pub mod specified { use std::ascii::AsciiExt; + use std::cmp; use std::f64::consts::PI; use std::fmt; use std::fmt::{Formatter, Debug}; + use std::num::{NumCast, ToPrimitive}; use url::Url; use cssparser::{self, Token, Parser, ToCss, CssStringWriter}; + use geom::size::Size2D; use parser::ParserContext; use text_writer::{self, TextWriter}; use util::geometry::Au; @@ -154,6 +157,51 @@ pub mod specified { } } + #[derive(Clone, PartialEq, Copy)] + pub enum ViewportPercentageLength { + Vw(CSSFloat), + Vh(CSSFloat), + Vmin(CSSFloat), + Vmax(CSSFloat) + } + + impl fmt::Debug for ViewportPercentageLength { + #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) } + } + + impl ToCss for ViewportPercentageLength { + fn to_css(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { + match self { + &ViewportPercentageLength::Vw(length) => write!(dest, "{}vw", length), + &ViewportPercentageLength::Vh(length) => write!(dest, "{}vh", length), + &ViewportPercentageLength::Vmin(length) => write!(dest, "{}vmin", length), + &ViewportPercentageLength::Vmax(length) => write!(dest, "{}vmax", length) + } + } + } + + impl ViewportPercentageLength { + pub fn to_computed_value(&self, viewport_size: Size2D) -> Au { + macro_rules! to_unit { + ($viewport_dimension:expr) => { + $viewport_dimension.to_f64().unwrap() / 100.0 + } + } + + let value = match self { + &ViewportPercentageLength::Vw(length) => + length * to_unit!(viewport_size.width), + &ViewportPercentageLength::Vh(length) => + length * to_unit!(viewport_size.height), + &ViewportPercentageLength::Vmin(length) => + length * to_unit!(cmp::min(viewport_size.width, viewport_size.height)), + &ViewportPercentageLength::Vmax(length) => + length * to_unit!(cmp::max(viewport_size.width, viewport_size.height)), + }; + NumCast::from(value).unwrap() + } + } + #[derive(Clone, PartialEq, Copy)] pub struct CharacterWidth(pub i32); @@ -173,6 +221,8 @@ pub mod specified { pub enum Length { Absolute(Au), // application units FontRelative(FontRelativeLength), + ViewportPercentage(ViewportPercentageLength), + /// HTML5 "character width", as defined in HTML5 ยง 14.5.4. /// /// This cannot be specified by the user directly and is only generated by @@ -189,6 +239,7 @@ pub mod specified { match self { &Length::Absolute(length) => write!(dest, "{}px", length.to_subpx()), &Length::FontRelative(length) => length.to_css(dest), + &Length::ViewportPercentage(length) => length.to_css(dest), &Length::ServoCharacterWidth(_) => panic!("internal CSS values should never be serialized"), } @@ -232,6 +283,11 @@ pub mod specified { "ex" => Ok(Length::FontRelative(FontRelativeLength::Ex(value))), "ch" => Err(()), "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))) _ => Err(()) } } @@ -701,6 +757,7 @@ pub mod computed { use super::specified::{AngleOrCorner}; use super::{specified, CSSFloat}; pub use cssparser::Color as CSSColor; + use geom::size::Size2D; use properties::longhands; use std::fmt; use url::Url; @@ -727,6 +784,7 @@ pub mod computed { pub border_bottom_present: bool, pub border_left_present: bool, pub is_root_element: bool, + pub viewport_size: Size2D // TODO, as needed: viewport size, etc. } @@ -768,6 +826,8 @@ pub mod computed { &specified::Length::Absolute(length) => length, &specified::Length::FontRelative(length) => length.to_computed_value(context.font_size, context.root_font_size), + &specified::Length::ViewportPercentage(length) => + length.to_computed_value(context.viewport_size), &specified::Length::ServoCharacterWidth(length) => length.to_computed_value(context.font_size) }