Permalink
Browse files

style: Use Rust lengths for margin / padding / inset.

Also for the intersection observer root margin, since it was easier to fix it
up and clean it up than not doing it.

This is the first big step to get rid of nscoord. It duplicates a bit of logic
in nsLayoutUtils since for now max/min-width/height are still represented with
nsStyleCoord, but I think I prefer to land this incrementally.

I didn't add helpers for the physical accessors of the style rect sides that
nsStyleSides has (top/bottom/left/right) since I think we generally should
encourage the logical versions, but let me know if you want me to do that.

Differential Revision: https://phabricator.services.mozilla.com/D17739
  • Loading branch information...
emilio committed Jan 26, 2019
1 parent 13e12d2 commit 8dad956513eba5cea9ce895c6f5351ff9f95c835
@@ -9,11 +9,15 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi
*/
#include "nsCoord.h"
#include "Units.h"
#include "mozilla/gfx/Types.h"
class nsAtom;
namespace mozilla {
class WritingMode;
enum LogicalSide : uint8_t;
namespace css {
struct URLValue;
}
// Work-around weird cbindgen renaming.
typedef css::URLValue StyleURLValue;
typedef nsAtom StylensAtom;
@@ -71,13 +75,17 @@ include = [
"Resize",
"Overflow",
"LengthPercentage",
"NonNegativeLengthPercentage",
"LengthPercentageOrAuto",
"Rect",
"IntersectionObserverRootMargin",
]
item_types = ["enums", "structs", "typedefs"]

[export.body]
"LengthPercentage" = """
// Defined in nsStyleCoord.h
static inline StyleLengthPercentage Zero();
static constexpr inline StyleLengthPercentage Zero();
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
@@ -90,3 +98,23 @@ item_types = ["enums", "structs", "typedefs"]
inline nscoord Resolve(nscoord aPercentageBasis) const;
template<typename T> inline nscoord ResolveWith(T aPercentageGetter) const;
"""

"LengthPercentageOrAuto" = """
inline const StyleLengthPercentage& AsLengthPercentage() const;
inline bool HasPercent() const;
inline bool ConvertsToLength() const;
"""

"Rect" = """
// Defined in nsStyleCoord.h
template<typename Predicate> inline bool All(Predicate) const;
template<typename Predicate> inline bool Any(Predicate) const;
// Defined in WritingModes.h
inline const T& Get(mozilla::Side) const;
inline const T& Get(mozilla::WritingMode, mozilla::LogicalSide) const;
inline const T& GetIStart(mozilla::WritingMode) const;
inline const T& GetBStart(mozilla::WritingMode) const;
inline const T& GetIEnd(mozilla::WritingMode) const;
inline const T& GetBEnd(mozilla::WritingMode) const;
"""
@@ -772,11 +772,12 @@ def set_gecko_property(ffi_name, expr):
<%def name="impl_split_style_coord(ident, gecko_ffi_name, index)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
v.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${index}));
self.gecko.${gecko_ffi_name}.${index} = v;
}
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
self.gecko.${gecko_ffi_name}.data_at_mut(${index}).copy_from(&other.gecko.${gecko_ffi_name}.data_at(${index}));
self.gecko.${gecko_ffi_name}.${index} =
other.gecko.${gecko_ffi_name}.${index};
}
#[allow(non_snake_case)]
pub fn reset_${ident}(&mut self, other: &Self) {
@@ -785,9 +786,7 @@ def set_gecko_property(ffi_name, expr):

#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use crate::properties::longhands::${ident}::computed_value::T;
T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name}.data_at(${index}))
.expect("clone for ${ident} failed")
self.gecko.${gecko_ffi_name}.${index}
}
</%def>

@@ -457,6 +457,7 @@ impl IsZeroLength for LengthPercentage {
#[derive(
Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss,
)]
#[repr(C, u8)]
pub enum LengthPercentageOrAuto {
LengthPercentage(LengthPercentage),
Auto,
@@ -23,6 +23,7 @@ use style_traits::{CssWriter, ParseError, ToCss};
ToAnimatedValue,
ToComputedValue,
)]
#[repr(C)]
pub struct Rect<T>(pub T, pub T, pub T, pub T);

