style: Use rust lengths for border corners.

The test in https://github.com/web-platform-tests/wpt/pull/15423 hasn't been
synced over yet, but it passes with this patch of course.

Differential Revision: https://phabricator.services.mozilla.com/D20960
This commit is contained in:
Emilio Cobos Álvarez 2019-02-24 10:47:53 -08:00
parent aad4dac5b4
commit 197065f6bc
7 changed files with 51 additions and 174 deletions

View file

@ -13,6 +13,7 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi
class nsAtom; class nsAtom;
namespace mozilla { namespace mozilla {
class WritingMode; class WritingMode;
enum HalfCorner : uint8_t;
enum LogicalSide : uint8_t; enum LogicalSide : uint8_t;
namespace css { namespace css {
struct URLValue; struct URLValue;
@ -88,6 +89,8 @@ include = [
"Position", "Position",
"BackgroundSize", "BackgroundSize",
"BorderImageSlice", "BorderImageSlice",
"BorderSpacing",
"BorderRadius",
"NonNegativeLengthOrNumberRect", "NonNegativeLengthOrNumberRect",
"Perspective", "Perspective",
"ZIndex", "ZIndex",
@ -185,3 +188,7 @@ item_types = ["enums", "structs", "typedefs"]
inline const T& GetIEnd(mozilla::WritingMode) const; inline const T& GetIEnd(mozilla::WritingMode) const;
inline const T& GetBEnd(mozilla::WritingMode) const; inline const T& GetBEnd(mozilla::WritingMode) const;
""" """
"GenericBorderRadius" = """
inline const StyleLengthPercentage& Get(mozilla::HalfCorner) const;
"""

View file

@ -575,17 +575,15 @@ pub mod basic_shape {
//! Conversions from and to CSS shape representations. //! Conversions from and to CSS shape representations.
use crate::gecko::values::GeckoStyleCoordConvertible; use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCorners}; use crate::gecko_bindings::structs::nsStyleCoord;
use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType}; use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType};
use crate::gecko_bindings::structs::{ use crate::gecko_bindings::structs::{
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType, StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
}; };
use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
use crate::gecko_bindings::sugar::refptr::RefPtr; use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::values::computed::basic_shape::{ use crate::values::computed::basic_shape::{
BasicShape, ClippingShape, FloatAreaShape, ShapeRadius, BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
}; };
use crate::values::computed::border::{BorderCornerRadius, BorderRadius};
use crate::values::computed::length::LengthPercentage; use crate::values::computed::length::LengthPercentage;
use crate::values::computed::motion::OffsetPath; use crate::values::computed::motion::OffsetPath;
use crate::values::computed::url::ComputedUrl; use crate::values::computed::url::ComputedUrl;
@ -594,9 +592,7 @@ pub mod basic_shape {
}; };
use crate::values::generics::basic_shape::{Circle, Ellipse, Path, PolygonCoord}; use crate::values::generics::basic_shape::{Circle, Ellipse, Path, PolygonCoord};
use crate::values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource}; use crate::values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource};
use crate::values::generics::border::BorderRadius as GenericBorderRadius;
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::values::generics::NonNegative;
use crate::values::specified::SVGPathData; use crate::values::specified::SVGPathData;
use std::borrow::Borrow; use std::borrow::Borrow;
@ -706,7 +702,7 @@ pub mod basic_shape {
let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]); let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]); let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]); let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
let round: BorderRadius = (&other.mRadius).into(); let round = other.mRadius;
let round = if round.all_zero() { None } else { Some(round) }; let round = if round.all_zero() { None } else { Some(round) };
let rect = Rect::new( let rect = Rect::new(
t.expect("inset() offset should be a length, percentage, or calc value"), t.expect("inset() offset should be a length, percentage, or calc value"),
@ -752,65 +748,6 @@ pub mod basic_shape {
} }
} }
impl<'a> From<&'a nsStyleCorners> for BorderRadius {
fn from(other: &'a nsStyleCorners) -> Self {
let get_corner = |index| {
BorderCornerRadius::new(
NonNegative(
LengthPercentage::from_gecko_style_coord(&other.data_at(index)).expect(
"<border-radius> should be a length, percentage, or calc value",
),
),
NonNegative(
LengthPercentage::from_gecko_style_coord(&other.data_at(index + 1)).expect(
"<border-radius> should be a length, percentage, or calc value",
),
),
)
};
GenericBorderRadius {
top_left: get_corner(0),
top_right: get_corner(2),
bottom_right: get_corner(4),
bottom_left: get_corner(6),
}
}
}
// Can't be a From impl since we need to set an existing
// nsStyleCorners, not create a new one
impl BorderRadius {
/// Set this `BorderRadius` into a given `nsStyleCoord`.
pub fn set_corners(&self, other: &mut nsStyleCorners) {
let mut set_corner = |field: &BorderCornerRadius, index| {
field
.0
.width()
.to_gecko_style_coord(&mut other.data_at_mut(index));
field
.0
.height()
.to_gecko_style_coord(&mut other.data_at_mut(index + 1));
};
set_corner(&self.top_left, 0);
set_corner(&self.top_right, 2);
set_corner(&self.bottom_right, 4);
set_corner(&self.bottom_left, 6);
}
}
/// We use None for a nonexistant radius, but Gecko uses (0 0 0 0 / 0 0 0 0)
pub fn set_corners_from_radius(radius: Option<BorderRadius>, other: &mut nsStyleCorners) {
if let Some(radius) = radius {
radius.set_corners(other);
} else {
for i in 0..8 {
other.data_at_mut(i).set_value(CoordDataValue::Coord(0));
}
}
}
impl<'a> From<&'a nsStyleCoord> for ShapeRadius { impl<'a> From<&'a nsStyleCoord> for ShapeRadius {
fn from(other: &'a nsStyleCoord) -> Self { fn from(other: &'a nsStyleCoord) -> Self {
let other = other.borrow(); let other = other.borrow();

View file

@ -6,7 +6,7 @@
use crate::gecko_bindings::bindings; use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue}; use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue};
use crate::gecko_bindings::structs::{nsStyleCorners, nsStyleSides}; use crate::gecko_bindings::structs::nsStyleSides;
use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord}; use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord};
use std::mem; use std::mem;
@ -123,64 +123,6 @@ unsafe impl<'a> CoordDataMut for SidesDataMut<'a> {
} }
} }
impl nsStyleCorners {
/// Get a `nsStyleCoord` like object representing the given index's value
/// and unit.
#[inline]
pub fn data_at(&self, index: usize) -> CornersData {
CornersData {
corners: self,
index: index,
}
}
/// Get a `nsStyleCoord` like object representing the mutable given index's
/// value and unit.
#[inline]
pub fn data_at_mut(&mut self, index: usize) -> CornersDataMut {
CornersDataMut {
corners: self,
index: index,
}
}
}
/// A `nsStyleCoord`-like struct on top of `nsStyleCorners`.
pub struct CornersData<'a> {
corners: &'a nsStyleCorners,
index: usize,
}
/// A `nsStyleCoord`-like struct on top of a mutable `nsStyleCorners` reference.
pub struct CornersDataMut<'a> {
corners: &'a mut nsStyleCorners,
index: usize,
}
unsafe impl<'a> CoordData for CornersData<'a> {
fn unit(&self) -> nsStyleUnit {
unsafe { self.corners.get_mUnits()[self.index] }
}
fn union(&self) -> nsStyleUnion {
unsafe { self.corners.get_mValues()[self.index] }
}
}
unsafe impl<'a> CoordData for CornersDataMut<'a> {
fn unit(&self) -> nsStyleUnit {
unsafe { self.corners.get_mUnits()[self.index] }
}
fn union(&self) -> nsStyleUnion {
unsafe { self.corners.get_mValues()[self.index] }
}
}
unsafe impl<'a> CoordDataMut for CornersDataMut<'a> {
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
let unit = &mut self.corners.get_mUnits_mut()[self.index] as *mut _;
let value = &mut self.corners.get_mValues_mut()[self.index] as *mut _;
(&mut *unit, &mut *value)
}
}
/// Enum representing the tagged union that is CoordData. /// Enum representing the tagged union that is CoordData.
/// ///
/// In release mode this should never actually exist in the code, and will be /// In release mode this should never actually exist in the code, and will be

