author | Anthony Ramine <n.oxyde@gmail.com> |
Thu, 04 May 2017 19:58:22 -0500 | |
changeset 356577 | 90c1a1964ca9113e4c0dbc050d527fc3434c0072 |
parent 356576 | beace30c107344274ebfa786ac723247e4ff413c |
child 356578 | e36712843b3bedb06bd08c081c27425d4a067f15 |
push id | 31767 |
push user | cbook@mozilla.com |
push date | Fri, 05 May 2017 13:15:58 +0000 |
treeherder | mozilla-central@8872ad4d52b6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Manishearth |
milestone | 55.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/servo/components/style/build_gecko.rs +++ b/servo/components/style/build_gecko.rs @@ -618,16 +618,17 @@ mod bindings { .hide_type("nsACString_internal") .hide_type("nsAString_internal") .raw_line("pub use nsstring::{nsACString, nsAString, nsString};") .raw_line("type nsACString_internal = nsACString;") .raw_line("type nsAString_internal = nsAString;") .whitelisted_function("Servo_.*") .whitelisted_function("Gecko_.*"); let structs_types = [ + "mozilla::css::GridTemplateAreasValue", "mozilla::css::URLValue", "mozilla::Side", "RawGeckoAnimationPropertySegment", "RawGeckoComputedTiming", "RawGeckoDocument", "RawGeckoElement", "RawGeckoKeyframeList", "RawGeckoComputedKeyframeValuesList",
--- a/servo/components/style/gecko_bindings/bindings.rs +++ b/servo/components/style/gecko_bindings/bindings.rs @@ -1,13 +1,14 @@ /* automatically generated by rust-bindgen */ pub use nsstring::{nsACString, nsAString, nsString}; type nsACString_internal = nsACString; type nsAString_internal = nsAString; +use gecko_bindings::structs::mozilla::css::GridTemplateAreasValue; use gecko_bindings::structs::mozilla::css::URLValue; use gecko_bindings::structs::mozilla::Side; use gecko_bindings::structs::RawGeckoAnimationPropertySegment; use gecko_bindings::structs::RawGeckoComputedTiming; use gecko_bindings::structs::RawGeckoDocument; use gecko_bindings::structs::RawGeckoElement; use gecko_bindings::structs::RawGeckoKeyframeList; use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList; @@ -889,16 +890,29 @@ extern "C" { } extern "C" { pub fn Gecko_CopyStyleGridTemplateValues(grid_template: *mut nsStyleGridTemplate, other: *const nsStyleGridTemplate); } extern "C" { + pub fn Gecko_NewGridTemplateAreasValue(areas: u32, templates: u32, + columns: u32) + -> *mut GridTemplateAreasValue; +} +extern "C" { + pub fn Gecko_AddRefGridTemplateAreasValueArbitraryThread(aPtr: + *mut GridTemplateAreasValue); +} +extern "C" { + pub fn Gecko_ReleaseGridTemplateAreasValueArbitraryThread(aPtr: + *mut GridTemplateAreasValue); +} +extern "C" { pub fn Gecko_ClearAndResizeStyleContents(content: *mut nsStyleContent, how_many: u32); } extern "C" { pub fn Gecko_ClearAndResizeCounterIncrements(content: *mut nsStyleContent, how_many: u32); } extern "C" {
--- a/servo/components/style/gecko_bindings/sugar/refptr.rs +++ b/servo/components/style/gecko_bindings/sugar/refptr.rs @@ -272,8 +272,11 @@ impl_threadsafe_refcount!(::gecko_bindin Gecko_AddRefQuoteValuesArbitraryThread, Gecko_ReleaseQuoteValuesArbitraryThread); impl_threadsafe_refcount!(::gecko_bindings::structs::nsCSSValueSharedList, Gecko_AddRefCSSValueSharedListArbitraryThread, Gecko_ReleaseCSSValueSharedListArbitraryThread); impl_threadsafe_refcount!(::gecko_bindings::structs::mozilla::css::URLValue, Gecko_AddRefCSSURLValueArbitraryThread, Gecko_ReleaseCSSURLValueArbitraryThread); +impl_threadsafe_refcount!(::gecko_bindings::structs::mozilla::css::GridTemplateAreasValue, + Gecko_AddRefGridTemplateAreasValueArbitraryThread, + Gecko_ReleaseGridTemplateAreasValueArbitraryThread);
--- a/servo/components/style/properties/gecko.mako.rs +++ b/servo/components/style/properties/gecko.mako.rs @@ -1047,17 +1047,18 @@ fn static_assert() { need_clone=True) %> % endfor </%self:impl_trait> <% skip_position_longhands = " ".join(x.ident for x in SIDES + GRID_LINES) %> <%self:impl_trait style_struct_name="Position" skip_longhands="${skip_position_longhands} z-index box-sizing order align-content justify-content align-self justify-self align-items - justify-items grid-auto-rows grid-auto-columns grid-auto-flow"> + justify-items grid-auto-rows grid-auto-columns grid-auto-flow + grid-template-areas"> % for side in SIDES: <% impl_split_style_coord("%s" % side.ident, "mOffset", side.index, need_clone=True) %> % endfor pub fn set_z_index(&mut self, v: longhands::z_index::computed_value::T) { @@ -1223,16 +1224,52 @@ fn static_assert() { self.gecko.mGridAutoFlow |= value as u8; if v.dense { self.gecko.mGridAutoFlow |= NS_STYLE_GRID_AUTO_FLOW_DENSE as u8; } } ${impl_simple_copy('grid_auto_flow', 'mGridAutoFlow')} + + pub fn set_grid_template_areas(&mut self, v: longhands::grid_template_areas::computed_value::T) { + use gecko_bindings::bindings::Gecko_NewGridTemplateAreasValue; + use gecko_bindings::sugar::refptr::UniqueRefPtr; + + let v = match v { + Either::First(areas) => areas, + Either::Second(_) => { + unsafe { self.gecko.mGridTemplateAreas.clear() } + return; + }, + }; + + let mut refptr = unsafe { + UniqueRefPtr::from_addrefed( + Gecko_NewGridTemplateAreasValue(v.areas.len() as u32, v.strings.len() as u32, v.width)) + }; + + for (servo, gecko) in v.areas.into_iter().zip(refptr.mNamedAreas.iter_mut()) { + gecko.mName.assign_utf8(&*servo.name); + gecko.mColumnStart = servo.columns.start; + gecko.mColumnEnd = servo.columns.end; + gecko.mRowStart = servo.rows.start; + gecko.mRowEnd = servo.rows.end; + } + + for (servo, gecko) in v.strings.into_iter().zip(refptr.mTemplates.iter_mut()) { + gecko.assign_utf8(&*servo); + } + + unsafe { self.gecko.mGridTemplateAreas.set_move(refptr.get()) } + } + + pub fn copy_grid_template_areas_from(&mut self, other: &Self) { + unsafe { self.gecko.mGridTemplateAreas.set(&other.gecko.mGridTemplateAreas) } + } </%self:impl_trait> <% skip_outline_longhands = " ".join("outline-style outline-width".split() + ["-moz-outline-radius-{0}".format(x.ident.replace("_", "")) for x in CORNERS]) %> <%self:impl_trait style_struct_name="Outline" skip_longhands="${skip_outline_longhands}" skip_additionals="*">
--- a/servo/components/style/properties/longhand/position.mako.rs +++ b/servo/components/style/properties/longhand/position.mako.rs @@ -401,8 +401,178 @@ autoflow: value.unwrap_or(AutoFlow::Row), dense: dense, }) } else { Err(()) } } </%helpers:longhand> + +<%helpers:longhand name="grid-template-areas" + spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas" + products="gecko" + animation_value_type="none" + disable_when_testing="True" + boxed="True"> + use cssparser::serialize_string; + use std::collections::HashMap; + use std::fmt; + use std::ops::Range; + use str::HTML_SPACE_CHARACTERS; + use style_traits::ToCss; + use style_traits::values::Css; + use values::HasViewportPercentage; + use values::computed::ComputedValueAsSpecified; + + 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(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { + SpecifiedValue::parse(context, input) + } + + #[derive(Clone, PartialEq)] + pub struct TemplateAreas { + pub areas: Box<[NamedArea]>, + pub strings: Box<[Box<str>]>, + pub width: u32, + } + + #[derive(Clone, PartialEq)] + pub struct NamedArea { + pub name: Box<str>, + pub rows: Range<u32>, + pub columns: Range<u32>, + } + + no_viewport_percentage!(TemplateAreas); + impl ComputedValueAsSpecified for TemplateAreas {} + + impl Parse for TemplateAreas { + fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { + let mut strings = vec![]; + while let Ok(string) = input.try(Parser::expect_string) { + strings.push(string.into_owned().into_boxed_str()); + } + if strings.is_empty() { + return Err(()); + } + let mut areas: Vec<NamedArea> = vec![]; + let mut width = 0; + { + let mut row = 0u32; + let mut area_indices = HashMap::<(&str), usize>::new(); + 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(" ")?; + } + serialize_string(string, 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>