impl<T> Rect<T> {
@@ -4,21 +4,19 @@

//! Specified types for legacy Gecko-only properties.

use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut};
use crate::parser::{Parse, ParserContext};
use crate::values::computed;
use crate::values::computed::{self, LengthPercentage};
use crate::values::computed::length::CSSPixelLength;
use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
use crate::values::generics::rect::Rect;
use crate::values::specified::length::LengthPercentage;
use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
use cssparser::{Parser, Token};
use std::fmt;
use style_traits::values::SequenceWriter;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};

/// A specified type for scroll snap points.
pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthPercentage>;
pub type ScrollSnapPoint = GenericScrollSnapPoint<SpecifiedLengthPercentage>;

impl Parse for ScrollSnapPoint {
fn parse<'i, 't>(
@@ -29,62 +27,34 @@ impl Parse for ScrollSnapPoint {
return Ok(GenericScrollSnapPoint::None);
}
input.expect_function_matching("repeat")?;
// FIXME(emilio): This won't clamp properly when animating.
let length =
input.parse_nested_block(|i| LengthPercentage::parse_non_negative(context, i))?;
input.parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?;
Ok(GenericScrollSnapPoint::Repeat(length))
}
}

/// A component of an IntersectionObserverRootMargin.
#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
pub enum PixelOrPercentage {
/// An absolute length in pixels (px)
Pixel(CSSPixelLength),
/// A percentage (%)
Percentage(computed::Percentage),
}

impl Parse for PixelOrPercentage {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let token = input.next()?;
let value = match *token {
Token::Dimension {
value, ref unit, ..
} => {
match_ignore_ascii_case! { unit,
"px" => Ok(PixelOrPercentage::Pixel(CSSPixelLength::new(value))),
_ => Err(()),
}
},
Token::Percentage { unit_value, .. } => Ok(PixelOrPercentage::Percentage(
computed::Percentage(unit_value),
)),
_ => Err(()),
};
value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}

impl GeckoStyleCoordConvertible for PixelOrPercentage {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
PixelOrPercentage::Pixel(ref l) => l.to_gecko_style_coord(coord),
PixelOrPercentage::Percentage(ref pc) => pc.to_gecko_style_coord(coord),
}
}

fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
CSSPixelLength::from_gecko_style_coord(coord)
.map(PixelOrPercentage::Pixel)
.or_else(|| {
computed::Percentage::from_gecko_style_coord(coord)
.map(PixelOrPercentage::Percentage)
})
}
fn parse_pixel_or_percent<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<LengthPercentage, ParseError<'i>> {
let location = input.current_source_location();
let token = input.next()?;
let value = match *token {
Token::Dimension {
value, ref unit, ..
} => {
match_ignore_ascii_case! { unit,
"px" => Ok(LengthPercentage::new(CSSPixelLength::new(value), None)),
_ => Err(()),
}
},
Token::Percentage { unit_value, .. } => Ok(
LengthPercentage::new_percent(computed::Percentage(unit_value))
),
_ => Err(()),
};
value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}

/// The value of an IntersectionObserver's rootMargin property.
@@ -93,14 +63,15 @@ impl GeckoStyleCoordConvertible for PixelOrPercentage {
/// calc() values are not allowed.
///
/// <https://w3c.github.io/IntersectionObserver/#parse-a-root-margin>
pub struct IntersectionObserverRootMargin(pub Rect<PixelOrPercentage>);
#[repr(transparent)]
pub struct IntersectionObserverRootMargin(pub Rect<LengthPercentage>);

impl Parse for IntersectionObserverRootMargin {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let rect = Rect::parse_with(context, input, PixelOrPercentage::parse)?;
let rect = Rect::parse_with(context, input, parse_pixel_or_percent)?;
Ok(IntersectionObserverRootMargin(rect))
}
}

0 comments on commit 8dad956

Please sign in to comment.