Implement ToCss for types in style::properties::common_values::specified

This commit is contained in:
Simon Sapin 2014-12-21 00:04:53 +00:00
parent 4a9d5b1130
commit 45a08c94a4
3 changed files with 177 additions and 81 deletions

View file

@ -50,3 +50,49 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_lint_pass(box lints::InheritancePass as LintPassObject);
}
#[macro_export]
macro_rules! define_css_keyword_enum {
($name: ident: $( $css: expr => $variant: ident ),+,) => {
define_css_keyword_enum!($name: $( $css => $variant ),+)
};
($name: ident: $( $css: expr => $variant: ident ),+) => {
#[allow(non_camel_case_types)]
#[deriving(Clone, Eq, PartialEq, FromPrimitive)]
pub enum $name {
$( $variant ),+
}
impl $name {
pub fn parse(component_value: &::cssparser::ast::ComponentValue) -> Result<$name, ()> {
use std::ascii::AsciiExt;
match component_value {
&::cssparser::ast::Ident(ref value) => {
match value.to_ascii_lower().as_slice() {
$( concat!($css) => Ok($name::$variant), )+
_ => Err(())
}
}
_ => Err(())
}
}
}
impl ::std::fmt::Show for $name {
#[inline]
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
use cssparser::ToCss;
self.fmt_to_css(f)
}
}
impl ::cssparser::ToCss for $name {
fn to_css<W>(&self, dest: &mut W) -> ::text_writer::Result
where W: ::text_writer::TextWriter {
match self {
$( &$name::$variant => dest.write_str($css) ),+
}
}
}
}
}

View file

@ -18,6 +18,7 @@ extern crate collections;
extern crate geom;
extern crate serialize;
extern crate sync;
extern crate text_writer;
extern crate url;
extern crate cssparser;
@ -27,6 +28,9 @@ extern crate string_cache;
#[phase(plugin)]
extern crate string_cache_macros;
#[phase(plugin)]
extern crate plugins;
#[phase(plugin)]
extern crate lazy_static;

View file

