mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
style: Use Servo for the representation of grid template areas.
Right now we do a lot of useless string copying. In order to avoid transcoding to utf-16 during layout, make sure to use nsCString at a few related places. I may revisit this since we're storing other line names as atoms in some places. So it may be better to just use atoms everywhere. But that'd be a different patch either way. Differential Revision: https://phabricator.services.mozilla.com/D35117
This commit is contained in:
parent
e8271ee926
commit
6cb588d2b5
4 changed files with 68 additions and 130 deletions
|
@ -308,11 +308,6 @@ impl_threadsafe_refcount!(
|
|||
bindings::Gecko_AddRefnsIURIArbitraryThread,
|
||||
bindings::Gecko_ReleasensIURIArbitraryThread
|
||||
);
|
||||
impl_threadsafe_refcount!(
|
||||
structs::mozilla::css::GridTemplateAreasValue,
|
||||
bindings::Gecko_AddRefGridTemplateAreasValueArbitraryThread,
|
||||
bindings::Gecko_ReleaseGridTemplateAreasValueArbitraryThread
|
||||
);
|
||||
impl_threadsafe_refcount!(
|
||||
structs::SharedFontList,
|
||||
bindings::Gecko_AddRefSharedFontListArbitraryThread,
|
||||
|
@ -328,6 +323,7 @@ impl_threadsafe_refcount!(
|
|||
unsafe fn addref_atom(atom: *mut structs::nsAtom) {
|
||||
mem::forget(Atom::from_raw(atom));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn release_atom(atom: *mut structs::nsAtom) {
|
||||
let _ = Atom::from_addrefed(atom);
|
||||
|
|
|
@ -1083,8 +1083,8 @@ fn static_assert() {
|
|||
align-content justify-content align-self
|
||||
justify-self align-items justify-items
|
||||
grid-auto-rows grid-auto-columns
|
||||
grid-auto-flow grid-template-areas
|
||||
grid-template-rows grid-template-columns">
|
||||
grid-auto-flow grid-template-rows
|
||||
grid-template-columns">
|
||||
% for side in SIDES:
|
||||
<% impl_split_style_coord(side.ident, "mOffset", side.index) %>
|
||||
% endfor
|
||||
|
@ -1136,13 +1136,19 @@ fn static_assert() {
|
|||
pub fn set_${value.name}(&mut self, v: longhands::${value.name}::computed_value::T) {
|
||||
use crate::gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine};
|
||||
|
||||
let ident = v.ident.as_ref().map_or(&[] as &[_], |ident| ident.0.as_slice());
|
||||
self.gecko.${value.gecko}.mLineName.assign(ident);
|
||||
self.gecko.${value.gecko}.mHasSpan = v.is_span;
|
||||
let line = &mut self.gecko.${value.gecko};
|
||||
let line_name = &mut line.mLineName;
|
||||
match v.ident.as_ref() {
|
||||
Some(i) => i.0.with_str(|s| line_name.assign(s)),
|
||||
None => line_name.assign(""),
|
||||
};
|
||||
line.mHasSpan = v.is_span;
|
||||
if let Some(integer) = v.line_num {
|
||||
// clamping the integer between a range
|
||||
self.gecko.${value.gecko}.mInteger = cmp::max(nsStyleGridLine_kMinLine,
|
||||
cmp::min(integer, nsStyleGridLine_kMaxLine));
|
||||
line.mInteger = cmp::max(
|
||||
nsStyleGridLine_kMinLine,
|
||||
cmp::min(integer, nsStyleGridLine_kMaxLine),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1205,20 +1211,20 @@ fn static_assert() {
|
|||
pub fn set_grid_template_${kind}(&mut self, v: longhands::grid_template_${kind}::computed_value::T) {
|
||||
<% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
|
||||
use crate::gecko_bindings::structs::{nsTArray, nsStyleGridLine_kMaxLine};
|
||||
use nsstring::nsString;
|
||||
use nsstring::nsCString;
|
||||
use std::usize;
|
||||
use crate::values::CustomIdent;
|
||||
use crate::values::generics::grid::TrackListType::Auto;
|
||||
use crate::values::generics::grid::{GridTemplateComponent, RepeatCount};
|
||||
|
||||
#[inline]
|
||||
fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<nsString>) {
|
||||
fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<nsCString>) {
|
||||
unsafe {
|
||||
bindings::Gecko_ResizeTArrayForStrings(gecko_names, servo_names.len() as u32);
|
||||
bindings::Gecko_ResizeTArrayForCStrings(gecko_names, servo_names.len() as u32);
|
||||
}
|
||||
|
||||
for (servo_name, gecko_name) in servo_names.iter().zip(gecko_names.iter_mut()) {
|
||||
gecko_name.assign(servo_name.0.as_slice());
|
||||
servo_name.0.with_str(|s| gecko_name.assign(s))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1256,9 +1262,9 @@ fn static_assert() {
|
|||
auto_track_size = Some(auto_repeat.track_sizes.get(0).unwrap().clone());
|
||||
} else {
|
||||
unsafe {
|
||||
bindings::Gecko_ResizeTArrayForStrings(
|
||||
bindings::Gecko_ResizeTArrayForCStrings(
|
||||
&mut value.mRepeatAutoLineNameListBefore, 0);
|
||||
bindings::Gecko_ResizeTArrayForStrings(
|
||||
bindings::Gecko_ResizeTArrayForCStrings(
|
||||
&mut value.mRepeatAutoLineNameListAfter, 0);
|
||||
}
|
||||
}
|
||||
|
@ -1332,7 +1338,7 @@ fn static_assert() {
|
|||
pub fn clone_grid_template_${kind}(&self) -> longhands::grid_template_${kind}::computed_value::T {
|
||||
<% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
|
||||
use crate::gecko_bindings::structs::nsTArray;
|
||||
use nsstring::nsString;
|
||||
use nsstring::nsCString;
|
||||
use crate::values::CustomIdent;
|
||||
use crate::values::generics::grid::{GridTemplateComponent, LineNameList, RepeatCount};
|
||||
use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue, TrackRepeat, TrackSize};
|
||||
|
@ -1343,15 +1349,15 @@ fn static_assert() {
|
|||
};
|
||||
|
||||
#[inline]
|
||||
fn to_boxed_customident_slice(gecko_names: &nsTArray<nsString>) -> Box<[CustomIdent]> {
|
||||
fn to_boxed_customident_slice(gecko_names: &nsTArray<nsCString>) -> Box<[CustomIdent]> {
|
||||
let idents: Vec<CustomIdent> = gecko_names.iter().map(|gecko_name| {
|
||||
CustomIdent(Atom::from(gecko_name.to_string()))
|
||||
CustomIdent(Atom::from(unsafe { gecko_name.as_str_unchecked() }))
|
||||
}).collect();
|
||||
idents.into_boxed_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_line_names_vec(gecko_line_names: &nsTArray<nsTArray<nsString>>)
|
||||
fn to_line_names_vec(gecko_line_names: &nsTArray<nsTArray<nsCString>>)
|
||||
-> Vec<Box<[CustomIdent]>> {
|
||||
gecko_line_names.iter().map(|gecko_names| {
|
||||
to_boxed_customident_slice(gecko_names)
|
||||
|
@ -1415,88 +1421,6 @@ fn static_assert() {
|
|||
% endfor
|
||||
|
||||
${impl_simple_type_with_conversion("grid_auto_flow")}
|
||||
|
||||
pub fn set_grid_template_areas(&mut self, v: values::computed::position::GridTemplateAreas) {
|
||||
use crate::gecko_bindings::bindings::Gecko_NewGridTemplateAreasValue;
|
||||
use crate::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.0.areas.len() as u32, v.0.strings.len() as u32, v.0.width))
|
||||
};
|
||||
|
||||
for (servo, gecko) in v.0.areas.iter().zip(refptr.mNamedAreas.iter_mut()) {
|
||||
gecko.mName.assign_str(&*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.0.strings.iter().zip(refptr.mTemplates.iter_mut()) {
|
||||
gecko.assign_str(&*servo);
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
|
||||
pub fn reset_grid_template_areas(&mut self, other: &Self) {
|
||||
self.copy_grid_template_areas_from(other)
|
||||
}
|
||||
|
||||
pub fn clone_grid_template_areas(&self) -> values::computed::position::GridTemplateAreas {
|
||||
use crate::values::None_;
|
||||
use crate::values::specified::position::{NamedArea, TemplateAreas, TemplateAreasArc, UnsignedRange};
|
||||
|
||||
if self.gecko.mGridTemplateAreas.mRawPtr.is_null() {
|
||||
return Either::Second(None_);
|
||||
}
|
||||
|
||||
let gecko_grid_template_areas = self.gecko.mGridTemplateAreas.mRawPtr;
|
||||
let areas = unsafe {
|
||||
let vec: Vec<NamedArea> =
|
||||
(*gecko_grid_template_areas).mNamedAreas.iter().map(|gecko_name_area| {
|
||||
let name = gecko_name_area.mName.to_string().into();
|
||||
let rows = UnsignedRange {
|
||||
start: gecko_name_area.mRowStart,
|
||||
end: gecko_name_area.mRowEnd
|
||||
};
|
||||
let columns = UnsignedRange {
|
||||
start: gecko_name_area.mColumnStart,
|
||||
end: gecko_name_area.mColumnEnd
|
||||
};
|
||||
NamedArea { name, rows, columns }
|
||||
}).collect();
|
||||
vec.into()
|
||||
};
|
||||
|
||||
let strings = unsafe {
|
||||
let vec: Vec<crate::OwnedStr> =
|
||||
(*gecko_grid_template_areas).mTemplates.iter().map(|gecko_template| {
|
||||
gecko_template.to_string().into()
|
||||
}).collect();
|
||||
vec.into()
|
||||
};
|
||||
|
||||
let width = unsafe {
|
||||
(*gecko_grid_template_areas).mNColumns
|
||||
};
|
||||
|
||||
Either::First(TemplateAreasArc(Arc::new(TemplateAreas { areas, strings, width })))
|
||||
}
|
||||
|
||||
</%self:impl_trait>
|
||||
|
||||
<% skip_outline_longhands = " ".join("outline-style outline-width".split() +
|
||||
|
|
|
@ -253,18 +253,17 @@
|
|||
products="gecko">
|
||||
use crate::parser::Parse;
|
||||
use servo_arc::Arc;
|
||||
use crate::values::{Either, None_};
|
||||
use crate::values::generics::grid::{TrackSize, TrackList, TrackListType};
|
||||
use crate::values::generics::grid::{TrackListValue, concat_serialize_idents};
|
||||
use crate::values::specified::{GridTemplateComponent, GenericGridTemplateComponent};
|
||||
use crate::values::specified::grid::parse_line_names;
|
||||
use crate::values::specified::position::{TemplateAreas, TemplateAreasArc};
|
||||
use crate::values::specified::position::{GridTemplateAreas, TemplateAreas, TemplateAreasArc};
|
||||
|
||||
/// Parsing for `<grid-template>` shorthand (also used by `grid` shorthand).
|
||||
pub fn parse_grid_template<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<(GridTemplateComponent, GridTemplateComponent, Either<TemplateAreasArc, None_>), ParseError<'i>> {
|
||||
) -> Result<(GridTemplateComponent, GridTemplateComponent, GridTemplateAreas), ParseError<'i>> {
|
||||
// Other shorthand sub properties also parse the `none` keyword and this shorthand
|
||||
// should know after this keyword there is nothing to parse. Otherwise it gets
|
||||
// confused and rejects the sub properties that contains `none`.
|
||||
|
@ -275,13 +274,10 @@
|
|||
% for keyword, rust_type in keywords.items():
|
||||
if let Ok(x) = input.try(|i| {
|
||||
if i.try(|i| i.expect_ident_matching("${keyword}")).is_ok() {
|
||||
if i.is_exhausted() {
|
||||
return Ok((${rust_type},
|
||||
${rust_type},
|
||||
Either::Second(None_)))
|
||||
} else {
|
||||
if !i.is_exhausted() {
|
||||
return Err(());
|
||||
}
|
||||
return Ok((${rust_type}, ${rust_type}, GridTemplateAreas::None));
|
||||
}
|
||||
Err(())
|
||||
}) {
|
||||
|
@ -342,7 +338,7 @@
|
|||
};
|
||||
|
||||
Ok((GenericGridTemplateComponent::TrackList(template_rows),
|
||||
template_cols, Either::First(TemplateAreasArc(Arc::new(template_areas)))))
|
||||
template_cols, GridTemplateAreas::Areas(TemplateAreasArc(Arc::new(template_areas)))))
|
||||
} else {
|
||||
let mut template_rows = GridTemplateComponent::parse(context, input)?;
|
||||
if let GenericGridTemplateComponent::TrackList(ref mut list) = template_rows {
|
||||
|
@ -356,7 +352,7 @@
|
|||
}
|
||||
|
||||
input.expect_delim('/')?;
|
||||
Ok((template_rows, GridTemplateComponent::parse(context, input)?, Either::Second(None_)))
|
||||
Ok((template_rows, GridTemplateComponent::parse(context, input)?, GridTemplateAreas::None))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,18 +373,18 @@
|
|||
pub fn serialize_grid_template<W>(
|
||||
template_rows: &GridTemplateComponent,
|
||||
template_columns: &GridTemplateComponent,
|
||||
template_areas: &Either<TemplateAreasArc, None_>,
|
||||
template_areas: &GridTemplateAreas,
|
||||
dest: &mut CssWriter<W>,
|
||||
) -> fmt::Result
|
||||
where
|
||||
W: Write {
|
||||
match *template_areas {
|
||||
Either::Second(_none) => {
|
||||
GridTemplateAreas::None => {
|
||||
template_rows.to_css(dest)?;
|
||||
dest.write_str(" / ")?;
|
||||
template_columns.to_css(dest)
|
||||
},
|
||||
Either::First(ref areas) => {
|
||||
GridTemplateAreas::Areas(ref areas) => {
|
||||
// The length of template-area and template-rows values should be equal.
|
||||
if areas.0.strings.len() != template_rows.track_list_len() {
|
||||
return Ok(());
|
||||
|
@ -485,10 +481,9 @@
|
|||
products="gecko">
|
||||
use crate::parser::Parse;
|
||||
use crate::properties::longhands::{grid_auto_columns, grid_auto_rows, grid_auto_flow};
|
||||
use crate::values::{Either, None_};
|
||||
use crate::values::generics::grid::{GridTemplateComponent, TrackListType};
|
||||
use crate::values::specified::{GenericGridTemplateComponent, TrackSize};
|
||||
use crate::values::specified::position::{AutoFlow, GridAutoFlow};
|
||||
use crate::values::specified::position::{AutoFlow, GridAutoFlow, GridTemplateAreas};
|
||||
|
||||
pub fn parse_value<'i, 't>(
|
||||
context: &ParserContext,
|
||||
|
@ -496,7 +491,7 @@
|
|||
) -> Result<Longhands, ParseError<'i>> {
|
||||
let mut temp_rows = GridTemplateComponent::None;
|
||||
let mut temp_cols = GridTemplateComponent::None;
|
||||
let mut temp_areas = Either::Second(None_);
|
||||
let mut temp_areas = GridTemplateAreas::None;
|
||||
let mut auto_rows = TrackSize::default();
|
||||
let mut auto_cols = TrackSize::default();
|
||||
let mut flow = grid_auto_flow::get_initial_value();
|
||||
|
@ -558,7 +553,7 @@
|
|||
impl<'a> LonghandsToSerialize<'a> {
|
||||
/// Returns true if other sub properties except template-{rows,columns} are initial.
|
||||
fn is_grid_template(&self) -> bool {
|
||||
*self.grid_template_areas == Either::Second(None_) &&
|
||||
*self.grid_template_areas == GridTemplateAreas::None &&
|
||||
*self.grid_auto_rows == TrackSize::default() &&
|
||||
*self.grid_auto_columns == TrackSize::default() &&
|
||||
*self.grid_auto_flow == grid_auto_flow::get_initial_value()
|
||||
|
@ -567,7 +562,7 @@
|
|||
|
||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||
if *self.grid_template_areas != Either::Second(None_) ||
|
||||
if *self.grid_template_areas != GridTemplateAreas::None ||
|
||||
(*self.grid_template_rows != GridTemplateComponent::None &&
|
||||
*self.grid_template_columns != GridTemplateComponent::None) ||
|
||||
self.is_grid_template() {
|
||||
|
|
|
@ -15,7 +15,6 @@ use crate::values::computed::{Context, Percentage, ToComputedValue};
|
|||
use crate::values::generics::position::Position as GenericPosition;
|
||||
use crate::values::generics::position::ZIndex as GenericZIndex;
|
||||
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
|
||||
use crate::values::{Either, None_};
|
||||
use crate::Zero;
|
||||
use cssparser::Parser;
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
|
@ -477,6 +476,7 @@ impl From<GridAutoFlow> for u8 {
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
/// https://drafts.csswg.org/css-grid/#named-grid-area
|
||||
pub struct TemplateAreas {
|
||||
/// `named area` containing for each template area
|
||||
|
@ -599,6 +599,7 @@ impl Parse for TemplateAreas {
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct TemplateAreasArc(#[ignore_malloc_size_of = "Arc"] pub Arc<TemplateAreas>);
|
||||
|
||||
impl Parse for TemplateAreasArc {
|
||||
|
@ -623,8 +624,9 @@ pub struct UnsignedRange {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)]
|
||||
/// Not associated with any particular grid item, but can
|
||||
/// be referenced from the grid-placement properties.
|
||||
#[repr(C)]
|
||||
/// 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: crate::OwnedStr,
|
||||
|
@ -670,16 +672,37 @@ fn is_name_code_point(c: char) -> bool {
|
|||
}
|
||||
|
||||
/// 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<TemplateAreasArc, None_>;
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[repr(C, u8)]
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
pub enum GridTemplateAreas {
|
||||
/// The `none` value.
|
||||
None,
|
||||
/// The actual value.
|
||||
Areas(TemplateAreasArc),
|
||||
}
|
||||
|
||||
impl GridTemplateAreas {
|
||||
#[inline]
|
||||
/// Get default value as `none`
|
||||
pub fn none() -> GridTemplateAreas {
|
||||
Either::Second(None_)
|
||||
GridTemplateAreas::None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue