Bug 1516454 - Use rust lengths for border corners. r=boris

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 b0d83e4a75
commit b7bb398730
23 changed files with 128 additions and 373 deletions

View File

@ -518,7 +518,7 @@ static inline Corner operator++(Corner& aCorner) {
}
// Indices into "half corner" arrays (nsStyleCorners e.g.)
enum HalfCorner {
enum HalfCorner : uint8_t {
// This order is important!
eCornerTopLeftX = 0,
eCornerTopLeftY = 1,

View File

@ -140,7 +140,7 @@ nsSize ShapeUtils::ComputeEllipseRadii(const StyleBasicShape& aBasicShape,
/* static */ bool ShapeUtils::ComputeInsetRadii(
const StyleBasicShape& aBasicShape, const nsRect& aInsetRect,
const nsRect& aRefBox, nscoord aRadii[8]) {
const nsStyleCorners& radius = aBasicShape.GetRadius();
const auto& radius = aBasicShape.GetRadius();
return nsIFrame::ComputeBorderRadii(radius, aInsetRect.Size(), aRefBox.Size(),
Sides(), aRadii);
}

View File

@ -6862,20 +6862,15 @@ static ImgDrawResult DrawImageInternal(
return img.forget();
}
static bool NonZeroStyleCoord(const nsStyleCoord& aCoord) {
if (aCoord.IsCoordPercentCalcUnit()) {
// Since negative results are clamped to 0, check > 0.
return aCoord.ComputeCoordPercentCalc(nscoord_MAX) > 0 ||
aCoord.ComputeCoordPercentCalc(0) > 0;
}
return true;
static bool NonZeroCorner(const LengthPercentage& aLength) {
// Since negative results are clamped to 0, check > 0.
return aLength.Resolve(nscoord_MAX) > 0 || aLength.Resolve(0) > 0;
}
/* static */ bool nsLayoutUtils::HasNonZeroCorner(
const nsStyleCorners& aCorners) {
const BorderRadius& aCorners) {
NS_FOR_CSS_HALF_CORNERS(corner) {
if (NonZeroStyleCoord(aCorners.Get(corner))) return true;
if (NonZeroCorner(aCorners.Get(corner))) return true;
}
return false;
}
@ -6900,7 +6895,7 @@ static bool IsCornerAdjacentToSide(uint8_t aCorner, Side aSide) {
}
/* static */ bool nsLayoutUtils::HasNonZeroCornerOnSide(
const nsStyleCorners& aCorners, Side aSide) {
const BorderRadius& aCorners, Side aSide) {
static_assert(eCornerTopLeftX / 2 == eCornerTopLeft,
"Check for Non Zero on side");
static_assert(eCornerTopLeftY / 2 == eCornerTopLeft,
@ -6921,7 +6916,7 @@ static bool IsCornerAdjacentToSide(uint8_t aCorner, Side aSide) {
NS_FOR_CSS_HALF_CORNERS(corner) {
// corner is a "half corner" value, so dividing by two gives us a
// "full corner" value.
if (NonZeroStyleCoord(aCorners.Get(corner)) &&
if (NonZeroCorner(aCorners.Get(corner)) &&
IsCornerAdjacentToSide(corner / 2, aSide))
return true;
}

View File

@ -55,7 +55,6 @@ class nsContainerFrame;
class nsView;
class nsIFrame;
class nsStyleCoord;
class nsStyleCorners;
class nsPIDOMWindowOuter;
class imgIRequest;
struct nsStyleFont;
@ -1937,7 +1936,7 @@ class nsLayoutUtils {
/**
* Determine if any corner radius is of nonzero size
* @param aCorners the |nsStyleCorners| object to check
* @param aCorners the |BorderRadius| object to check
* @return true unless all the coordinates are 0%, 0 or null.
*
* A corner radius with one dimension zero and one nonzero is
@ -1946,13 +1945,13 @@ class nsLayoutUtils {
* corners are not expected to appear outside of test cases, and it's
* simpler to implement the test this way.
*/
static bool HasNonZeroCorner(const nsStyleCorners& aCorners);
static bool HasNonZeroCorner(const mozilla::BorderRadius& aCorners);
/**
* Determine if there is any corner radius on corners adjacent to the
* given side.
*/
static bool HasNonZeroCornerOnSide(const nsStyleCorners& aCorners,
static bool HasNonZeroCornerOnSide(const mozilla::BorderRadius& aCorners,
mozilla::Side aSide);
/**

View File

@ -1644,25 +1644,15 @@ nsRect nsIFrame::GetContentRect() const {
return GetContentRectRelativeToSelf() + GetPosition();
}
bool nsIFrame::ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
bool nsIFrame::ComputeBorderRadii(const BorderRadius& aBorderRadius,
const nsSize& aFrameSize,
const nsSize& aBorderArea, Sides aSkipSides,
nscoord aRadii[8]) {
// Percentages are relative to whichever side they're on.
NS_FOR_CSS_HALF_CORNERS(i) {
const nsStyleCoord c = aBorderRadius.Get(i);
const LengthPercentage& c = aBorderRadius.Get(i);
nscoord axis = HalfCornerIsX(i) ? aFrameSize.width : aFrameSize.height;
if (c.IsCoordPercentCalcUnit()) {
aRadii[i] = c.ComputeCoordPercentCalc(axis);
if (aRadii[i] < 0) {
// clamp calc()
aRadii[i] = 0;
}
} else {
MOZ_ASSERT_UNREACHABLE("ComputeBorderRadii: bad unit");
aRadii[i] = 0;
}
aRadii[i] = std::max(0, c.Resolve(axis));
}
if (aSkipSides.Top()) {

View File

@ -1363,7 +1363,7 @@ class nsIFrame : public nsQueryFrame {
*
* Return whether any radii are nonzero.
*/
static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
static bool ComputeBorderRadii(const mozilla::BorderRadius&,
const nsSize& aFrameSize,
const nsSize& aBorderArea, Sides aSkipSides,
nscoord aRadii[8]);

View File

@ -513,6 +513,8 @@ bool Servo_ParseEasing(const nsAString* easing, RawGeckoURLExtraData* data,
void Servo_SerializeEasing(nsTimingFunctionBorrowed easing, nsAString* output);
void Servo_SerializeBorderRadius(const mozilla::StyleBorderRadius*, nsAString*);
void Servo_GetComputedKeyframeValues(
RawGeckoKeyframeListBorrowed keyframes, RawGeckoElementBorrowed element,
ComputedStyleBorrowed style, RawServoStyleSetBorrowed set,

View File

@ -444,6 +444,7 @@ cbindgen-types = [
{ gecko = "StyleZIndex", servo = "values::computed::ZIndex" },
{ gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
{ gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
{ gecko = "StyleGenericBorderRadius", servo = "values::generics::border::BorderRadius" },
]
mapped-generic-types = [
@ -502,6 +503,7 @@ structs-types = [
"mozilla::OriginFlags",
"mozilla::StyleMotion",
"mozilla::UniquePtr",
"mozilla::StyleBorderRadius",
"mozilla::StyleDisplayMode",
"mozilla::StylePrefersColorScheme",
"mozilla::StyleIntersectionObserverRootMargin",

View File

@ -1902,14 +1902,14 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetOutlineRadiusTopRight() {
}
already_AddRefed<CSSValue> nsComputedDOMStyle::GetEllipseRadii(
const nsStyleCorners& aRadius, Corner aFullCorner) {
nsStyleCoord radiusX = aRadius.Get(FullToHalfCorner(aFullCorner, false));
nsStyleCoord radiusY = aRadius.Get(FullToHalfCorner(aFullCorner, true));
const BorderRadius& aRadius, Corner aFullCorner) {
const auto& radiusX = aRadius.Get(FullToHalfCorner(aFullCorner, false));
const auto& radiusY = aRadius.Get(FullToHalfCorner(aFullCorner, true));
// for compatibility, return a single value if X and Y are equal
if (radiusX == radiusY) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToCoord(val, radiusX, true);
SetValueToLengthPercentage(val, radiusX, true);
return val.forget();
}
@ -1918,8 +1918,8 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetEllipseRadii(
RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
SetValueToCoord(valX, radiusX, true);
SetValueToCoord(valY, radiusY, true);
SetValueToLengthPercentage(valX, radiusX, true);
SetValueToLengthPercentage(valY, radiusY, true);
valueList->AppendCSSValue(valX.forget());
valueList->AppendCSSValue(valY.forget());
@ -3273,22 +3273,9 @@ void nsComputedDOMStyle::BoxValuesToString(
}
}
void nsComputedDOMStyle::BasicShapeRadiiToString(
nsAString& aCssText, const nsStyleCorners& aCorners) {
nsTArray<nsStyleCoord> horizontal, vertical;
nsAutoString horizontalString, verticalString;
NS_FOR_CSS_FULL_CORNERS(corner) {
horizontal.AppendElement(aCorners.Get(FullToHalfCorner(corner, false)));
vertical.AppendElement(aCorners.Get(FullToHalfCorner(corner, true)));
}
BoxValuesToString(horizontalString, horizontal, true);
BoxValuesToString(verticalString, vertical, true);
aCssText.Append(horizontalString);
if (horizontalString == verticalString) {
return;
}
aCssText.AppendLiteral(" / ");
aCssText.Append(verticalString);
void nsComputedDOMStyle::BasicShapeRadiiToString(nsAString& aCssText,
const BorderRadius& aCorners) {
Servo_SerializeBorderRadius(&aCorners, &aCssText);
}
already_AddRefed<CSSValue>

View File

@ -41,7 +41,6 @@ class nsDOMCSSValueList;
struct nsMargin;
class nsROCSSPrimitiveValue;
class nsStyleCoord;
class nsStyleCorners;
struct nsStyleFilter;
class nsStyleGradient;
struct nsStyleImage;
@ -170,11 +169,10 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
*/
typedef bool (nsComputedDOMStyle::*PercentageBaseGetter)(nscoord&);
already_AddRefed<CSSValue> GetEllipseRadii(const nsStyleCorners& aRadius,
already_AddRefed<CSSValue> GetEllipseRadii(const mozilla::BorderRadius&,
mozilla::Corner aFullCorner);
already_AddRefed<CSSValue> GetOffsetWidthFor(mozilla::Side aSide);
already_AddRefed<CSSValue> GetOffsetWidthFor(mozilla::Side);
already_AddRefed<CSSValue> GetAbsoluteOffset(mozilla::Side);
nscoord GetUsedAbsoluteOffset(mozilla::Side);
already_AddRefed<CSSValue> GetNonStaticPositionOffset(
@ -296,6 +294,7 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
already_AddRefed<CSSValue> DoGetBorderTopLeftRadius();
already_AddRefed<CSSValue> DoGetBorderTopRightRadius();
/* Border Image */
already_AddRefed<CSSValue> DoGetBorderImageWidth();
@ -315,6 +314,7 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
already_AddRefed<CSSValue> DoGetOutlineRadiusTopLeft();
already_AddRefed<CSSValue> DoGetOutlineRadiusTopRight();
/* Text Properties */
already_AddRefed<CSSValue> DoGetInitialLetter();
already_AddRefed<CSSValue> DoGetLineHeight();
@ -496,7 +496,7 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
const nsTArray<nsStyleCoord>& aBoxValues,
bool aClampNegativeCalc);
void BasicShapeRadiiToString(nsAString& aCssText,
const nsStyleCorners& aCorners);
const mozilla::BorderRadius&);
// Find out if we can safely skip flushing for aDocument (i.e. pending
// restyles does not affect mContent).

View File

@ -203,42 +203,6 @@ void nsStyleSides::Reset() {
NS_FOR_CSS_SIDES(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
}
nsStyleCorners::nsStyleCorners() {
NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
mozilla::PodArrayZero(mValues);
}
nsStyleCorners::nsStyleCorners(const nsStyleCorners& aOther) {
NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
*this = aOther;
}
nsStyleCorners::~nsStyleCorners() { Reset(); }
nsStyleCorners& nsStyleCorners::operator=(const nsStyleCorners& aCopy) {
if (this != &aCopy) {
NS_FOR_CSS_HALF_CORNERS(i) {
nsStyleCoord::SetValue(mUnits[i], mValues[i], aCopy.mUnits[i],
aCopy.mValues[i]);
}
}
return *this;
}
bool nsStyleCorners::operator==(const nsStyleCorners& aOther) const {
NS_FOR_CSS_HALF_CORNERS(i) {
if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
return false;
}
}
return true;
}
void nsStyleCorners::Reset() {
NS_FOR_CSS_HALF_CORNERS(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
}
// Validation of SideIsVertical.
#define CASE(side, result) \
static_assert(SideIsVertical(side) == result, "SideIsVertical is wrong")

View File

@ -44,6 +44,7 @@ using LengthPercentageOrAuto = StyleLengthPercentageOrAuto;
using NonNegativeLengthPercentage = StyleNonNegativeLengthPercentage;
using NonNegativeLengthPercentageOrAuto =
StyleNonNegativeLengthPercentageOrAuto;
using BorderRadius = StyleBorderRadius;
nscoord StyleCSSPixelLength::ToAppUnits() const {
// We want to resolve the length part of the calc() expression rounding 0.5
@ -251,6 +252,14 @@ bool StyleRect<T>::Any(Predicate aPredicate) const {
return aPredicate(_0) || aPredicate(_1) || aPredicate(_2) || aPredicate(_3);
}
template <>
inline const LengthPercentage& BorderRadius::Get(HalfCorner aCorner) const {
static_assert(sizeof(BorderRadius) == sizeof(LengthPercentage) * 8, "");
static_assert(alignof(BorderRadius) == alignof(LengthPercentage), "");
auto* self = reinterpret_cast<const LengthPercentage*>(this);
return self[aCorner];
}
} // namespace mozilla
enum nsStyleUnit : uint8_t {
@ -589,45 +598,6 @@ class nsStyleSides {
nsStyleUnion mValues[4];
};
/**
* Class that represents a set of top-left/top-right/bottom-right/bottom-left
* nsStyleCoord pairs. This is used to hold the dimensions of the
* corners of a box (for, e.g., border-radius and outline-radius).
*/
/** <div rustbindgen private accessor="unsafe"></div> */
class nsStyleCorners {
public:
nsStyleCorners();
nsStyleCorners(const nsStyleCorners&);
~nsStyleCorners();
// use compiler's version
nsStyleCorners& operator=(const nsStyleCorners& aCopy);
bool operator==(const nsStyleCorners& aOther) const;
bool operator!=(const nsStyleCorners& aOther) const;
// aHalfCorner is always one of enum HalfCorner in gfx/2d/Types.h.
inline nsStyleUnit GetUnit(uint8_t aHalfCorner) const;
inline nsStyleCoord Get(uint8_t aHalfCorner) const;
// Sets each corner to null and releases any refcounted objects. Only use
// this if the object is initialized (i.e. don't use it in nsStyleCorners
// constructors).
void Reset();
inline void Set(uint8_t aHalfCorner, const nsStyleCoord& aCoord);
protected:
// Stored as:
// top-left.x, top-left.y,
// top-right.x, top-right.y,
// bottom-right.x, bottom-right.y,
// bottom-left.x, bottom-left.y
nsStyleUnit mUnits[8];
nsStyleUnion mValues[8];
};
// -------------------------
// nsStyleCoord inlines
//
@ -830,24 +800,4 @@ inline void nsStyleSides::SetRight(const nsStyleCoord& aCoord) {
inline void nsStyleSides::SetBottom(const nsStyleCoord& aCoord) {
Set(mozilla::eSideBottom, aCoord);
}
// -------------------------
// nsStyleCorners inlines
//
inline bool nsStyleCorners::operator!=(const nsStyleCorners& aOther) const {
return !((*this) == aOther);
}
inline nsStyleUnit nsStyleCorners::GetUnit(uint8_t aCorner) const {
return (nsStyleUnit)mUnits[aCorner];
}
inline nsStyleCoord nsStyleCorners::Get(uint8_t aCorner) const {
return nsStyleCoord(mValues[aCorner], nsStyleUnit(mUnits[aCorner]));
}
inline void nsStyleCorners::Set(uint8_t aCorner, const nsStyleCoord& aCoord) {
nsStyleCoord::SetValue(mUnits[aCorner], mValues[aCorner], aCoord);
}
#endif /* nsStyleCoord_h___ */

View File

@ -242,8 +242,14 @@ static nscoord TwipsPerPixel(const Document& aDocument) {
return pc ? pc->AppUnitsPerDevPixel() : mozilla::AppUnitsPerCSSPixel();
}
static inline BorderRadius ZeroBorderRadius() {
auto zero = LengthPercentage::Zero();
return {{{zero, zero}}, {{zero, zero}}, {{zero, zero}}, {{zero, zero}}};
}
nsStyleBorder::nsStyleBorder(const Document& aDocument)
: mBorderImageOutset(
: mBorderRadius(ZeroBorderRadius()),
mBorderImageOutset(
StyleRectWithAllSides(StyleNonNegativeLengthOrNumber::Number(0.))),
mBorderImageSlice(
{StyleRectWithAllSides(StyleNumberOrPercentage::Percentage({1.})),
@ -260,10 +266,6 @@ nsStyleBorder::nsStyleBorder(const Document& aDocument)
mTwipsPerPixel(TwipsPerPixel(aDocument)) {
MOZ_COUNT_CTOR(nsStyleBorder);
NS_FOR_CSS_HALF_CORNERS(corner) {
mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
}
nscoord medium = kMediumBorderWidth;
NS_FOR_CSS_SIDES(side) {
mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor));
@ -400,16 +402,14 @@ nsChangeHint nsStyleBorder::CalcDifference(
}
nsStyleOutline::nsStyleOutline(const Document& aDocument)
: mOutlineWidth(kMediumBorderWidth),
: mOutlineRadius(ZeroBorderRadius()),
mOutlineWidth(kMediumBorderWidth),
mOutlineOffset(0),
mOutlineColor(StyleComplexColor::CurrentColor()),
mOutlineStyle(StyleOutlineStyle::BorderStyle(StyleBorderStyle::None)),
mActualOutlineWidth(0),
mTwipsPerPixel(TwipsPerPixel(aDocument)) {
MOZ_COUNT_CTOR(nsStyleOutline);
// spacing values not inherited
nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
NS_FOR_CSS_HALF_CORNERS(corner) { mOutlineRadius.Set(corner, zero); }
}
nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc)
@ -782,6 +782,12 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const {
// --------------------
// StyleBasicShape
StyleBasicShape::StyleBasicShape(StyleBasicShapeType aType)
: mType(aType),
mFillRule(StyleFillRule::Nonzero),
mPosition(Position::FromPercentage(0.5f)),
mRadius(ZeroBorderRadius()) {}
nsCSSKeyword StyleBasicShape::GetShapeTypeName() const {
switch (mType) {
case StyleBasicShapeType::Polygon:

View File

@ -943,7 +943,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder {
}
public:
nsStyleCorners mBorderRadius; // coord, percent
mozilla::StyleBorderRadius mBorderRadius; // coord, percent
nsStyleImage mBorderImageSource;
nsStyleSides mBorderImageWidth; // length, factor, percent, auto
mozilla::StyleNonNegativeLengthOrNumberRect mBorderImageOutset;
@ -1047,7 +1047,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline {
nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const;
nsStyleCorners mOutlineRadius; // coord, percent, calc
mozilla::StyleBorderRadius mOutlineRadius;
// This is the specified value of outline-width, but with length values
// computed to absolute. mActualOutlineWidth stores the outline-width
@ -1291,9 +1291,9 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
uint8_t mSpecifiedJustifyItems;
uint8_t mJustifyItems;
uint8_t mJustifySelf;
mozilla::StyleFlexDirection mFlexDirection;
uint8_t mFlexWrap; // NS_STYLE_FLEX_WRAP_*
uint8_t mObjectFit; // NS_STYLE_OBJECT_FIT_*
mozilla::StyleFlexDirection mFlexDirection;
uint8_t mFlexWrap; // NS_STYLE_FLEX_WRAP_*
uint8_t mObjectFit; // NS_STYLE_OBJECT_FIT_*
int32_t mOrder;
float mFlexGrow;
float mFlexShrink;
@ -1635,10 +1635,7 @@ struct StyleAnimation {
class StyleBasicShape final {
public:
explicit StyleBasicShape(StyleBasicShapeType type)
: mType(type),
mFillRule(StyleFillRule::Nonzero),
mPosition(Position::FromPercentage(0.5f)) {}
explicit StyleBasicShape(StyleBasicShapeType);
StyleBasicShapeType GetShapeType() const { return mType; }
nsCSSKeyword GetShapeTypeName() const;
@ -1654,17 +1651,16 @@ class StyleBasicShape final {
bool HasRadius() const {
MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
nsStyleCoord zero;
zero.SetCoordValue(0);
NS_FOR_CSS_HALF_CORNERS(corner) {
if (mRadius.Get(corner) != zero) {
auto& radius = mRadius.Get(corner);
if (radius.HasPercent() || radius.LengthInCSSPixels() != 0.0f) {
return true;
}
}
return false;
}
const nsStyleCorners& GetRadius() const {
const mozilla::StyleBorderRadius& GetRadius() const {
MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
return mRadius;
}
@ -1693,7 +1689,7 @@ class StyleBasicShape final {
// position of center for ellipse or circle
mozilla::Position mPosition;
// corner radii for inset (0 if not set)
nsStyleCorners mRadius;
mozilla::StyleBorderRadius mRadius;
};
struct StyleSVGPath final {

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,

View File

@ -3703,6 +3703,15 @@ pub unsafe extern "C" fn Servo_SerializeEasing(
.unwrap();
}
#[no_mangle]
pub unsafe extern "C" fn Servo_SerializeBorderRadius(
radius: *const computed::BorderRadius,
output: *mut nsAString,
) {
(*radius).to_css(&mut CssWriter::new(&mut *output)).unwrap();
}
#[no_mangle]
pub extern "C" fn Servo_GetProperties_Overriding_Animation(
element: RawGeckoElementBorrowed,

View File

@ -1,22 +0,0 @@
[shape-outside-inset-006.html]
[inset(10px round 10.1200px 20.34px 30.56px 40.780px) - computed]
expected: FAIL
[inset(10px round 10.123px 20.00px 30.10px 40.5678px) - computed]
expected: FAIL
[inset(10px round +10.1200px +20.340px +30.56px +40.780px) - computed]
expected: FAIL
[inset(10px round 10.1200px 20.34px 30.56px 40.780px / 10.1200px 20.34px 30.56px 40.780px) - computed]
expected: FAIL
[inset(10px round 10.123px 20.00px 30.10px 40.5678px / 10.123px 20.00px 30.10px 40.5678px) - computed]
expected: FAIL
[inset(10px round +10.1200px +20.340px +30.56px +40.780px / +10.1200px +20.340px +30.56px +40.780px) - computed]
expected: FAIL
[inset(10px round +10.123px +20.00px +30.10px +40.5678px / 10.123px +20.00px +30.10px +40.5678px) - computed]
expected: FAIL