@ -14,11 +14,11 @@ pub mod specified {
use std::ascii::AsciiExt;
use std::f64::consts::PI;
use std::fmt;
use std::fmt::{Formatter, FormatError, Show};
use std::fmt::{Formatter, Show};
use url::Url;
use cssparser;
use cssparser::ast;
use cssparser::{mod, ast, ToCss, CssStringWriter};
use cssparser::ast::*;
use text_writer::{mod, TextWriter};
use parsing_utils::{mod, BufferedIter, ParserIter};
use super::{Au, CSSFloat};
@ -42,11 +42,16 @@ pub mod specified {
})
}
}
impl fmt::Show for CSSColor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for CSSColor {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self.authored {
Some(ref s) => write!(f, "{}", s),
None => write!(f, "{}", self.parsed),
Some(ref s) => dest.write_str(s.as_slice()),
None => self.parsed.to_css(dest),
}
}
}
@ -57,22 +62,30 @@ pub mod specified {
pub authored: Option<String>,
}
impl fmt::Show for CSSRGBA {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for CSSRGBA {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self.authored {
Some(ref s) => write!(f, "{}", s),
None => write!(f, "{}", self.parsed),
Some(ref s) => dest.write_str(s.as_slice()),
None => self.parsed.to_css(dest),
}
}
}
#[deriving(Clone, PartialEq)]
pub struct CSSImage(pub Option<Image>);
impl fmt::Show for CSSImage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let &CSSImage(ref url) = self;
match url {
&Some(ref image) => write!(f, "{}", image),
&None => write!(f, "none"),
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for CSSImage {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&CSSImage(Some(ref image)) => image.to_css(dest),
&CSSImage(None) => dest.write_str("none"),
}
}
}
@ -97,17 +110,24 @@ pub mod specified {
// Vmin(CSSFloat),
// Vmax(CSSFloat),
}
impl fmt::Show for Length {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for Length {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&Length::Au(length) => write!(f, "{}", length),
&Length::Em(length) => write!(f, "{}em", length),
&Length::Ex(length) => write!(f, "{}ex", length),
&Length::Rem(length) => write!(f, "{}rem", length),
&Length::ServoCharacterWidth(_) => panic!("internal CSS values should never be serialized"),
&Length::Au(length) => write!(dest, "{}px", length.to_subpx()),
&Length::Em(length) => write!(dest, "{}em", length),
&Length::Ex(length) => write!(dest, "{}ex", length),
&Length::Rem(length) => write!(dest, "{}rem", length),
&Length::ServoCharacterWidth(_)
=> panic!("internal CSS values should never be serialized"),
}
}
}
const AU_PER_PX: CSSFloat = 60.;
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
@ -156,11 +176,17 @@ pub mod specified {
Length(Length),
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
}
impl fmt::Show for LengthOrPercentage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for LengthOrPercentage {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&LengthOrPercentage::Length(length) => write!(f, "{}", length),
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
&LengthOrPercentage::Length(length) => length.to_css(dest),
&LengthOrPercentage::Percentage(percentage)
=> write!(dest, "{}%", percentage * 100.),
}
}
}
@ -195,12 +221,18 @@ pub mod specified {
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
Auto,
}
impl fmt::Show for LengthOrPercentageOrAuto {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for LengthOrPercentageOrAuto {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&LengthOrPercentageOrAuto::Length(length) => write!(f, "{}", length),
&LengthOrPercentageOrAuto::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
&LengthOrPercentageOrAuto::Auto => write!(f, "auto"),
&LengthOrPercentageOrAuto::Length(length) => length.to_css(dest),
&LengthOrPercentageOrAuto::Percentage(percentage)
=> write!(dest, "{}%", percentage * 100.),
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
}
}
}
@ -235,12 +267,18 @@ pub mod specified {
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
None,
}
impl fmt::Show for LengthOrPercentageOrNone {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for LengthOrPercentageOrNone {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&LengthOrPercentageOrNone::Length(length) => write!(f, "{}", length),
&LengthOrPercentageOrNone::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
&LengthOrPercentageOrNone::None => write!(f, "none"),
&LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
&LengthOrPercentageOrNone::Percentage(percentage)
=> write!(dest, "{}%", percentage * 100.),
&LengthOrPercentageOrNone::None => dest.write_str("none"),
}
}
}
@ -312,10 +350,14 @@ pub mod specified {
#[deriving(Clone, PartialEq, PartialOrd)]
pub struct Angle(pub CSSFloat);
impl Show for Angle {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
impl fmt::Show for Angle {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for Angle {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
let Angle(value) = *self;
write!(f, "{}", value)
write!(dest, "{}rad", value)
}
}
@ -353,11 +395,20 @@ pub mod specified {
LinearGradient(LinearGradient),
}
impl Show for Image {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
impl fmt::Show for Image {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&Image::Url(ref url) => write!(f, "url(\"{}\")", url),
&Image::LinearGradient(ref grad) => write!(f, "linear-gradient({})", grad),
&Image::Url(ref url) => {
try!(dest.write_str("url(\""));
try!(write!(CssStringWriter::new(dest), "{}", url));
try!(dest.write_str("\")"));
Ok(())
}
&Image::LinearGradient(ref gradient) => gradient.to_css(dest)
}
}
}
@ -405,12 +456,19 @@ pub mod specified {
pub stops: Vec<ColorStop>,
}
impl Show for LinearGradient {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
let _ = write!(f, "{}", self.angle_or_corner);
for stop in self.stops.iter() {
let _ = write!(f, ", {}", stop);
impl fmt::Show for LinearGradient {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for LinearGradient {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
try!(dest.write_str("linear-gradient("));
try!(self.angle_or_corner.to_css(dest));
for stop in self.stops.iter() {
try!(dest.write_str(", "));
try!(stop.to_css(dest));
}
try!(dest.write_char(')'));
Ok(())
}
}
@ -422,11 +480,21 @@ pub mod specified {
Corner(HorizontalDirection, VerticalDirection),
}
impl Show for AngleOrCorner {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
impl fmt::Show for AngleOrCorner {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for AngleOrCorner {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&AngleOrCorner::Angle(angle) => write!(f, "{}", angle),
&AngleOrCorner::Corner(horiz, vert) => write!(f, "to {} {}", horiz, vert),
&AngleOrCorner::Angle(angle) => angle.to_css(dest),
&AngleOrCorner::Corner(horizontal, vertical) => {
try!(dest.write_str("to "));
try!(horizontal.to_css(dest));
try!(dest.write_char(' '));
try!(vertical.to_css(dest));
Ok(())
}
}
}
}
@ -442,45 +510,23 @@ pub mod specified {
pub position: Option<LengthOrPercentage>,
}
impl Show for ColorStop {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
let _ = write!(f, "{}", self.color);
self.position.map(|pos| {
let _ = write!(f, " {}", pos);
});
impl fmt::Show for ColorStop {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for ColorStop {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
try!(self.color.to_css(dest));
if let Some(position) = self.position {
try!(dest.write_char(' '));
try!(position.to_css(dest));
}
Ok(())
}
}
#[deriving(Clone, PartialEq)]
pub enum HorizontalDirection {
Left,
Right,
}
impl Show for HorizontalDirection {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
match self {
&HorizontalDirection::Left => write!(f, "left"),
&HorizontalDirection::Right => write!(f, "right"),
}
}
}
#[deriving(Clone, PartialEq)]
pub enum VerticalDirection {
Top,
Bottom,
}
impl Show for VerticalDirection {
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
match self {
&VerticalDirection::Top => write!(f, "top"),
&VerticalDirection::Bottom => write!(f, "bottom"),
}
}
}
define_css_keyword_enum!(HorizontalDirection: "left" => Left, "right" => Right)
define_css_keyword_enum!(VerticalDirection: "top" => Top, "bottom" => Bottom)
fn parse_color_stop(source: ParserIter) -> Result<ColorStop,()> {
let color = match source.next() {