style: Move grid-template-areas outside of mako

This commit is contained in:
CYBAI 2017-11-29 00:17:45 +08:00
parent 2eb266b314
commit 003ddfc945
7 changed files with 195 additions and 185 deletions

View file

@ -2252,7 +2252,7 @@ fn static_assert() {
${impl_simple_type_with_conversion("grid_auto_flow")}
pub fn set_grid_template_areas(&mut self, v: longhands::grid_template_areas::computed_value::T) {
pub fn set_grid_template_areas(&mut self, v: values::computed::position::GridTemplateAreas) {
use gecko_bindings::bindings::Gecko_NewGridTemplateAreasValue;
use gecko_bindings::sugar::refptr::UniqueRefPtr;
@ -2292,10 +2292,10 @@ fn static_assert() {
self.copy_grid_template_areas_from(other)
}
pub fn clone_grid_template_areas(&self) -> longhands::grid_template_areas::computed_value::T {
use properties::longhands::grid_template_areas::{NamedArea, TemplateAreas};
pub fn clone_grid_template_areas(&self) -> values::computed::position::GridTemplateAreas {
use std::ops::Range;
use values::None_;
use values::specified::position::{NamedArea, TemplateAreas};
if self.gecko.mGridTemplateAreas.mRawPtr.is_null() {
return Either::Second(None_);

View file

@ -301,181 +301,11 @@ ${helpers.predefined_type("grid-auto-flow",
gecko_pref="layout.css.grid.enabled",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow")}
<%helpers:longhand name="grid-template-areas"
spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas"
products="gecko"
animation_value_type="discrete"
gecko_pref="layout.css.grid.enabled"
boxed="True">
use hash::FnvHashMap;
use std::fmt;
use std::ops::Range;
use str::HTML_SPACE_CHARACTERS;
use style_traits::ToCss;
pub mod computed_value {
pub use super::SpecifiedValue as T;
}
pub type SpecifiedValue = Either<TemplateAreas, None_>;
#[inline]
pub fn get_initial_value() -> computed_value::T {
Either::Second(None_)
}
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct TemplateAreas {
pub areas: Box<[NamedArea]>,
pub strings: Box<[Box<str>]>,
pub width: u32,
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct NamedArea {
pub name: Box<str>,
pub rows: Range<u32>,
pub columns: Range<u32>,
}
trivial_to_computed_value!(TemplateAreas);
impl Parse for TemplateAreas {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut strings = vec![];
while let Ok(string) = input.try(|i| i.expect_string().map(|s| s.as_ref().into())) {
strings.push(string);
}
TemplateAreas::from_vec(strings)
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
impl TemplateAreas {
pub fn from_vec(strings: Vec<Box<str>>) -> Result<TemplateAreas, ()> {
if strings.is_empty() {
return Err(());
}
let mut areas: Vec<NamedArea> = vec![];
let mut width = 0;
{
let mut row = 0u32;
let mut area_indices = FnvHashMap::<(&str), usize>::default();
for string in &strings {
let mut current_area_index: Option<usize> = None;
row += 1;
let mut column = 0u32;
for token in Tokenizer(string) {
column += 1;
let token = if let Some(token) = token? {
token
} else {
if let Some(index) = current_area_index.take() {
if areas[index].columns.end != column {
return Err(());
}
}
continue;
};
if let Some(index) = current_area_index {
if &*areas[index].name == token {
if areas[index].rows.start == row {
areas[index].columns.end += 1;
}
continue;
}
if areas[index].columns.end != column {
return Err(());
}
}
if let Some(index) = area_indices.get(token).cloned() {
if areas[index].columns.start != column || areas[index].rows.end != row {
return Err(());
}
areas[index].rows.end += 1;
current_area_index = Some(index);
continue;
}
let index = areas.len();
areas.push(NamedArea {
name: token.to_owned().into_boxed_str(),
columns: column..(column + 1),
rows: row..(row + 1),
});
assert!(area_indices.insert(token, index).is_none());
current_area_index = Some(index);
}
if let Some(index) = current_area_index {
if areas[index].columns.end != column + 1 {
assert!(areas[index].rows.start != row);
return Err(());
}
}
if row == 1 {
width = column;
} else if width != column {
return Err(());
}
}
}
Ok(TemplateAreas {
areas: areas.into_boxed_slice(),
strings: strings.into_boxed_slice(),
width: width,
})
}
}
impl ToCss for TemplateAreas {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
for (i, string) in self.strings.iter().enumerate() {
if i != 0 {
dest.write_str(" ")?;
}
string.to_css(dest)?;
}
Ok(())
}
}
struct Tokenizer<'a>(&'a str);
impl<'a> Iterator for Tokenizer<'a> {
type Item = Result<Option<(&'a str)>, ()>;
fn next(&mut self) -> Option<Self::Item> {
let rest = self.0.trim_left_matches(HTML_SPACE_CHARACTERS);
if rest.is_empty() {
return None;
}
if rest.starts_with('.') {
self.0 = &rest[rest.find(|c| c != '.').unwrap_or(rest.len())..];
return Some(Ok(None));
}
if !rest.starts_with(is_name_code_point) {
return Some(Err(()));
}
let token_len = rest.find(|c| !is_name_code_point(c)).unwrap_or(rest.len());
let token = &rest[..token_len];
self.0 = &rest[token_len..];
Some(Ok(Some(token)))
}
}
fn is_name_code_point(c: char) -> bool {
c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' ||
c >= '\u{80}' || c == '_' ||
c >= '0' && c <= '9' || c == '-'
}
</%helpers:longhand>
${helpers.predefined_type("grid-template-areas",
"GridTemplateAreas",
initial_value="computed::GridTemplateAreas::none()",
products="gecko",
animation_value_type="discrete",
gecko_pref="layout.css.grid.enabled",
boxed=True,
spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas")}

View file

@ -246,12 +246,12 @@
spec="https://drafts.csswg.org/css-grid/#propdef-grid-template"
products="gecko">
use parser::Parse;
use properties::longhands::grid_template_areas::TemplateAreas;
use values::{Either, None_};
use values::generics::grid::{LineNameList, TrackSize, TrackList, TrackListType};
use values::generics::grid::{TrackListValue, concat_serialize_idents};
use values::specified::{GridTemplateComponent, GenericGridTemplateComponent};
use values::specified::grid::parse_line_names;
use values::specified::position::TemplateAreas;
/// Parsing for `<grid-template>` shorthand (also used by `grid` shorthand).
pub fn parse_grid_template<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)

View file

@ -54,7 +54,7 @@ pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNum
pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
pub use self::length::{CSSPixelLength, NonNegativeLength, NonNegativeLengthOrPercentage};
pub use self::percentage::Percentage;
pub use self::position::{Position, GridAutoFlow};
pub use self::position::{Position, GridAutoFlow, GridTemplateAreas};
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth};
pub use self::table::XSpan;
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextOverflow, WordSpacing};

View file

@ -11,7 +11,7 @@ use std::fmt;
use style_traits::ToCss;
use values::computed::{LengthOrPercentage, Percentage};
use values::generics::position::Position as GenericPosition;
pub use values::specified::position::GridAutoFlow;
pub use values::specified::position::{GridAutoFlow, GridTemplateAreas};
/// The computed value of a CSS `<position>`
pub type Position = GenericPosition<HorizontalPosition, VerticalPosition>;

View file

@ -50,7 +50,7 @@ pub use self::length::{NoCalcLength, ViewportPercentageLength};
pub use self::length::NonNegativeLengthOrPercentage;
pub use self::rect::LengthOrNumberRect;
pub use self::percentage::Percentage;
pub use self::position::{Position, PositionComponent, GridAutoFlow};
pub use self::position::{Position, PositionComponent, GridAutoFlow, GridTemplateAreas};
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth};
pub use self::table::XSpan;
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine, TextOverflow, WordSpacing};

View file

@ -8,10 +8,14 @@
//! [position]: https://drafts.csswg.org/css-backgrounds-3/#position
use cssparser::Parser;
use hash::FnvHashMap;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind;
use std::fmt;
use std::ops::Range;
use str::HTML_SPACE_CHARACTERS;
use style_traits::{ToCss, StyleParseErrorKind, ParseError};
use values::{Either, None_};
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage as ComputedLengthOrPercentage};
use values::computed::{Context, Percentage, ToComputedValue};
use values::generics::position::Position as GenericPosition;
@ -486,3 +490,179 @@ impl From<GridAutoFlow> for u8 {
result
}
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq)]
/// https://drafts.csswg.org/css-grid/#named-grid-area
pub struct TemplateAreas {
/// `named area` containing for each template area
pub areas: Box<[NamedArea]>,
/// The original CSS string value of each template area
pub strings: Box<[Box<str>]>,
/// The number of columns of the grid.
pub width: u32,
}
impl TemplateAreas {
/// Transform `vector` of str into `template area`
pub fn from_vec(strings: Vec<Box<str>>) -> Result<TemplateAreas, ()> {
if strings.is_empty() {
return Err(());
}
let mut areas: Vec<NamedArea> = vec![];
let mut width = 0;
{
let mut row = 0u32;
let mut area_indices = FnvHashMap::<&str, usize>::default();
for string in &strings {
let mut current_area_index: Option<usize> = None;
row += 1;
let mut column = 0u32;
for token in TemplateAreasTokenizer(string) {
column += 1;
let token = if let Some(token) = token? {
token
} else {
if let Some(index) = current_area_index.take() {
if areas[index].columns.end != column {
return Err(());
}
}
continue;
};
if let Some(index) = current_area_index {
if &*areas[index].name == token {
if areas[index].rows.start == row {
areas[index].columns.end += 1;
}
continue;
}
if areas[index].columns.end != column {
return Err(());
}
}
if let Some(index) = area_indices.get(token).cloned() {
if areas[index].columns.start != column || areas[index].rows.end != row {
return Err(());
}
areas[index].rows.end += 1;
current_area_index = Some(index);
continue;
}
let index = areas.len();
areas.push(NamedArea {
name: token.to_owned().into_boxed_str(),
columns: column..(column + 1),
rows: row..(row + 1),
});
assert!(area_indices.insert(token, index).is_none());
current_area_index = Some(index);
}
if let Some(index) = current_area_index {
if areas[index].columns.end != column + 1 {
assert_ne!(areas[index].rows.start, row);
return Err(());
}
}
if row == 1 {
width = column;
} else if width != column {
return Err(());
}
}
}
Ok(TemplateAreas {
areas: areas.into_boxed_slice(),
strings: strings.into_boxed_slice(),
width: width,
})
}
}
impl ToCss for TemplateAreas {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
for (i, string) in self.strings.iter().enumerate() {
if i != 0 {
dest.write_str(" ")?;
}
string.to_css(dest)?;
}
Ok(())
}
}
impl Parse for TemplateAreas {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut strings = vec![];
while let Ok(string) = input.try(|i| i.expect_string().map(|s| s.as_ref().into())) {
strings.push(string);
}
TemplateAreas::from_vec(strings)
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
trivial_to_computed_value!(TemplateAreas);
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq)]
/// Not associated with any particular grid item, but can
/// be referenced from the grid-placement properties.
pub struct NamedArea {
/// Name of the `named area`
pub name: Box<str>,
/// Rows of the `named area`
pub rows: Range<u32>,
/// Columns of the `named area`
pub columns: Range<u32>,
}
/// Tokenize the string into a list of the tokens,
/// using longest-match semantics
struct TemplateAreasTokenizer<'a>(&'a str);
impl<'a> Iterator for TemplateAreasTokenizer<'a> {
type Item = Result<Option<&'a str>, ()>;
fn next(&mut self) -> Option<Self::Item> {
let rest = self.0.trim_left_matches(HTML_SPACE_CHARACTERS);
if rest.is_empty() {
return None;
}
if rest.starts_with('.') {
self.0 = &rest[rest.find(|c| c != '.').unwrap_or(rest.len())..];
return Some(Ok(None));
}
if !rest.starts_with(is_name_code_point) {
return Some(Err(()));
}
let token_len = rest.find(|c| !is_name_code_point(c)).unwrap_or(rest.len());
let token = &rest[..token_len];
self.0 = &rest[token_len..];
Some(Ok(Some(token)))
}
}
fn is_name_code_point(c: char) -> bool {
c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' ||
c >= '\u{80}' || c == '_' ||
c >= '0' && c <= '9' || c == '-'
}
/// This property specifies named grid areas.
/// The syntax of this property also provides a visualization of
/// the structure of the grid, making the overall layout of
/// the grid container easier to understand.
pub type GridTemplateAreas = Either<TemplateAreas, None_>;
impl GridTemplateAreas {
#[inline]
/// Get default value as `none`
pub fn none() -> GridTemplateAreas {
Either::Second(None_)
}
}