View file

@ -52,7 +52,7 @@ use crate::rule_tree::StrongRuleNode;
use crate::selector_parser::PseudoElement; use crate::selector_parser::PseudoElement;
use servo_arc::{Arc, RawOffsetArc}; use servo_arc::{Arc, RawOffsetArc};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::{forget, uninitialized, transmute, zeroed}; use std::mem::{forget, uninitialized, zeroed};
use std::{cmp, ops, ptr}; use std::{cmp, ops, ptr};
use crate::values::{self, CustomIdent, Either, KeyframesName, None_}; use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty}; use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
@ -817,34 +817,23 @@ def set_gecko_property(ffi_name, expr):
} }
</%def> </%def>
<%def name="impl_corner_style_coord(ident, gecko_ffi_name, x_index, y_index)"> <%def name="impl_corner_style_coord(ident, gecko_ffi_name, corner)">
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
v.0.width().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${x_index})); self.gecko.${gecko_ffi_name}.${corner} = v;
v.0.height().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) { pub fn copy_${ident}_from(&mut self, other: &Self) {
self.gecko.${gecko_ffi_name}.data_at_mut(${x_index}) self.gecko.${gecko_ffi_name}.${corner} =
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${x_index})); other.gecko.${gecko_ffi_name}.${corner};
self.gecko.${gecko_ffi_name}.data_at_mut(${y_index})
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${y_index}));
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn reset_${ident}(&mut self, other: &Self) { pub fn reset_${ident}(&mut self, other: &Self) {
self.copy_${ident}_from(other) self.copy_${ident}_from(other)
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use crate::values::computed::border::BorderCornerRadius; self.gecko.${gecko_ffi_name}.${corner}
let width = GeckoStyleCoordConvertible::from_gecko_style_coord(
&self.gecko.${gecko_ffi_name}.data_at(${x_index}))
.expect("Failed to clone ${ident}");
let height = GeckoStyleCoordConvertible::from_gecko_style_coord(
&self.gecko.${gecko_ffi_name}.data_at(${y_index}))
.expect("Failed to clone ${ident}");
BorderCornerRadius::new(width, height)
} }
</%def> </%def>
@ -1387,14 +1376,6 @@ class Side(object):
self.ident = name.lower() self.ident = name.lower()
self.index = index self.index = index
class Corner(object):
def __init__(self, vert, horiz, index):
self.x_name = "HalfCorner::eCorner" + vert + horiz + "X"
self.y_name = "HalfCorner::eCorner" + vert + horiz + "Y"
self.ident = (vert + "_" + horiz).lower()
self.x_index = 2 * index
self.y_index = 2 * index + 1
class GridLine(object): class GridLine(object):
def __init__(self, name): def __init__(self, name):
self.ident = "grid-" + name.lower() self.ident = "grid-" + name.lower()
@ -1402,19 +1383,12 @@ class GridLine(object):
self.gecko = "m" + to_camel_case(self.ident) self.gecko = "m" + to_camel_case(self.ident)
SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)] SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
CORNERS = [Corner("Top", "Left", 0), Corner("Top", "Right", 1), CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"]
Corner("Bottom", "Right", 2), Corner("Bottom", "Left", 3)]
GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"]) GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
%> %>
#[allow(dead_code)] #[allow(dead_code)]
fn static_assert() { fn static_assert() {
unsafe {
% for corner in CORNERS:
transmute::<_, [u32; ${corner.x_index}]>([1; structs::${corner.x_name} as usize]);
transmute::<_, [u32; ${corner.y_index}]>([1; structs::${corner.y_name} as usize]);
% endfor
}
// Note: using the above technique with an enum hits a rust bug when |structs| is in a different crate. // Note: using the above technique with an enum hits a rust bug when |structs| is in a different crate.
% for side in SIDES: % for side in SIDES:
{ const DETAIL: u32 = [0][(structs::Side::eSide${side.name} as usize != ${side.index}) as usize]; let _ = DETAIL; } { const DETAIL: u32 = [0][(structs::Side::eSide${side.name} as usize != ${side.index}) as usize]; let _ = DETAIL; }
@ -1425,7 +1399,7 @@ fn static_assert() {
<% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y) <% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
for x in SIDES for x in SIDES
for y in ["color", "style", "width"]] + for y in ["color", "style", "width"]] +
["border-{0}-radius".format(x.ident.replace("_", "-")) ["border-{0}-radius".format(x.replace("_", "-"))
for x in CORNERS]) %> for x in CORNERS]) %>
<%self:impl_trait style_struct_name="Border" <%self:impl_trait style_struct_name="Border"
@ -1494,10 +1468,9 @@ fn static_assert() {
% endfor % endfor
% for corner in CORNERS: % for corner in CORNERS:
<% impl_corner_style_coord("border_%s_radius" % corner.ident, <% impl_corner_style_coord("border_%s_radius" % corner,
"mBorderRadius", "mBorderRadius",
corner.x_index, corner) %>
corner.y_index) %>
% endfor % endfor
pub fn set_border_image_source(&mut self, image: longhands::border_image_source::computed_value::T) { pub fn set_border_image_source(&mut self, image: longhands::border_image_source::computed_value::T) {
@ -2027,7 +2000,7 @@ fn static_assert() {
</%self:impl_trait> </%self:impl_trait>
<% skip_outline_longhands = " ".join("outline-style outline-width".split() + <% skip_outline_longhands = " ".join("outline-style outline-width".split() +
["-moz-outline-radius-{0}".format(x.ident.replace("_", "")) ["-moz-outline-radius-{0}".format(x.replace("_", ""))
for x in CORNERS]) %> for x in CORNERS]) %>
<%self:impl_trait style_struct_name="Outline" <%self:impl_trait style_struct_name="Outline"
skip_longhands="${skip_outline_longhands}"> skip_longhands="${skip_outline_longhands}">
@ -2059,10 +2032,9 @@ fn static_assert() {
round_to_pixels=True) %> round_to_pixels=True) %>
% for corner in CORNERS: % for corner in CORNERS:
<% impl_corner_style_coord("_moz_outline_radius_%s" % corner.ident.replace("_", ""), <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.replace("_", ""),
"mOutlineRadius", "mOutlineRadius",
corner.x_index, corner) %>
corner.y_index) %>
% endfor % endfor
pub fn outline_has_nonzero_width(&self) -> bool { pub fn outline_has_nonzero_width(&self) -> bool {
@ -4593,7 +4565,6 @@ fn set_style_svg_path(
use crate::gecko_bindings::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource}; use crate::gecko_bindings::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource};
use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType}; use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType};
use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource}; use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource};
use crate::gecko::conversions::basic_shape::set_corners_from_radius;
use crate::gecko::values::GeckoStyleCoordConvertible; use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::values::generics::basic_shape::{BasicShape, ShapeSource}; use crate::values::generics::basic_shape::{BasicShape, ShapeSource};
@ -4658,8 +4629,10 @@ fn set_style_svg_path(
inset.rect.2.to_gecko_style_coord(&mut shape.mCoordinates[2]); inset.rect.2.to_gecko_style_coord(&mut shape.mCoordinates[2]);
shape.mCoordinates[3].leaky_set_null(); shape.mCoordinates[3].leaky_set_null();
inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]); inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
shape.mRadius = match inset.round {
set_corners_from_radius(inset.round, &mut shape.mRadius); Some(radius) => radius,
None => crate::values::computed::BorderRadius::zero(),
};
} }
BasicShape::Circle(circ) => { BasicShape::Circle(circ) => {
let shape = init_shape(${ident}, StyleBasicShapeType::Circle); let shape = init_shape(${ident}, StyleBasicShapeType::Circle);

View file

@ -87,6 +87,16 @@ impl BorderCornerRadius {
} }
impl BorderRadius { impl BorderRadius {
/// Returns a `0` border radius.
pub fn zero() -> Self {
Self {
top_left: BorderCornerRadius::zero(),
top_right: BorderCornerRadius::zero(),
bottom_right: BorderCornerRadius::zero(),
bottom_left: BorderCornerRadius::zero(),
}
}
/// Returns whether all the values are `0px`. /// Returns whether all the values are `0px`.
pub fn all_zero(&self) -> bool { pub fn all_zero(&self) -> bool {
fn all(corner: &BorderCornerRadius) -> bool { fn all(corner: &BorderCornerRadius) -> bool {

View file

@ -53,7 +53,10 @@ pub use self::GenericBorderImageSlice as BorderImageSlice;
ToComputedValue, ToComputedValue,
ToCss, ToCss,
)] )]
pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>); #[repr(C)]
pub struct GenericBorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>);
pub use self::GenericBorderCornerRadius as BorderCornerRadius;
impl<L> BorderCornerRadius<L> { impl<L> BorderCornerRadius<L> {
/// Trivially create a `BorderCornerRadius`. /// Trivially create a `BorderCornerRadius`.
@ -77,6 +80,7 @@ impl<L> BorderCornerRadius<L> {
ToComputedValue, ToComputedValue,
ToCss, ToCss,
)] )]
#[repr(transparent)]
pub struct BorderSpacing<L>(#[css(field_bound)] pub Size2D<L>); pub struct BorderSpacing<L>(#[css(field_bound)] pub Size2D<L>);
impl<L> BorderSpacing<L> { impl<L> BorderSpacing<L> {
@ -101,17 +105,20 @@ impl<L> BorderSpacing<L> {
ToAnimatedValue, ToAnimatedValue,
ToComputedValue, ToComputedValue,
)] )]
pub struct BorderRadius<LengthPercentage> { #[repr(C)]
pub struct GenericBorderRadius<LengthPercentage> {
/// The top left radius. /// The top left radius.
pub top_left: BorderCornerRadius<LengthPercentage>, pub top_left: GenericBorderCornerRadius<LengthPercentage>,
/// The top right radius. /// The top right radius.
pub top_right: BorderCornerRadius<LengthPercentage>, pub top_right: GenericBorderCornerRadius<LengthPercentage>,
/// The bottom right radius. /// The bottom right radius.
pub bottom_right: BorderCornerRadius<LengthPercentage>, pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
/// The bottom left radius. /// The bottom left radius.
pub bottom_left: BorderCornerRadius<LengthPercentage>, pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
} }
pub use self::GenericBorderRadius as BorderRadius;
impl<L> BorderRadius<L> { impl<L> BorderRadius<L> {
/// Returns a new `BorderRadius<L>`. /// Returns a new `BorderRadius<L>`.
#[inline] #[inline]

View file

@ -25,6 +25,7 @@ use style_traits::{CssWriter, ParseError, ToCss};
ToComputedValue, ToComputedValue,
)] )]
#[allow(missing_docs)] #[allow(missing_docs)]
#[repr(C)]
pub struct Size2D<L> { pub struct Size2D<L> {
pub width: L, pub width: L,
pub height: L, pub height: L,