mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
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:
parent
aad4dac5b4
commit
197065f6bc
7 changed files with 51 additions and 174 deletions
|
@ -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;
|
||||
"""
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue