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;
namespace mozilla {
class WritingMode;
enum HalfCorner : uint8_t;
enum LogicalSide : uint8_t;
namespace css {
struct URLValue;
@ -88,6 +89,8 @@ include = [
"Position",
"BackgroundSize",
"BorderImageSlice",
"BorderSpacing",
"BorderRadius",
"NonNegativeLengthOrNumberRect",
"Perspective",
"ZIndex",
@ -185,3 +188,7 @@ item_types = ["enums", "structs", "typedefs"]
inline const T& GetIEnd(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.
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::{
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
};
use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::values::computed::basic_shape::{
BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
};
use crate::values::computed::border::{BorderCornerRadius, BorderRadius};
use crate::values::computed::length::LengthPercentage;
use crate::values::computed::motion::OffsetPath;
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::{GeometryBox, ShapeBox, ShapeSource};
use crate::values::generics::border::BorderRadius as GenericBorderRadius;
use crate::values::generics::rect::Rect;
use crate::values::generics::NonNegative;
use crate::values::specified::SVGPathData;
use std::borrow::Borrow;
@ -706,7 +702,7 @@ pub mod basic_shape {
let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
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 rect = Rect::new(
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 {
fn from(other: &'a nsStyleCoord) -> Self {
let other = other.borrow();

View file

@ -6,7 +6,7 @@
use crate::gecko_bindings::bindings;
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 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.
///
/// 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 servo_arc::{Arc, RawOffsetArc};
use std::marker::PhantomData;
use std::mem::{forget, uninitialized, transmute, zeroed};
use std::mem::{forget, uninitialized, zeroed};
use std::{cmp, ops, ptr};
use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
@ -817,34 +817,23 @@ def set_gecko_property(ffi_name, expr):
}
</%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)]
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}));
v.0.height().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
self.gecko.${gecko_ffi_name}.${corner} = v;
}
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
self.gecko.${gecko_ffi_name}.data_at_mut(${x_index})
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${x_index}));
self.gecko.${gecko_ffi_name}.data_at_mut(${y_index})
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${y_index}));
self.gecko.${gecko_ffi_name}.${corner} =
other.gecko.${gecko_ffi_name}.${corner};
}
#[allow(non_snake_case)]
pub fn reset_${ident}(&mut self, other: &Self) {
self.copy_${ident}_from(other)
}
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use crate::values::computed::border::BorderCornerRadius;
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)
self.gecko.${gecko_ffi_name}.${corner}
}
</%def>
@ -1387,14 +1376,6 @@ class Side(object):
self.ident = name.lower()
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):
def __init__(self, name):
self.ident = "grid-" + name.lower()
@ -1402,19 +1383,12 @@ class GridLine(object):
self.gecko = "m" + to_camel_case(self.ident)
SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
CORNERS = [Corner("Top", "Left", 0), Corner("Top", "Right", 1),
Corner("Bottom", "Right", 2), Corner("Bottom", "Left", 3)]
CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"]
GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
%>
#[allow(dead_code)]
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.
% for side in SIDES:
{ 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)
for x in SIDES
for y in ["color", "style", "width"]] +
["border-{0}-radius".format(x.ident.replace("_", "-"))
["border-{0}-radius".format(x.replace("_", "-"))
for x in CORNERS]) %>
<%self:impl_trait style_struct_name="Border"
@ -1494,10 +1468,9 @@ fn static_assert() {
% endfor
% for corner in CORNERS:
<% impl_corner_style_coord("border_%s_radius" % corner.ident,
<% impl_corner_style_coord("border_%s_radius" % corner,
"mBorderRadius",
corner.x_index,
corner.y_index) %>
corner) %>
% endfor
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>
<% 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]) %>
<%self:impl_trait style_struct_name="Outline"
skip_longhands="${skip_outline_longhands}">
@ -2059,10 +2032,9 @@ fn static_assert() {
round_to_pixels=True) %>
% 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",
corner.x_index,
corner.y_index) %>
corner) %>
% endfor
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::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType};
use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource};
use crate::gecko::conversions::basic_shape::set_corners_from_radius;
use crate::gecko::values::GeckoStyleCoordConvertible;
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]);
shape.mCoordinates[3].leaky_set_null();
inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
set_corners_from_radius(inset.round, &mut shape.mRadius);
shape.mRadius = match inset.round {
Some(radius) => radius,
None => crate::values::computed::BorderRadius::zero(),
};
}
BasicShape::Circle(circ) => {
let shape = init_shape(${ident}, StyleBasicShapeType::Circle);

View file

@ -87,6 +87,16 @@ impl BorderCornerRadius {
}
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`.
pub fn all_zero(&self) -> bool {
fn all(corner: &BorderCornerRadius) -> bool {

View file

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

View file

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