Bug 1548691 - Use the owned slice type for basic shape polygon coordinates. r=TYLin,heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 09 May 2019 11:24:57 +0000
changeset 535087 fe11fc11ec5b0ee0111351c01cf601109798ca85
parent 535086 41acb048244d7d2bad371761bf54c80670fe683b
child 535088 f419e689abf08b654c99ec258f2118b0523628cf
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersTYLin, heycam
bugs1548691
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1548691 - Use the owned slice type for basic shape polygon coordinates. r=TYLin,heycam This enables destructors for tagged unions in cbindgen, implemented in: * https://github.com/eqrion/cbindgen/pull/333 Which allow us to properly generate a destructor for the cbindgen-generated StyleBasicShape (which now contains an OwnedSlice). For now, we still use the glue code to go from Box<BasicShape> to UniquePtr<BasicShape>. But that will change in the future when we generate even more stuff and remove all the glue. I could add support for copy-constructor generation to cbindgen for tagged enums, but I'm not sure if it'll end up being needed, and copy-constructing unions in C++ is always very tricky. Differential Revision: https://phabricator.services.mozilla.com/D29769
layout/base/ShapeUtils.cpp
layout/base/ShapeUtils.h
layout/generic/nsFloatManager.cpp
layout/generic/nsFloatManager.h
layout/painting/nsDisplayList.cpp
layout/style/GeckoBindings.cpp
layout/style/GeckoBindings.h
layout/style/ServoBindings.toml
layout/style/ServoStyleConstsForwards.h
layout/style/nsCSSProps.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsStyleConsts.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/nsCSSClipPathInstance.cpp
layout/svg/nsSVGIntegrationUtils.cpp
servo/components/style/gecko/conversions.rs
servo/components/style/gecko/values.rs
servo/components/style/owned_slice.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhands/svg.mako.rs
servo/components/style/values/animated/mod.rs
servo/components/style/values/computed/basic_shape.rs
servo/components/style/values/generics/basic_shape.rs
servo/components/style/values/specified/basic_shape.rs
servo/ports/geckolib/cbindgen.toml
servo/ports/geckolib/glue.rs
testing/web-platform/meta/css/css-shapes/parsing/shape-outside-computed.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-circle-005.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-circle-006.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-ellipse-005.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-ellipse-006.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-001.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-003.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-004.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-polygon-004.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-polygon-005.html.ini
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000.html.ini
--- a/layout/base/ShapeUtils.cpp
+++ b/layout/base/ShapeUtils.cpp
@@ -11,117 +11,102 @@
 #include "nsCSSRendering.h"
 #include "nsMargin.h"
 #include "nsStyleCoord.h"
 #include "nsStyleStruct.h"
 #include "SVGContentUtils.h"
 
 namespace mozilla {
 
-nscoord ShapeUtils::ComputeShapeRadius(const StyleShapeRadius aType,
+nscoord ShapeUtils::ComputeShapeRadius(const StyleShapeRadius& aType,
                                        const nscoord aCenter,
                                        const nscoord aPosMin,
                                        const nscoord aPosMax) {
+  MOZ_ASSERT(aType.IsFarthestSide() || aType.IsClosestSide());
   nscoord dist1 = std::abs(aPosMin - aCenter);
   nscoord dist2 = std::abs(aPosMax - aCenter);
   nscoord length = 0;
-  switch (aType) {
-    case StyleShapeRadius::FarthestSide:
-      length = dist1 > dist2 ? dist1 : dist2;
-      break;
-    case StyleShapeRadius::ClosestSide:
-      length = dist1 > dist2 ? dist2 : dist1;
-      break;
+  if (aType.IsFarthestSide()) {
+    length = dist1 > dist2 ? dist1 : dist2;
+  } else {
+    length = dist1 > dist2 ? dist2 : dist1;
   }
   return length;
 }
 
 nsPoint ShapeUtils::ComputeCircleOrEllipseCenter(
     const StyleBasicShape& aBasicShape, const nsRect& aRefBox) {
-  MOZ_ASSERT(aBasicShape.GetShapeType() == StyleBasicShapeType::Circle ||
-                 aBasicShape.GetShapeType() == StyleBasicShapeType::Ellipse,
+  MOZ_ASSERT(aBasicShape.IsCircle() || aBasicShape.IsEllipse(),
              "The basic shape must be circle() or ellipse!");
 
+  const auto& position = aBasicShape.IsCircle()
+                             ? aBasicShape.AsCircle().position
+                             : aBasicShape.AsEllipse().position;
+
   nsPoint topLeft, anchor;
   nsSize size(aRefBox.Size());
-  nsImageRenderer::ComputeObjectAnchorPoint(aBasicShape.GetPosition(), size,
-                                            size, &topLeft, &anchor);
+  nsImageRenderer::ComputeObjectAnchorPoint(position, size, size, &topLeft,
+                                            &anchor);
   return anchor + aRefBox.TopLeft();
 }
 
 nscoord ShapeUtils::ComputeCircleRadius(const StyleBasicShape& aBasicShape,
                                         const nsPoint& aCenter,
                                         const nsRect& aRefBox) {
-  MOZ_ASSERT(aBasicShape.GetShapeType() == StyleBasicShapeType::Circle,
-             "The basic shape must be circle()!");
+  MOZ_ASSERT(aBasicShape.IsCircle(), "The basic shape must be circle()!");
+  const auto& radius = aBasicShape.AsCircle().radius;
+  if (radius.IsLength()) {
+    return radius.AsLength().Resolve([&] {
+      // We resolve percent <shape-radius> value for circle() as defined here:
+      // https://drafts.csswg.org/css-shapes/#funcdef-circle
+      double referenceLength = SVGContentUtils::ComputeNormalizedHypotenuse(
+          aRefBox.width, aRefBox.height);
+      return NSToCoordRound(referenceLength);
+    });
+  }
 
-  const nsTArray<nsStyleCoord>& coords = aBasicShape.Coordinates();
-  MOZ_ASSERT(coords.Length() == 1, "wrong number of arguments");
-  nscoord r = 0;
-  if (coords[0].GetUnit() == eStyleUnit_Enumerated) {
-    const auto styleShapeRadius = coords[0].GetEnumValue<StyleShapeRadius>();
-    nscoord horizontal = ComputeShapeRadius(styleShapeRadius, aCenter.x,
-                                            aRefBox.x, aRefBox.XMost());
-    nscoord vertical = ComputeShapeRadius(styleShapeRadius, aCenter.y,
-                                          aRefBox.y, aRefBox.YMost());
-    r = styleShapeRadius == StyleShapeRadius::FarthestSide
-            ? std::max(horizontal, vertical)
-            : std::min(horizontal, vertical);
-  } else {
-    // We resolve percent <shape-radius> value for circle() as defined here:
-    // https://drafts.csswg.org/css-shapes/#funcdef-circle
-    double referenceLength = SVGContentUtils::ComputeNormalizedHypotenuse(
-        aRefBox.width, aRefBox.height);
-    r = coords[0].ComputeCoordPercentCalc(NSToCoordRound(referenceLength));
-  }
-  return r;
+  nscoord horizontal =
+      ComputeShapeRadius(radius, aCenter.x, aRefBox.x, aRefBox.XMost());
+  nscoord vertical =
+      ComputeShapeRadius(radius, aCenter.y, aRefBox.y, aRefBox.YMost());
+  return radius.IsFarthestSide() ? std::max(horizontal, vertical)
+                                 : std::min(horizontal, vertical);
 }
 
 nsSize ShapeUtils::ComputeEllipseRadii(const StyleBasicShape& aBasicShape,
                                        const nsPoint& aCenter,
                                        const nsRect& aRefBox) {
-  MOZ_ASSERT(aBasicShape.GetShapeType() == StyleBasicShapeType::Ellipse,
-             "The basic shape must be ellipse()!");
-
-  const nsTArray<nsStyleCoord>& coords = aBasicShape.Coordinates();
-  MOZ_ASSERT(coords.Length() == 2, "wrong number of arguments");
+  MOZ_ASSERT(aBasicShape.IsEllipse(), "The basic shape must be ellipse()!");
+  const auto& ellipse = aBasicShape.AsEllipse();
   nsSize radii;
-
-  if (coords[0].GetUnit() == eStyleUnit_Enumerated) {
-    const StyleShapeRadius radiusX = coords[0].GetEnumValue<StyleShapeRadius>();
-    radii.width =
-        ComputeShapeRadius(radiusX, aCenter.x, aRefBox.x, aRefBox.XMost());
+  if (ellipse.semiaxis_x.IsLength()) {
+    radii.width = ellipse.semiaxis_x.AsLength().Resolve(aRefBox.width);
   } else {
-    radii.width = coords[0].ComputeCoordPercentCalc(aRefBox.width);
+    radii.width = ComputeShapeRadius(ellipse.semiaxis_x, aCenter.x, aRefBox.x,
+                                     aRefBox.XMost());
   }
 
-  if (coords[1].GetUnit() == eStyleUnit_Enumerated) {
-    const StyleShapeRadius radiusY = coords[1].GetEnumValue<StyleShapeRadius>();
-    radii.height =
-        ComputeShapeRadius(radiusY, aCenter.y, aRefBox.y, aRefBox.YMost());
+  if (ellipse.semiaxis_y.IsLength()) {
+    radii.height = ellipse.semiaxis_y.AsLength().Resolve(aRefBox.height);
   } else {
-    radii.height = coords[1].ComputeCoordPercentCalc(aRefBox.height);
+    radii.height = ComputeShapeRadius(ellipse.semiaxis_y, aCenter.y, aRefBox.y,
+                                      aRefBox.YMost());
   }
 
   return radii;
 }
 
 /* static */
 nsRect ShapeUtils::ComputeInsetRect(const StyleBasicShape& aBasicShape,
                                     const nsRect& aRefBox) {
-  MOZ_ASSERT(aBasicShape.GetShapeType() == StyleBasicShapeType::Inset,
-             "The basic shape must be inset()!");
-
-  const nsTArray<nsStyleCoord>& coords = aBasicShape.Coordinates();
-  MOZ_ASSERT(coords.Length() == 4, "wrong number of arguments");
-
-  nsMargin inset(coords[0].ComputeCoordPercentCalc(aRefBox.Height()),
-                 coords[1].ComputeCoordPercentCalc(aRefBox.Width()),
-                 coords[2].ComputeCoordPercentCalc(aRefBox.Height()),
-                 coords[3].ComputeCoordPercentCalc(aRefBox.Width()));
+  MOZ_ASSERT(aBasicShape.IsInset(), "The basic shape must be inset()!");
+  const auto& rect = aBasicShape.AsInset().rect;
+  nsMargin inset(
+      rect._0.Resolve(aRefBox.Height()), rect._1.Resolve(aRefBox.Width()),
+      rect._2.Resolve(aRefBox.Height()), rect._3.Resolve(aRefBox.Width()));
 
   nscoord x = aRefBox.X() + inset.left;
   nscoord width = aRefBox.Width() - inset.LeftRight();
   nscoord y = aRefBox.Y() + inset.top;
   nscoord height = aRefBox.Height() - inset.TopBottom();
 
   // Invert left and right, if necessary.
   if (width < 0) {
@@ -137,34 +122,29 @@ nsRect ShapeUtils::ComputeInsetRect(cons
 
   return nsRect(x, y, width, height);
 }
 
 /* static */
 bool ShapeUtils::ComputeInsetRadii(const StyleBasicShape& aBasicShape,
                                    const nsRect& aInsetRect,
                                    const nsRect& aRefBox, nscoord aRadii[8]) {
-  const auto& radius = aBasicShape.GetRadius();
+  const auto& radius = aBasicShape.AsInset().round;
   return nsIFrame::ComputeBorderRadii(radius, aInsetRect.Size(), aRefBox.Size(),
                                       Sides(), aRadii);
 }
 
 /* static */
 nsTArray<nsPoint> ShapeUtils::ComputePolygonVertices(
     const StyleBasicShape& aBasicShape, const nsRect& aRefBox) {
-  MOZ_ASSERT(aBasicShape.GetShapeType() == StyleBasicShapeType::Polygon,
-             "The basic shape must be polygon()!");
-
-  const nsTArray<nsStyleCoord>& coords = aBasicShape.Coordinates();
-  MOZ_ASSERT(coords.Length() % 2 == 0 && coords.Length() >= 2,
-             "Wrong number of arguments!");
+  MOZ_ASSERT(aBasicShape.IsPolygon(), "The basic shape must be polygon()!");
 
-  nsTArray<nsPoint> vertices(coords.Length() / 2);
-  for (size_t i = 0; i + 1 < coords.Length(); i += 2) {
-    vertices.AppendElement(
-        nsPoint(coords[i].ComputeCoordPercentCalc(aRefBox.width),
-                coords[i + 1].ComputeCoordPercentCalc(aRefBox.height)) +
-        aRefBox.TopLeft());
+  auto coords = aBasicShape.AsPolygon().coordinates.AsSpan();
+  nsTArray<nsPoint> vertices(coords.Length());
+  for (const StylePolygonCoord<LengthPercentage>& point : coords) {
+    vertices.AppendElement(nsPoint(point._0.Resolve(aRefBox.width),
+                                   point._1.Resolve(aRefBox.height)) +
+                           aRefBox.TopLeft());
   }
   return vertices;
 }
 
 }  // namespace mozilla
--- a/layout/base/ShapeUtils.h
+++ b/layout/base/ShapeUtils.h
@@ -5,35 +5,34 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ShapeUtils_h
 #define mozilla_ShapeUtils_h
 
 #include "nsCoord.h"
 #include "nsSize.h"
 #include "nsStyleConsts.h"
+#include "nsStyleCoord.h"
 #include "nsTArray.h"
 
 struct nsPoint;
 struct nsRect;
 
 namespace mozilla {
-class StyleBasicShape;
-
 // ShapeUtils is a namespace class containing utility functions related to
 // processing basic shapes in the CSS Shapes Module.
 // https://drafts.csswg.org/css-shapes/#basic-shape-functions
 //
 struct ShapeUtils final {
   // Compute the length of a keyword <shape-radius>, i.e. closest-side or
   // farthest-side, for a circle or an ellipse on a single dimension. The
   // caller needs to call for both dimensions and combine the result.
   // https://drafts.csswg.org/css-shapes/#typedef-shape-radius.
   // @return The length of the radius in app units.
-  static nscoord ComputeShapeRadius(const StyleShapeRadius aType,
+  static nscoord ComputeShapeRadius(const StyleShapeRadius& aType,
                                     const nscoord aCenter,
                                     const nscoord aPosMin,
                                     const nscoord aPosMax);
 
   // Compute the center of a circle or an ellipse.
   // @param aRefBox The reference box of the basic shape.
   // @return The point of the center.
   static nsPoint ComputeCircleOrEllipseCenter(const StyleBasicShape&,
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -2498,25 +2498,25 @@ nsFloatManager::ShapeInfo::CreateShapeBo
 /* static */ UniquePtr<nsFloatManager::ShapeInfo>
 nsFloatManager::ShapeInfo::CreateBasicShape(const StyleBasicShape& aBasicShape,
                                             nscoord aShapeMargin,
                                             nsIFrame* const aFrame,
                                             const LogicalRect& aShapeBoxRect,
                                             const LogicalRect& aMarginRect,
                                             WritingMode aWM,
                                             const nsSize& aContainerSize) {
-  switch (aBasicShape.GetShapeType()) {
-    case StyleBasicShapeType::Polygon:
+  switch (aBasicShape.tag) {
+    case StyleBasicShape::Tag::Polygon:
       return CreatePolygon(aBasicShape, aShapeMargin, aFrame, aShapeBoxRect,
                            aMarginRect, aWM, aContainerSize);
-    case StyleBasicShapeType::Circle:
-    case StyleBasicShapeType::Ellipse:
+    case StyleBasicShape::Tag::Circle:
+    case StyleBasicShape::Tag::Ellipse:
       return CreateCircleOrEllipse(aBasicShape, aShapeMargin, aFrame,
                                    aShapeBoxRect, aWM, aContainerSize);
-    case StyleBasicShapeType::Inset:
+    case StyleBasicShape::Tag::Inset:
       return CreateInset(aBasicShape, aShapeMargin, aFrame, aShapeBoxRect, aWM,
                          aContainerSize);
   }
   return nullptr;
 }
 
 /* static */ UniquePtr<nsFloatManager::ShapeInfo>
 nsFloatManager::ShapeInfo::CreateInset(const StyleBasicShape& aBasicShape,
@@ -2594,27 +2594,26 @@ nsFloatManager::ShapeInfo::CreateCircleO
       aShapeBoxRect.GetPhysicalRect(aWM, aContainerSize);
   nsPoint physicalCenter = ShapeUtils::ComputeCircleOrEllipseCenter(
       aBasicShape, physicalShapeBoxRect);
   nsPoint logicalCenter =
       ConvertToFloatLogical(physicalCenter, aWM, aContainerSize);
 
   // Compute the circle or ellipse radii.
   nsSize radii;
-  StyleBasicShapeType type = aBasicShape.GetShapeType();
-  if (type == StyleBasicShapeType::Circle) {
+  if (aBasicShape.IsCircle()) {
     nscoord radius = ShapeUtils::ComputeCircleRadius(
         aBasicShape, physicalCenter, physicalShapeBoxRect);
     // Circles can use the three argument, math constructor for
     // EllipseShapeInfo.
     radii = nsSize(radius, radius);
     return MakeUnique<EllipseShapeInfo>(logicalCenter, radii, aShapeMargin);
   }
 
-  MOZ_ASSERT(type == StyleBasicShapeType::Ellipse);
+  MOZ_ASSERT(aBasicShape.IsEllipse());
   nsSize physicalRadii = ShapeUtils::ComputeEllipseRadii(
       aBasicShape, physicalCenter, physicalShapeBoxRect);
   LogicalSize logicalRadii(aWM, physicalRadii);
   radii = nsSize(logicalRadii.ISize(aWM), logicalRadii.BSize(aWM));
 
   // If radii are close to the same value, or if aShapeMargin is small
   // enough (as specified in css pixels), then we can use the three argument
   // constructor for EllipseShapeInfo, which uses math for a more efficient
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -19,17 +19,16 @@
 #include "nsPoint.h"
 #include "nsTArray.h"
 
 class nsIFrame;
 class nsPresContext;
 namespace mozilla {
 struct ReflowInput;
 class PresShell;
-class StyleBasicShape;
 }  // namespace mozilla
 
 enum class nsFlowAreaRectFlags : uint32_t {
   NoFlags = 0,
   HasFloats = 1 << 0,
   MayWiden = 1 << 1
 };
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsFlowAreaRectFlags)
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -9589,38 +9589,38 @@ static Maybe<wr::WrClipId> CreateSimpleC
 
   auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
   const nsRect refBox =
       nsLayoutUtils::ComputeGeometryBox(frame, clipPath.GetReferenceBox());
 
   AutoTArray<wr::ComplexClipRegion, 1> clipRegions;
 
   wr::LayoutRect rect;
-  switch (shape.GetShapeType()) {
-    case StyleBasicShapeType::Inset: {
+  switch (shape.tag) {
+    case StyleBasicShape::Tag::Inset: {
       const nsRect insetRect = ShapeUtils::ComputeInsetRect(shape, refBox) +
                                aDisplayItem.ToReferenceFrame();
 
       nscoord radii[8] = {0};
 
       if (ShapeUtils::ComputeInsetRadii(shape, insetRect, refBox, radii)) {
         clipRegions.AppendElement(
             wr::ToComplexClipRegion(insetRect, radii, appUnitsPerDevPixel));
       }
 
       rect = wr::ToRoundedLayoutRect(
           LayoutDeviceRect::FromAppUnits(insetRect, appUnitsPerDevPixel));
       break;
     }
-    case StyleBasicShapeType::Ellipse:
-    case StyleBasicShapeType::Circle: {
+    case StyleBasicShape::Tag::Ellipse:
+    case StyleBasicShape::Tag::Circle: {
       nsPoint center = ShapeUtils::ComputeCircleOrEllipseCenter(shape, refBox);
 
       nsSize radii;
-      if (shape.GetShapeType() == StyleBasicShapeType::Ellipse) {
+      if (shape.IsEllipse()) {
         radii = ShapeUtils::ComputeEllipseRadii(shape, center, refBox);
       } else {
         nscoord radius = ShapeUtils::ComputeCircleRadius(shape, center, refBox);
         radii = {radius, radius};
       }
 
       nsRect ellipseRect(aDisplayItem.ToReferenceFrame() + center -
                              nsPoint(radii.width, radii.height),
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -1555,21 +1555,16 @@ void Gecko_DestroyShapeSource(StyleShape
   aShape->~StyleShapeSource();
 }
 
 void Gecko_StyleShapeSource_SetURLValue(StyleShapeSource* aShape,
                                         URLValue* aURL) {
   aShape->SetURL(*aURL);
 }
 
-void Gecko_NewBasicShape(StyleShapeSource* aShape, StyleBasicShapeType aType) {
-  aShape->SetBasicShape(MakeUnique<StyleBasicShape>(aType),
-                        StyleGeometryBox::NoBox);
-}
-
 void Gecko_NewShapeImage(StyleShapeSource* aShape) {
   aShape->SetShapeImage(MakeUnique<nsStyleImage>());
 }
 
 void Gecko_NewStyleSVGPath(StyleShapeSource* aShape) {
   MOZ_ASSERT(aShape);
   aShape->SetPath(MakeUnique<StyleSVGPath>());
 }
--- a/layout/style/GeckoBindings.h
+++ b/layout/style/GeckoBindings.h
@@ -522,19 +522,16 @@ void Gecko_ResetStyleCoord(nsStyleUnit* 
 void Gecko_SetStyleCoordCalcValue(nsStyleUnit* unit, nsStyleUnion* value,
                                   nsStyleCoord::CalcValue calc);
 
 void Gecko_CopyShapeSourceFrom(mozilla::StyleShapeSource* dst,
                                const mozilla::StyleShapeSource* src);
 
 void Gecko_DestroyShapeSource(mozilla::StyleShapeSource* shape);
 
-void Gecko_NewBasicShape(mozilla::StyleShapeSource* shape,
-                         mozilla::StyleBasicShapeType type);
-
 void Gecko_NewShapeImage(mozilla::StyleShapeSource* shape);
 
 void Gecko_StyleShapeSource_SetURLValue(mozilla::StyleShapeSource* shape,
                                         mozilla::css::URLValue* uri);
 
 void Gecko_NewStyleSVGPath(mozilla::StyleShapeSource* shape);
 
 void Gecko_SetStyleMotion(mozilla::UniquePtr<mozilla::StyleMotion>* aMotion,
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -468,16 +468,17 @@ cbindgen-types = [
     { gecko = "StyleGenericColor", servo = "values::generics::color::Color" },
     { gecko = "StyleGenericColorOrAuto", servo = "values::generics::color::ColorOrAuto" },
     { gecko = "StyleGenericScrollbarColor", servo = "values::generics::ui::ScrollbarColor" },
     { gecko = "StyleRGBA", servo = "cssparser::RGBA" },
     { gecko = "StyleOrigin", servo = "stylesheets::Origin" },
     { gecko = "StyleGenericGradientItem", servo = "values::generics::image::GradientItem" },
     { gecko = "StyleGenericVerticalAlign", servo = "values::generics::box_::VerticalAlign" },
     { gecko = "StyleVerticalAlignKeyword", servo = "values::generics::box_::VerticalAlignKeyword" },
+    { gecko = "StyleGenericBasicShape", servo = "values::generics::basic_shape::BasicShape" },
 ]
 
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::RustCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
--- a/layout/style/ServoStyleConstsForwards.h
+++ b/layout/style/ServoStyleConstsForwards.h
@@ -13,16 +13,18 @@
 #endif
 
 #ifndef mozilla_ServoStyleConstsForwards_h
 #  define mozilla_ServoStyleConstsForwards_h
 
 #  include "nsColor.h"
 #  include "nsCoord.h"
 #  include "mozilla/AtomArray.h"
+#  include "mozilla/IntegerRange.h"
+#  include "mozilla/Span.h"
 #  include "Units.h"
 #  include "mozilla/gfx/Types.h"
 #  include "mozilla/MemoryReporting.h"
 #  include "mozilla/ServoTypes.h"
 #  include "mozilla/ServoBindingTypes.h"
 #  include "nsCSSPropertyID.h"
 #  include "nsCompatibility.h"
 
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -378,21 +378,16 @@ const KTableEntry nsCSSProps::kTextEmpha
 
 const KTableEntry nsCSSProps::kTextOverflowKTable[] = {
     {eCSSKeyword_clip, NS_STYLE_TEXT_OVERFLOW_CLIP},
     {eCSSKeyword_ellipsis, NS_STYLE_TEXT_OVERFLOW_ELLIPSIS},
     {eCSSKeyword_UNKNOWN, -1}};
 
 // keyword tables for SVG properties
 
-const KTableEntry nsCSSProps::kShapeRadiusKTable[] = {
-    {eCSSKeyword_closest_side, StyleShapeRadius::ClosestSide},
-    {eCSSKeyword_farthest_side, StyleShapeRadius::FarthestSide},
-    {eCSSKeyword_UNKNOWN, -1}};
-
 const KTableEntry nsCSSProps::kFilterFunctionKTable[] = {
     {eCSSKeyword_blur, NS_STYLE_FILTER_BLUR},
     {eCSSKeyword_brightness, NS_STYLE_FILTER_BRIGHTNESS},
     {eCSSKeyword_contrast, NS_STYLE_FILTER_CONTRAST},
     {eCSSKeyword_grayscale, NS_STYLE_FILTER_GRAYSCALE},
     {eCSSKeyword_invert, NS_STYLE_FILTER_INVERT},
     {eCSSKeyword_opacity, NS_STYLE_FILTER_OPACITY},
     {eCSSKeyword_saturate, NS_STYLE_FILTER_SATURATE},
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2560,150 +2560,16 @@ already_AddRefed<CSSValue> nsComputedDOM
 
   gfx::Matrix4x4 matrix = nsStyleTransformMatrix::ReadTransforms(
       aSpecifiedTransform->mHead, refBox,
       float(mozilla::AppUnitsPerCSSPixel()));
 
   return MatrixToCSSValue(matrix);
 }
 
-void nsComputedDOMStyle::BoxValuesToString(
-    nsAString& aString, const nsTArray<nsStyleCoord>& aBoxValues,
-    bool aClampNegativeCalc) {
-  MOZ_ASSERT(aBoxValues.Length() == 4, "wrong number of box values");
-  nsAutoString value1, value2, value3, value4;
-  SetCssTextToCoord(value1, aBoxValues[0], aClampNegativeCalc);
-  SetCssTextToCoord(value2, aBoxValues[1], aClampNegativeCalc);
-  SetCssTextToCoord(value3, aBoxValues[2], aClampNegativeCalc);
-  SetCssTextToCoord(value4, aBoxValues[3], aClampNegativeCalc);
-
-  // nsROCSSPrimitiveValue do not have binary comparison operators.
-  // Compare string results instead.
-  aString.Append(value1);
-  if (value1 != value2 || value1 != value3 || value1 != value4) {
-    aString.Append(' ');
-    aString.Append(value2);
-    if (value1 != value3 || value2 != value4) {
-      aString.Append(' ');
-      aString.Append(value3);
-      if (value2 != value4) {
-        aString.Append(' ');
-        aString.Append(value4);
-      }
-    }
-  }
-}
-
-void nsComputedDOMStyle::BasicShapeRadiiToString(nsAString& aCssText,
-                                                 const BorderRadius& aCorners) {
-  Servo_SerializeBorderRadius(&aCorners, &aCssText);
-}
-
-already_AddRefed<CSSValue>
-nsComputedDOMStyle::CreatePrimitiveValueForBasicShape(
-    const UniquePtr<StyleBasicShape>& aStyleBasicShape) {
-  MOZ_ASSERT(aStyleBasicShape, "Expect a valid basic shape pointer!");
-
-  StyleBasicShapeType type = aStyleBasicShape->GetShapeType();
-  // Shape function name and opening parenthesis.
-  nsAutoString shapeFunctionString;
-  AppendASCIItoUTF16(
-      nsCSSKeywords::GetStringValue(aStyleBasicShape->GetShapeTypeName()),
-      shapeFunctionString);
-  shapeFunctionString.Append('(');
-  switch (type) {
-    case StyleBasicShapeType::Polygon: {
-      bool hasEvenOdd =
-          aStyleBasicShape->GetFillRule() == StyleFillRule::Evenodd;
-      if (hasEvenOdd) {
-        shapeFunctionString.AppendLiteral("evenodd");
-      }
-      for (size_t i = 0; i < aStyleBasicShape->Coordinates().Length(); i += 2) {
-        nsAutoString coordString;
-        if (i > 0 || hasEvenOdd) {
-          shapeFunctionString.AppendLiteral(", ");
-        }
-        SetCssTextToCoord(coordString, aStyleBasicShape->Coordinates()[i],
-                          false);
-        shapeFunctionString.Append(coordString);
-        shapeFunctionString.Append(' ');
-        SetCssTextToCoord(coordString, aStyleBasicShape->Coordinates()[i + 1],
-                          false);
-        shapeFunctionString.Append(coordString);
-      }
-      break;
-    }
-    case StyleBasicShapeType::Circle:
-    case StyleBasicShapeType::Ellipse: {
-      const nsTArray<nsStyleCoord>& radii = aStyleBasicShape->Coordinates();
-      MOZ_ASSERT(
-          radii.Length() == (type == StyleBasicShapeType::Circle ? 1 : 2),
-          "wrong number of radii");
-      for (size_t i = 0; i < radii.Length(); ++i) {
-        nsAutoString radius;
-        RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
-        bool clampNegativeCalc = true;
-        SetValueToCoord(value, radii[i], clampNegativeCalc, nullptr,
-                        nsCSSProps::kShapeRadiusKTable);
-        value->GetCssText(radius);
-        shapeFunctionString.Append(radius);
-        shapeFunctionString.Append(' ');
-      }
-      shapeFunctionString.AppendLiteral("at ");
-
-      RefPtr<nsDOMCSSValueList> position = GetROCSSValueList(false);
-      nsAutoString positionString;
-      SetValueToPosition(aStyleBasicShape->GetPosition(), position);
-      position->GetCssText(positionString);
-      shapeFunctionString.Append(positionString);
-      break;
-    }
-    case StyleBasicShapeType::Inset: {
-      BoxValuesToString(shapeFunctionString, aStyleBasicShape->Coordinates(),
-                        false);
-      if (aStyleBasicShape->HasRadius()) {
-        shapeFunctionString.AppendLiteral(" round ");
-        nsAutoString radiiString;
-        BasicShapeRadiiToString(radiiString, aStyleBasicShape->GetRadius());
-        shapeFunctionString.Append(radiiString);
-      }
-      break;
-    }
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected type");
-  }
-  shapeFunctionString.Append(')');
-  RefPtr<nsROCSSPrimitiveValue> functionValue = new nsROCSSPrimitiveValue;
-  functionValue->SetString(shapeFunctionString);
-  return functionValue.forget();
-}
-
-template <typename ReferenceBox>
-already_AddRefed<CSSValue>
-nsComputedDOMStyle::CreatePrimitiveValueForShapeSource(
-    const UniquePtr<StyleBasicShape>& aStyleBasicShape,
-    ReferenceBox aReferenceBox, const KTableEntry aBoxKeywordTable[]) {
-  RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
-  if (aStyleBasicShape) {
-    valueList->AppendCSSValue(
-        CreatePrimitiveValueForBasicShape(aStyleBasicShape));
-  }
-
-  if (aReferenceBox == ReferenceBox::NoBox) {
-    return valueList.forget();
-  }
-
-  RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-  val->SetIdent(
-      nsCSSProps::ValueToKeywordEnum(aReferenceBox, aBoxKeywordTable));
-  valueList->AppendCSSValue(val.forget());
-
-  return valueList.forget();
-}
-
 void nsComputedDOMStyle::SetCssTextToCoord(nsAString& aCssText,
                                            const nsStyleCoord& aCoord,
                                            bool aClampNegativeCalc) {
   RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
   SetValueToCoord(value, aCoord, aClampNegativeCalc);
   value->GetCssText(aCssText);
 }
 
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -370,30 +370,16 @@ class nsComputedDOMStyle final : public 
   bool GetScrollFrameContentHeight(nscoord& aHeight);
   bool GetFrameBorderRectWidth(nscoord& aWidth);
   bool GetFrameBorderRectHeight(nscoord& aHeight);
 
   /* Helper functions for computing and serializing a nsStyleCoord. */
   void SetCssTextToCoord(nsAString& aCssText, const nsStyleCoord& aCoord,
                          bool aClampNegativeCalc);
 
-  template <typename ReferenceBox>
-  already_AddRefed<CSSValue> CreatePrimitiveValueForShapeSource(
-      const mozilla::UniquePtr<mozilla::StyleBasicShape>& aStyleBasicShape,
-      ReferenceBox aReferenceBox, const KTableEntry aBoxKeywordTable[]);
-
-  // Helper function for computing basic shape styles.
-  already_AddRefed<CSSValue> CreatePrimitiveValueForBasicShape(
-      const mozilla::UniquePtr<mozilla::StyleBasicShape>& aStyleBasicShape);
-  void BoxValuesToString(nsAString& aString,
-                         const nsTArray<nsStyleCoord>& aBoxValues,
-                         bool aClampNegativeCalc);
-  void BasicShapeRadiiToString(nsAString& aCssText,
-                               const mozilla::BorderRadius&);
-
   // Find out if we can safely skip flushing (i.e. pending restyles do not
   // affect mElement).
   bool NeedsToFlush() const;
 
   static ComputedStyleMap* GetComputedStyleMap();
 
   // We don't really have a good immutable representation of "presentation".
   // Given the way GetComputedStyle is currently used, we should just grab the
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -163,22 +163,16 @@ enum class StyleImageOrientation : uint8
 
 // scrollbar-width
 enum class StyleScrollbarWidth : uint8_t {
   Auto,
   Thin,
   None,
 };
 
-// <shape-radius> for <basic-shape>
-enum class StyleShapeRadius : uint8_t {
-  ClosestSide,
-  FarthestSide,
-};
-
 // Shape source type
 enum class StyleShapeSourceType : uint8_t {
   None,
   URL,    // clip-path only
   Image,  // shape-outside only
   Shape,
   Box,
   Path,  // SVG path function
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -806,40 +806,16 @@ nsChangeHint nsStyleSVG::CalcDifference(
       hint = nsChangeHint_NeutralChange;
     }
   }
 
   return hint;
 }
 
 // --------------------
-// 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:
-      return eCSSKeyword_polygon;
-    case StyleBasicShapeType::Circle:
-      return eCSSKeyword_circle;
-    case StyleBasicShapeType::Ellipse:
-      return eCSSKeyword_ellipse;
-    case StyleBasicShapeType::Inset:
-      return eCSSKeyword_inset;
-  }
-  MOZ_ASSERT_UNREACHABLE("unexpected type");
-  return eCSSKeyword_UNKNOWN;
-}
-
-// --------------------
 // StyleShapeSource
 StyleShapeSource::StyleShapeSource() : mBasicShape() {}
 
 StyleShapeSource::StyleShapeSource(const StyleShapeSource& aSource) {
   DoCopy(aSource);
 }
 
 StyleShapeSource::~StyleShapeSource() { DoDestroy(); }
@@ -952,20 +928,23 @@ void StyleShapeSource::DoCopy(const Styl
     case StyleShapeSourceType::URL:
       SetURL(aOther.URL());
       break;
 
     case StyleShapeSourceType::Image:
       SetShapeImage(MakeUnique<nsStyleImage>(aOther.ShapeImage()));
       break;
 
-    case StyleShapeSourceType::Shape:
-      SetBasicShape(MakeUnique<StyleBasicShape>(aOther.BasicShape()),
-                    aOther.GetReferenceBox());
+    case StyleShapeSourceType::Shape: {
+      UniquePtr<StyleBasicShape> shape(Servo_CloneBasicShape(&aOther.BasicShape()));
+      // TODO(emilio): This could be a copy-ctor call like above if we teach
+      // cbindgen to generate copy-constructors for tagged unions.
+      SetBasicShape(std::move(shape), aOther.GetReferenceBox());
       break;
+    }
 
     case StyleShapeSourceType::Box:
       SetReferenceBox(aOther.GetReferenceBox());
       break;
 
     case StyleShapeSourceType::Path:
       SetPath(MakeUnique<StyleSVGPath>(aOther.Path()));
       break;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1658,75 +1658,16 @@ struct StyleAnimation {
   float mDelay;
   RefPtr<nsAtom> mName;  // nsGkAtoms::_empty for 'none'
   dom::PlaybackDirection mDirection;
   dom::FillMode mFillMode;
   StyleAnimationPlayState mPlayState;
   float mIterationCount;  // mozilla::PositiveInfinity<float>() means infinite
 };
 
-class StyleBasicShape final {
- public:
-  explicit StyleBasicShape(StyleBasicShapeType);
-
-  StyleBasicShapeType GetShapeType() const { return mType; }
-  nsCSSKeyword GetShapeTypeName() const;
-
-  StyleFillRule GetFillRule() const { return mFillRule; }
-
-  const mozilla::Position& GetPosition() const {
-    MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
-                   mType == StyleBasicShapeType::Ellipse,
-               "expected circle or ellipse");
-    return mPosition;
-  }
-
-  bool HasRadius() const {
-    MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
-    NS_FOR_CSS_HALF_CORNERS(corner) {
-      auto& radius = mRadius.Get(corner);
-      if (radius.HasPercent() || radius.LengthInCSSPixels() != 0.0f) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  const mozilla::StyleBorderRadius& GetRadius() const {
-    MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
-    return mRadius;
-  }
-
-  // mCoordinates has coordinates for polygon or radii for
-  // ellipse and circle.
-  const nsTArray<nsStyleCoord>& Coordinates() const { return mCoordinates; }
-
-  bool operator==(const StyleBasicShape& aOther) const {
-    return mType == aOther.mType && mFillRule == aOther.mFillRule &&
-           mCoordinates == aOther.mCoordinates &&
-           mPosition == aOther.mPosition && mRadius == aOther.mRadius;
-  }
-  bool operator!=(const StyleBasicShape& aOther) const {
-    return !(*this == aOther);
-  }
-
- private:
-  StyleBasicShapeType mType;
-  StyleFillRule mFillRule;
-
-  // mCoordinates has coordinates for polygon or radii for
-  // ellipse and circle.
-  // (top, right, bottom, left) for inset
-  nsTArray<nsStyleCoord> mCoordinates;
-  // position of center for ellipse or circle
-  mozilla::Position mPosition;
-  // corner radii for inset (0 if not set)
-  mozilla::StyleBorderRadius mRadius;
-};
-
 struct StyleSVGPath final {
   const nsTArray<StylePathCommand>& Path() const { return mPath; }
 
   StyleFillRule FillRule() const { return mFillRule; }
 
   bool operator==(const StyleSVGPath& aOther) const {
     return mPath == aOther.mPath && mFillRule == aOther.mFillRule;
   }
@@ -1774,24 +1715,24 @@ struct StyleShapeSource final {
 
   // Iff we have "shape-outside:<image>" with an image URI (not a gradient),
   // this method returns the corresponding imgIRequest*. Else, returns
   // null.
   imgIRequest* GetShapeImageData() const;
 
   void SetShapeImage(UniquePtr<nsStyleImage> aShapeImage);
 
-  const StyleBasicShape& BasicShape() const {
+  const mozilla::StyleBasicShape& BasicShape() const {
     MOZ_ASSERT(mType == StyleShapeSourceType::Shape,
                "Wrong shape source type!");
     MOZ_ASSERT(mBasicShape);
     return *mBasicShape;
   }
 
-  void SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
+  void SetBasicShape(UniquePtr<mozilla::StyleBasicShape> aBasicShape,
                      StyleGeometryBox aReferenceBox);
 
   StyleGeometryBox GetReferenceBox() const {
     MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
                    mType == StyleShapeSourceType::Shape,
                "Wrong shape source type!");
     return mReferenceBox;
   }
@@ -1810,17 +1751,17 @@ struct StyleShapeSource final {
 
  private:
   void* operator new(size_t) = delete;
 
   void DoCopy(const StyleShapeSource& aOther);
   void DoDestroy();
 
   union {
-    mozilla::UniquePtr<StyleBasicShape> mBasicShape;
+    mozilla::UniquePtr<mozilla::StyleBasicShape> mBasicShape;
     mozilla::UniquePtr<nsStyleImage> mShapeImage;
     mozilla::UniquePtr<StyleSVGPath> mSVGPath;
     // TODO: Bug 1480665, implement ray() function.
   };
   StyleShapeSourceType mType = StyleShapeSourceType::None;
   StyleGeometryBox mReferenceBox = StyleGeometryBox::NoBox;
 };
 
@@ -2722,16 +2663,17 @@ class nsStyleSVGPaint {
  private:
   void Reset();
   void Assign(const nsStyleSVGPaint& aOther);
 
   union ColorOrPaintServer {
     mozilla::StyleColor mColor;
     mozilla::css::URLValue* mPaintServer;
     explicit ColorOrPaintServer(mozilla::StyleColor c) : mColor(c) {}
+    ~ColorOrPaintServer() {}  // Caller must call Reset().
   };
   ColorOrPaintServer mPaint;
   nsStyleSVGPaintType mType;
   nsStyleSVGFallbackType mFallbackType;
   mozilla::StyleColor mFallbackColor;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG {
--- a/layout/svg/nsCSSClipPathInstance.cpp
+++ b/layout/svg/nsCSSClipPathInstance.cpp
@@ -111,24 +111,24 @@ already_AddRefed<Path> nsCSSClipPathInst
     return builder->Finish();
   }
 
   MOZ_ASSERT(mClipPathStyle.GetType() == StyleShapeSourceType::Shape);
 
   r = ToAppUnits(r.ToNearestPixels(appUnitsPerDevPixel), appUnitsPerDevPixel);
 
   const auto& basicShape = mClipPathStyle.BasicShape();
-  switch (basicShape.GetShapeType()) {
-    case StyleBasicShapeType::Circle:
+  switch (basicShape.tag) {
+    case StyleBasicShape::Tag::Circle:
       return CreateClipPathCircle(aDrawTarget, r);
-    case StyleBasicShapeType::Ellipse:
+    case StyleBasicShape::Tag::Ellipse:
       return CreateClipPathEllipse(aDrawTarget, r);
-    case StyleBasicShapeType::Polygon:
+    case StyleBasicShape::Tag::Polygon:
       return CreateClipPathPolygon(aDrawTarget, r);
-    case StyleBasicShapeType::Inset:
+    case StyleBasicShape::Tag::Inset:
       return CreateClipPathInset(aDrawTarget, r);
       break;
     default:
       MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected shape type");
   }
   // Return an empty Path:
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
   return builder->Finish();
@@ -167,17 +167,17 @@ already_AddRefed<Path> nsCSSClipPathInst
                   Size(radii.width, radii.height) / appUnitsPerDevPixel);
   builder->Close();
   return builder->Finish();
 }
 
 already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathPolygon(
     DrawTarget* aDrawTarget, const nsRect& aRefBox) {
   const auto& basicShape = mClipPathStyle.BasicShape();
-  auto fillRule = basicShape.GetFillRule() == StyleFillRule::Nonzero
+  auto fillRule = basicShape.AsPolygon().fill == StyleFillRule::Nonzero
                       ? FillRule::FILL_WINDING
                       : FillRule::FILL_EVEN_ODD;
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder(fillRule);
 
   nsTArray<nsPoint> vertices =
       ShapeUtils::ComputePolygonVertices(basicShape, aRefBox);
   if (vertices.IsEmpty()) {
     MOZ_ASSERT_UNREACHABLE(
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -177,17 +177,17 @@ bool nsSVGIntegrationUtils::UsingSimpleC
   }
 
   const auto& clipPath = style->mClipPath;
   if (clipPath.GetType() != StyleShapeSourceType::Shape) {
     return false;
   }
 
   const auto& shape = clipPath.BasicShape();
-  return (shape.GetShapeType() != StyleBasicShapeType::Polygon);
+  return !shape.IsPolygon();
 }
 
 nsPoint nsSVGIntegrationUtils::GetOffsetToBoundingBox(nsIFrame* aFrame) {
   if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
     // Do NOT call GetAllInFlowRectsUnion for SVG - it will get the
     // covered region relative to the nsSVGOuterSVGFrame, which is absolutely
     // not what we want. SVG frames are always in user space, so they have
     // no offset adjustment to make.
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -527,54 +527,43 @@ impl nsStyleImage {
             kind,
             compat_mode,
         })
     }
 }
 
 pub mod basic_shape {
     //! Conversions from and to CSS shape representations.
-
-    use crate::gecko::values::GeckoStyleCoordConvertible;
-    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::refptr::RefPtr;
     use crate::values::computed::basic_shape::{
-        BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
+        BasicShape, ClippingShape, FloatAreaShape,
     };
-    use crate::values::computed::length::LengthPercentage;
     use crate::values::computed::motion::OffsetPath;
     use crate::values::computed::url::ComputedUrl;
-    use crate::values::generics::basic_shape::{
-        BasicShape as GenericBasicShape, InsetRect, Polygon,
-    };
-    use crate::values::generics::basic_shape::{Circle, Ellipse, Path, PolygonCoord};
-    use crate::values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource};
-    use crate::values::generics::rect::Rect;
+    use crate::values::generics::basic_shape::{Path, GeometryBox, ShapeBox, ShapeSource};
     use crate::values::specified::SVGPathData;
-    use std::borrow::Borrow;
 
     impl StyleShapeSource {
         /// Convert StyleShapeSource to ShapeSource except URL and Image
         /// types.
         fn into_shape_source<ReferenceBox, ImageOrUrl>(
             &self,
         ) -> Option<ShapeSource<BasicShape, ReferenceBox, ImageOrUrl>>
         where
             ReferenceBox: From<StyleGeometryBox>,
         {
             match self.mType {
                 StyleShapeSourceType::None => Some(ShapeSource::None),
                 StyleShapeSourceType::Box => Some(ShapeSource::Box(self.mReferenceBox.into())),
                 StyleShapeSourceType::Shape => {
                     let other_shape = unsafe { &*self.__bindgen_anon_1.mBasicShape.as_ref().mPtr };
-                    let shape = other_shape.into();
+                    let shape = Box::new(other_shape.clone());
                     let reference_box = if self.mReferenceBox == StyleGeometryBox::NoBox {
                         None
                     } else {
                         Some(self.mReferenceBox.into())
                     };
                     Some(ShapeSource::Shape(shape, reference_box))
                 },
                 StyleShapeSourceType::URL | StyleShapeSourceType::Image => None,
@@ -648,77 +637,16 @@ pub mod basic_shape {
                 StyleShapeSourceType::Shape |
                 StyleShapeSourceType::Box |
                 StyleShapeSourceType::URL |
                 StyleShapeSourceType::Image => unreachable!("Unsupported offset-path type"),
             }
         }
     }
 
-    impl<'a> From<&'a StyleBasicShape> for BasicShape {
-        fn from(other: &'a StyleBasicShape) -> Self {
-            match other.mType {
-                StyleBasicShapeType::Inset => {
-                    let t = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[0]);
-                    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 = other.mRadius;
-                    let rect = Rect::new(
-                        t.expect("inset() offset should be a length, percentage, or calc value"),
-                        r.expect("inset() offset should be a length, percentage, or calc value"),
-                        b.expect("inset() offset should be a length, percentage, or calc value"),
-                        l.expect("inset() offset should be a length, percentage, or calc value"),
-                    );
-                    GenericBasicShape::Inset(InsetRect { rect, round })
-                },
-                StyleBasicShapeType::Circle => GenericBasicShape::Circle(Circle {
-                    radius: (&other.mCoordinates[0]).into(),
-                    position: other.mPosition,
-                }),
-                StyleBasicShapeType::Ellipse => GenericBasicShape::Ellipse(Ellipse {
-                    semiaxis_x: (&other.mCoordinates[0]).into(),
-                    semiaxis_y: (&other.mCoordinates[1]).into(),
-                    position: other.mPosition,
-                }),
-                StyleBasicShapeType::Polygon => {
-                    let mut coords = Vec::with_capacity(other.mCoordinates.len() / 2);
-                    for i in 0..(other.mCoordinates.len() / 2) {
-                        let x = 2 * i;
-                        let y = x + 1;
-                        coords.push(PolygonCoord(
-                            LengthPercentage::from_gecko_style_coord(&other.mCoordinates[x])
-                                .expect(
-                                    "polygon() coordinate should be a length, percentage, \
-                                     or calc value",
-                                ),
-                            LengthPercentage::from_gecko_style_coord(&other.mCoordinates[y])
-                                .expect(
-                                    "polygon() coordinate should be a length, percentage, \
-                                     or calc value",
-                                ),
-                        ))
-                    }
-                    GenericBasicShape::Polygon(Polygon {
-                        fill: other.mFillRule,
-                        coordinates: coords,
-                    })
-                },
-            }
-        }
-    }
-
-    impl<'a> From<&'a nsStyleCoord> for ShapeRadius {
-        fn from(other: &'a nsStyleCoord) -> Self {
-            let other = other.borrow();
-            ShapeRadius::from_gecko_style_coord(other)
-                .expect("<shape-radius> should be a length, percentage, calc, or keyword value")
-        }
-    }
-
     impl From<ShapeBox> for StyleGeometryBox {
         fn from(reference: ShapeBox) -> Self {
             use crate::gecko_bindings::structs::StyleGeometryBox::*;
             match reference {
                 ShapeBox::ContentBox => ContentBox,
                 ShapeBox::PaddingBox => PaddingBox,
                 ShapeBox::BorderBox => BorderBox,
                 ShapeBox::MarginBox => MarginBox,
--- a/servo/components/style/gecko/values.rs
+++ b/servo/components/style/gecko/values.rs
@@ -3,22 +3,20 @@
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 #![allow(unsafe_code)]
 
 //! Different kind of helpers to interact with Gecko values.
 
 use crate::counter_style::{Symbol, Symbols};
 use crate::gecko_bindings::structs::{nsStyleCoord, CounterStylePtr};
-use crate::gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius};
+use crate::gecko_bindings::structs::StyleGridTrackBreadth;
 use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
-use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
 use crate::values::computed::{Angle, Length, LengthPercentage};
 use crate::values::computed::{Number, NumberOrPercentage, Percentage};
-use crate::values::generics::basic_shape::ShapeRadius;
 use crate::values::generics::gecko::ScrollSnapPoint;
 use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
 use crate::values::generics::length::LengthPercentageOrAuto;
 use crate::values::generics::{CounterStyleOrNone, NonNegative};
 use crate::values::Either;
 use crate::{Atom, Zero};
 use app_units::Au;
 use cssparser::RGBA;
@@ -187,45 +185,16 @@ impl<L: GeckoStyleCoordConvertible> Geck
                 },
                 CoordDataValue::FlexFraction(fr) => Some(TrackBreadth::Fr(fr)),
                 CoordDataValue::Auto => Some(TrackBreadth::Keyword(TrackKeyword::Auto)),
                 _ => L::from_gecko_style_coord(coord).map(TrackBreadth::Breadth),
             })
     }
 }
 
-impl GeckoStyleCoordConvertible for ComputedShapeRadius {
-    fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
-        match *self {
-            ShapeRadius::ClosestSide => coord.set_value(CoordDataValue::Enumerated(
-                StyleShapeRadius::ClosestSide as u32,
-            )),
-            ShapeRadius::FarthestSide => coord.set_value(CoordDataValue::Enumerated(
-                StyleShapeRadius::FarthestSide as u32,
-            )),
-            ShapeRadius::Length(lp) => lp.to_gecko_style_coord(coord),
-        }
-    }
-
-    fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
-        match coord.as_value() {
-            CoordDataValue::Enumerated(v) => {
-                if v == StyleShapeRadius::ClosestSide as u32 {
-                    Some(ShapeRadius::ClosestSide)
-                } else if v == StyleShapeRadius::FarthestSide as u32 {
-                    Some(ShapeRadius::FarthestSide)
-                } else {
-                    None
-                }
-            },
-            _ => GeckoStyleCoordConvertible::from_gecko_style_coord(coord).map(ShapeRadius::Length),
-        }
-    }
-}
-
 impl<T: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for Option<T> {
     fn to_gecko_style_coord<U: CoordDataMut>(&self, coord: &mut U) {
         if let Some(ref me) = *self {
             me.to_gecko_style_coord(coord);
         } else {
             coord.set_value(CoordDataValue::None);
         }
     }
--- a/servo/components/style/owned_slice.rs
+++ b/servo/components/style/owned_slice.rs
@@ -15,16 +15,19 @@ use to_shmem::{SharedMemoryBuilder, ToSh
 /// understand.
 ///
 /// We could rely on the struct layout of `Box<[T]>` per:
 ///
 ///   https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/pointers.md
 ///
 /// But handling fat pointers with cbindgen both in structs and argument
 /// positions more generally is a bit tricky.
+///
+/// cbindgen:derive-eq=false
+/// cbindgen:derive-neq=false
 #[repr(C)]
 pub struct OwnedSlice<T: Sized> {
     ptr: NonNull<T>,
     len: usize,
     _phantom: PhantomData<T>,
 }
 
 impl<T: Sized> Default for OwnedSlice<T> {
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -4041,26 +4041,25 @@ fn set_style_svg_path(
     gecko_path.mPath.assign_from_iter_pod(servo_path.commands().iter().cloned());
 
     // Setup fill-rule.
     gecko_path.mFillRule = fill;
 }
 
 <%def name="impl_shape_source(ident, gecko_ffi_name)">
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
-        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::values::GeckoStyleCoordConvertible;
-        use crate::values::generics::basic_shape::{BasicShape, ShapeSource};
+        use crate::values::generics::basic_shape::ShapeSource;
+        use crate::gecko_bindings::structs::StyleShapeSourceType;
+        use crate::gecko_bindings::structs::StyleGeometryBox;
 
         let ref mut ${ident} = self.gecko.${gecko_ffi_name};
 
-        // clean up existing struct
-        unsafe { Gecko_DestroyShapeSource(${ident}) };
+        // clean up existing struct.
+        unsafe { bindings::Gecko_DestroyShapeSource(${ident}) };
+
         ${ident}.mType = StyleShapeSourceType::None;
 
         match v {
             % if ident == "clip_path":
             ShapeSource::ImageOrUrl(ref url) => {
                 unsafe {
                     bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.url_value_ptr())
                 }
@@ -4079,82 +4078,22 @@ fn set_style_svg_path(
             % endif
             ShapeSource::None => {} // don't change the type
             ShapeSource::Box(reference) => {
                 ${ident}.mReferenceBox = reference.into();
                 ${ident}.mType = StyleShapeSourceType::Box;
             }
             ShapeSource::Path(p) => set_style_svg_path(${ident}, &p.path, p.fill),
             ShapeSource::Shape(servo_shape, maybe_box) => {
-                fn init_shape(${ident}: &mut StyleShapeSource, basic_shape_type: StyleBasicShapeType)
-                              -> &mut StyleBasicShape {
-                    unsafe {
-                        // Create StyleBasicShape in StyleShapeSource. mReferenceBox and mType
-                        // will be set manually later.
-                        Gecko_NewBasicShape(${ident}, basic_shape_type);
-                        &mut *${ident}.__bindgen_anon_1.mBasicShape.as_mut().mPtr
-                    }
+                unsafe {
+                    ${ident}.__bindgen_anon_1.mBasicShape.as_mut().mPtr =
+                        Box::into_raw(servo_shape);
                 }
-                match servo_shape {
-                    BasicShape::Inset(inset) => {
-                        let shape = init_shape(${ident}, StyleBasicShapeType::Inset);
-                        unsafe { shape.mCoordinates.set_len(4) };
-
-                        // set_len() can't call constructors, so the coordinates
-                        // can contain any value. set_value() attempts to free
-                        // allocated coordinates, so we don't want to feed it
-                        // garbage values which it may misinterpret.
-                        // Instead, we use leaky_set_value to blindly overwrite
-                        // the garbage data without
-                        // attempting to clean up.
-                        shape.mCoordinates[0].leaky_set_null();
-                        inset.rect.0.to_gecko_style_coord(&mut shape.mCoordinates[0]);
-                        shape.mCoordinates[1].leaky_set_null();
-                        inset.rect.1.to_gecko_style_coord(&mut shape.mCoordinates[1]);
-                        shape.mCoordinates[2].leaky_set_null();
-                        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]);
-                        shape.mRadius = inset.round;
-                    }
-                    BasicShape::Circle(circ) => {
-                        let shape = init_shape(${ident}, StyleBasicShapeType::Circle);
-                        unsafe { shape.mCoordinates.set_len(1) };
-                        shape.mCoordinates[0].leaky_set_null();
-                        circ.radius.to_gecko_style_coord(&mut shape.mCoordinates[0]);
-
-                        shape.mPosition = circ.position.into();
-                    }
-                    BasicShape::Ellipse(el) => {
-                        let shape = init_shape(${ident}, StyleBasicShapeType::Ellipse);
-                        unsafe { shape.mCoordinates.set_len(2) };
-                        shape.mCoordinates[0].leaky_set_null();
-                        el.semiaxis_x.to_gecko_style_coord(&mut shape.mCoordinates[0]);
-                        shape.mCoordinates[1].leaky_set_null();
-                        el.semiaxis_y.to_gecko_style_coord(&mut shape.mCoordinates[1]);
-
-                        shape.mPosition = el.position.into();
-                    }
-                    BasicShape::Polygon(poly) => {
-                        let shape = init_shape(${ident}, StyleBasicShapeType::Polygon);
-                        unsafe {
-                            shape.mCoordinates.set_len(poly.coordinates.len() as u32 * 2);
-                        }
-                        for (i, coord) in poly.coordinates.iter().enumerate() {
-                            shape.mCoordinates[2 * i].leaky_set_null();
-                            shape.mCoordinates[2 * i + 1].leaky_set_null();
-                            coord.0.to_gecko_style_coord(&mut shape.mCoordinates[2 * i]);
-                            coord.1.to_gecko_style_coord(&mut shape.mCoordinates[2 * i + 1]);
-                        }
-                        shape.mFillRule = poly.fill;
-                    }
-                }
-
-                ${ident}.mReferenceBox = maybe_box.map(Into::into)
-                                                  .unwrap_or(StyleGeometryBox::NoBox);
+                ${ident}.mReferenceBox =
+                    maybe_box.map(Into::into).unwrap_or(StyleGeometryBox::NoBox);
                 ${ident}.mType = StyleShapeSourceType::Shape;
             }
         }
 
     }
 
     pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         (&self.gecko.${gecko_ffi_name}).into()
--- a/servo/components/style/properties/longhands/svg.mako.rs
+++ b/servo/components/style/properties/longhands/svg.mako.rs
@@ -82,18 +82,18 @@
     spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type",
 )}
 
 ${helpers.predefined_type(
     "clip-path",
     "basic_shape::ClippingShape",
     "generics::basic_shape::ShapeSource::None",
     products="gecko",
+    animation_value_type="basic_shape::ClippingShape",
     boxed=True,
-    animation_value_type="basic_shape::ClippingShape",
     flags="CREATES_STACKING_CONTEXT",
     spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path",
 )}
 
 ${helpers.single_keyword(
     "mask-mode",
     "match-source alpha luminance",
     gecko_enum_prefix="StyleMaskMode",
--- a/servo/components/style/values/animated/mod.rs
+++ b/servo/components/style/values/animated/mod.rs
@@ -11,17 +11,16 @@
 use crate::properties::PropertyId;
 use crate::values::computed::length::LengthPercentage;
 use crate::values::computed::url::ComputedUrl;
 use crate::values::computed::Angle as ComputedAngle;
 use crate::values::computed::Image;
 use crate::values::specified::SVGPathData;
 use crate::values::CSSFloat;
 use app_units::Au;
-use euclid::Point2D;
 use smallvec::SmallVec;
 use std::cmp;
 
 pub mod color;
 pub mod effects;
 mod font;
 mod grid;
 mod length;
@@ -236,26 +235,20 @@ where
 
 impl Animate for Au {
     #[inline]
     fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
         Ok(Au::new(self.0.animate(&other.0, procedure)?))
     }
 }
 
-impl<T> Animate for Point2D<T>
-where
-    T: Animate,
-{
+impl<T: Animate> Animate for Box<T> {
     #[inline]
     fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
-        Ok(Point2D::new(
-            self.x.animate(&other.x, procedure)?,
-            self.y.animate(&other.y, procedure)?,
-        ))
+        Ok(Box::new((**self).animate(&other, procedure)?))
     }
 }
 
 impl<T> ToAnimatedValue for Option<T>
 where
     T: ToAnimatedValue,
 {
     type AnimatedValue = Option<<T as ToAnimatedValue>::AnimatedValue>;
@@ -283,16 +276,34 @@ where
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
         animated.into_iter().map(T::from_animated_value).collect()
     }
 }
 
+impl<T> ToAnimatedValue for Box<T>
+where
+    T: ToAnimatedValue,
+{
+    type AnimatedValue = Box<<T as ToAnimatedValue>::AnimatedValue>;
+
+    #[inline]
+    fn to_animated_value(self) -> Self::AnimatedValue {
+        Box::new((*self).to_animated_value())
+    }
+
+    #[inline]
+    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
+        Box::new(T::from_animated_value(*animated))
+    }
+}
+
+
 impl<T> ToAnimatedValue for Box<[T]>
 where
     T: ToAnimatedValue,
 {
     type AnimatedValue = Box<[<T as ToAnimatedValue>::AnimatedValue]>;
 
     #[inline]
     fn to_animated_value(self) -> Self::AnimatedValue {
@@ -323,17 +334,17 @@ where
 
     #[inline]
     fn to_animated_value(self) -> Self::AnimatedValue {
         self.into_box().to_animated_value().into()
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
-        Box::from_animated_value(animated.into_box()).into()
+        Self::from(Box::from_animated_value(animated.into_box()))
     }
 }
 
 impl<T> ToAnimatedValue for SmallVec<[T; 1]>
 where
     T: ToAnimatedValue,
 {
     type AnimatedValue = SmallVec<[T::AnimatedValue; 1]>;
--- a/servo/components/style/values/computed/basic_shape.rs
+++ b/servo/components/style/values/computed/basic_shape.rs
@@ -18,17 +18,17 @@ pub use crate::values::generics::basic_s
 
 /// A computed clipping shape.
 pub type ClippingShape = generic::ClippingShape<BasicShape, ComputedUrl>;
 
 /// A computed float area shape.
 pub type FloatAreaShape = generic::FloatAreaShape<BasicShape, Image>;
 
 /// A computed basic shape.
-pub type BasicShape = generic::BasicShape<
+pub type BasicShape = generic::GenericBasicShape<
     LengthPercentage,
     LengthPercentage,
     LengthPercentage,
     NonNegativeLengthPercentage,
 >;
 
 /// The computed value of `inset()`
 pub type InsetRect = generic::InsetRect<LengthPercentage, NonNegativeLengthPercentage>;
@@ -36,17 +36,17 @@ pub type InsetRect = generic::InsetRect<
 /// A computed circle.
 pub type Circle = generic::Circle<LengthPercentage, LengthPercentage, NonNegativeLengthPercentage>;
 
 /// A computed ellipse.
 pub type Ellipse =
     generic::Ellipse<LengthPercentage, LengthPercentage, NonNegativeLengthPercentage>;
 
 /// The computed value of `ShapeRadius`
-pub type ShapeRadius = generic::ShapeRadius<NonNegativeLengthPercentage>;
+pub type ShapeRadius = generic::GenericShapeRadius<NonNegativeLengthPercentage>;
 
 impl ToCss for Circle {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: Write,
     {
         dest.write_str("circle(")?;
         self.radius.to_css(dest)?;
--- a/servo/components/style/values/generics/basic_shape.rs
+++ b/servo/components/style/values/generics/basic_shape.rs
@@ -2,18 +2,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the [`basic-shape`](https://drafts.csswg.org/css-shapes/#typedef-basic-shape)
 //! types that are generic over their `ToCss` implementations.
 
 use crate::values::animated::{Animate, Procedure, ToAnimatedZero};
 use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
-use crate::values::generics::border::BorderRadius;
-use crate::values::generics::position::Position;
+use crate::values::generics::border::GenericBorderRadius;
+use crate::values::generics::position::GenericPosition;
 use crate::values::generics::rect::Rect;
 use crate::values::specified::SVGPathData;
 use crate::Zero;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
 /// A clipping shape, for `clip-path`.
 pub type ClippingShape<BasicShape, Url> = ShapeSource<BasicShape, GeometryBox, Url>;
@@ -84,17 +84,17 @@ pub enum ShapeBox {
     ToComputedValue,
     ToCss,
     ToResolvedValue,
     ToShmem,
 )]
 pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
     #[animation(error)]
     ImageOrUrl(ImageOrUrl),
-    Shape(BasicShape, Option<ReferenceBox>),
+    Shape(Box<BasicShape>, Option<ReferenceBox>),
     #[animation(error)]
     Box(ReferenceBox),
     #[css(function)]
     Path(Path),
     #[animation(error)]
     None,
 }
 
@@ -108,55 +108,59 @@ pub enum ShapeSource<BasicShape, Referen
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
     ToResolvedValue,
     ToShmem,
 )]
-pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
+#[repr(C, u8)]
+pub enum GenericBasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
     Inset(
         #[css(field_bound)]
         #[shmem(field_bound)]
         InsetRect<LengthPercentage, NonNegativeLengthPercentage>,
     ),
     Circle(
         #[css(field_bound)]
         #[shmem(field_bound)]
         Circle<H, V, NonNegativeLengthPercentage>,
     ),
     Ellipse(
         #[css(field_bound)]
         #[shmem(field_bound)]
         Ellipse<H, V, NonNegativeLengthPercentage>,
     ),
-    Polygon(Polygon<LengthPercentage>),
+    Polygon(GenericPolygon<LengthPercentage>),
 }
 
+pub use self::GenericBasicShape as BasicShape;
+
 /// <https://drafts.csswg.org/css-shapes/#funcdef-inset>
 #[allow(missing_docs)]
 #[css(function = "inset")]
 #[derive(
     Animate,
     Clone,
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToResolvedValue,
     ToShmem,
 )]
+#[repr(C)]
 pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
     pub rect: Rect<LengthPercentage>,
     #[shmem(field_bound)]
-    pub round: BorderRadius<NonNegativeLengthPercentage>,
+    pub round: GenericBorderRadius<NonNegativeLengthPercentage>,
 }
 
 /// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
 #[allow(missing_docs)]
 #[css(function)]
 #[derive(
     Animate,
     Clone,
@@ -166,19 +170,20 @@ pub struct InsetRect<LengthPercentage, N
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToResolvedValue,
     ToShmem,
 )]
+#[repr(C)]
 pub struct Circle<H, V, NonNegativeLengthPercentage> {
-    pub position: Position<H, V>,
-    pub radius: ShapeRadius<NonNegativeLengthPercentage>,
+    pub position: GenericPosition<H, V>,
+    pub radius: GenericShapeRadius<NonNegativeLengthPercentage>,
 }
 
 /// <https://drafts.csswg.org/css-shapes/#funcdef-ellipse>
 #[allow(missing_docs)]
 #[css(function)]
 #[derive(
     Animate,
     Clone,
@@ -188,20 +193,21 @@ pub struct Circle<H, V, NonNegativeLengt
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToResolvedValue,
     ToShmem,
 )]
+#[repr(C)]
 pub struct Ellipse<H, V, NonNegativeLengthPercentage> {
-    pub position: Position<H, V>,
-    pub semiaxis_x: ShapeRadius<NonNegativeLengthPercentage>,
-    pub semiaxis_y: ShapeRadius<NonNegativeLengthPercentage>,
+    pub position: GenericPosition<H, V>,
+    pub semiaxis_x: GenericShapeRadius<NonNegativeLengthPercentage>,
+    pub semiaxis_y: GenericShapeRadius<NonNegativeLengthPercentage>,
 }
 
 /// <https://drafts.csswg.org/css-shapes/#typedef-shape-radius>
 #[allow(missing_docs)]
 #[derive(
     Animate,
     Clone,
     ComputeSquaredDistance,
@@ -211,62 +217,69 @@ pub struct Ellipse<H, V, NonNegativeLeng
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
     ToResolvedValue,
     ToShmem,
 )]
-pub enum ShapeRadius<NonNegativeLengthPercentage> {
+#[repr(C, u8)]
+pub enum GenericShapeRadius<NonNegativeLengthPercentage> {
     Length(NonNegativeLengthPercentage),
     #[animation(error)]
     ClosestSide,
     #[animation(error)]
     FarthestSide,
 }
 
+pub use self::GenericShapeRadius as ShapeRadius;
+
 /// A generic type for representing the `polygon()` function
 ///
 /// <https://drafts.csswg.org/css-shapes/#funcdef-polygon>
-#[css(comma, function)]
+#[css(comma, function = "polygon")]
 #[derive(
     Clone,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
     ToResolvedValue,
     ToShmem,
 )]
-pub struct Polygon<LengthPercentage> {
+#[repr(C)]
+pub struct GenericPolygon<LengthPercentage> {
     /// The filling rule for a polygon.
     #[css(skip_if = "fill_is_default")]
     pub fill: FillRule,
     /// A collection of (x, y) coordinates to draw the polygon.
     #[css(iterable)]
-    pub coordinates: Vec<PolygonCoord<LengthPercentage>>,
+    pub coordinates: crate::OwnedSlice<PolygonCoord<LengthPercentage>>,
 }
 
+pub use self::GenericPolygon as Polygon;
+
 /// Coordinates for Polygon.
 #[derive(
     Clone,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
     ToResolvedValue,
     ToShmem,
 )]
+#[repr(C)]
 pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercentage);
 
 // https://drafts.csswg.org/css-shapes/#typedef-fill-rule
 // NOTE: Basic shapes spec says that these are the only two values, however
 // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
 // says that it can also be `inherit`
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
@@ -388,17 +401,18 @@ where
             .iter()
             .zip(other.coordinates.iter())
             .map(|(this, other)| {
                 Ok(PolygonCoord(
                     this.0.animate(&other.0, procedure)?,
                     this.1.animate(&other.1, procedure)?,
                 ))
             })
-            .collect::<Result<Vec<_>, _>>()?;
+            .collect::<Result<Vec<_>, _>>()?
+            .into();
         Ok(Polygon {
             fill: self.fill,
             coordinates,
         })
     }
 }
 
 impl<L> ComputeSquaredDistance for Polygon<L>
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -50,17 +50,17 @@ pub type Circle =
 /// A specified ellipse.
 pub type Ellipse =
     generic::Ellipse<HorizontalPosition, VerticalPosition, NonNegativeLengthPercentage>;
 
 /// The specified value of `ShapeRadius`
 pub type ShapeRadius = generic::ShapeRadius<NonNegativeLengthPercentage>;
 
 /// The specified value of `Polygon`
-pub type Polygon = generic::Polygon<LengthPercentage>;
+pub type Polygon = generic::GenericPolygon<LengthPercentage>;
 
 #[cfg(feature = "gecko")]
 fn is_clip_path_path_enabled(context: &ParserContext) -> bool {
     use crate::gecko_bindings::structs::mozilla;
     context.chrome_rules_enabled() ||
         unsafe { mozilla::StaticPrefs_sVarCache_layout_css_clip_path_path_enabled }
 }
 #[cfg(feature = "servo")]
@@ -133,31 +133,31 @@ where
 
         while parse_component(context, input, &mut shape) ||
             parse_component(context, input, &mut ref_box)
         {
             //
         }
 
         if let Some(shp) = shape {
-            return Ok(ShapeSource::Shape(shp, ref_box));
+            return Ok(ShapeSource::Shape(Box::new(shp), ref_box));
         }
 
         ref_box
-            .map(|v| ShapeSource::Box(v))
+            .map(ShapeSource::Box)
             .ok_or(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
     }
 }
 
 impl Parse for GeometryBox {
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
-        if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
+        if let Ok(shape_box) = input.try(ShapeBox::parse) {
             return Ok(GeometryBox::ShapeBox(shape_box));
         }
 
         try_match_ident_ignore_ascii_case! { input,
             "fill-box" => Ok(GeometryBox::FillBox),
             "stroke-box" => Ok(GeometryBox::StrokeBox),
             "view-box" => Ok(GeometryBox::ViewBox),
         }
@@ -347,27 +347,24 @@ impl Polygon {
         let fill = input
             .try(|i| -> Result<_, ParseError> {
                 let fill = FillRule::parse(i)?;
                 i.expect_comma()?; // only eat the comma if there is something before it
                 Ok(fill)
             })
             .unwrap_or_default();
 
-        let buf = input.parse_comma_separated(|i| {
+        let coordinates = input.parse_comma_separated(|i| {
             Ok(PolygonCoord(
                 LengthPercentage::parse(context, i)?,
                 LengthPercentage::parse(context, i)?,
             ))
-        })?;
+        })?.into();
 
-        Ok(Polygon {
-            fill: fill,
-            coordinates: buf,
-        })
+        Ok(Polygon { fill, coordinates })
     }
 }
 
 impl Parse for Path {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
--- a/servo/ports/geckolib/cbindgen.toml
+++ b/servo/ports/geckolib/cbindgen.toml
@@ -33,16 +33,17 @@ derive_eq = true
 derive_neq = true
 
 [macro_expansion]
 bitflags = true
 
 [enum]
 derive_helper_methods = true
 derive_const_casts = true
+derive_tagged_enum_destructor = true
 cast_assert_name = "MOZ_ASSERT"
 
 [export]
 prefix = "Style"
 include = [
   "Appearance",
   "BreakBetween",
   "BreakWithin",
@@ -113,16 +114,18 @@ include = [
   "Owned",
   "OwnedOrNull",
   "Strong",
   "ScrollbarColor",
   "Color",
   "ColorOrAuto",
   "GradientItem",
   "VerticalAlign",
+  "BasicShape",
+  "ShapeRadius",
 ]
 item_types = ["enums", "structs", "typedefs", "functions"]
 renaming_overrides_prefixing = true
 
 # Prevent some renaming for Gecko types that cbindgen doesn't otherwise understand.
 [export.rename]
 "nscolor" = "nscolor"
 "nsAtom" = "nsAtom"
@@ -326,8 +329,45 @@ renaming_overrides_prefixing = true
 """
 
 "RGBA" = """
   static inline StyleRGBA Transparent();
   static inline StyleRGBA FromColor(nscolor);
 
   inline nscolor ToColor() const;
 """
+
+"OwnedSlice" = """
+  StyleOwnedSlice() :
+    ptr((T*)alignof(T)),
+    len(0) {}
+
+  // NOTE(emilio): Could be implemented with some effort, but for now no copy.
+  StyleOwnedSlice(const StyleOwnedSlice& aOther) = delete;
+
+  ~StyleOwnedSlice() {
+    if (!len) {
+      return;
+    }
+    for (size_t i : IntegerRange(len)) {
+      ptr[i].~T();
+    }
+    free(ptr);
+    ptr = (T*)alignof(T);
+    len = 0;
+  }
+
+  Span<const T> AsSpan() const {
+    return MakeSpan(ptr, len);
+  }
+
+  size_t Length() const {
+    return AsSpan().Length();
+  }
+
+  bool operator==(const StyleOwnedSlice& other) const {
+    return AsSpan() == other.AsSpan();
+  }
+
+  bool operator!=(const StyleOwnedSlice& other) const {
+    return !(*this == other);
+  }
+"""
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -6397,8 +6397,17 @@ pub unsafe extern "C" fn Servo_SharedMem
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_SharedMemoryBuilder_Drop(
     builder: *mut RawServoSharedMemoryBuilder
 ) {
     SharedMemoryBuilder::drop_ffi(builder)
 }
+
+/// Returns a unique pointer to a clone of the shape image.
+///
+/// Probably temporary, as we move more stuff to cbindgen.
+#[no_mangle]
+#[must_use]
+pub unsafe extern "C" fn Servo_CloneBasicShape(v: &computed::basic_shape::BasicShape) -> *mut computed::basic_shape::BasicShape {
+    Box::into_raw(Box::new(v.clone()))
+}
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-shapes/parsing/shape-outside-computed.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[shape-outside-computed.html]
-  [Property shape-outside value 'circle(calc(10px - 0.5em) at 50% -50%) border-box' computes to 'circle(0px at 50% -50%) border-box']
-    expected: FAIL
-
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-circle-005.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-circle-005.html.ini
@@ -1,15 +1,12 @@
 [shape-outside-circle-005.html]
   [test unit: cm - circle(50cm) - computed]
     expected: FAIL
 
-  [test unit: mm - circle(50mm) - computed]
-    expected: FAIL
-
   [test unit: ex - circle(50ex) - computed]
     expected:
       if os == "win": PASS
       if os == "mac": PASS
       if (os == "android") and not e10s: PASS
       if (os == "android") and e10s: PASS
       FAIL
 
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-circle-006.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-circle-006.html.ini
@@ -1,11 +1,9 @@
 [shape-outside-circle-006.html]
-  [circle(+20.340px) - computed]
-    expected: FAIL
 
   [circle(+10px) - inline]
     expected: FAIL
 
   [circle(+10.00px) - inline]
     expected: FAIL
 
   [circle(+20.340px) - inline]
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-ellipse-005.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-ellipse-005.html.ini
@@ -93,49 +93,25 @@
     expected: FAIL
 
   [test unit: cm - ellipse(25cm closest-side) - computed]
     expected: FAIL
 
   [test unit: cm - ellipse(closest-side 75cm) - computed]
     expected: FAIL
 
-  [test unit: cm - ellipse(25cm farthest-side) - computed]
-    expected: FAIL
-
   [test unit: cm - ellipse(farthest-side 75cm) - computed]
     expected: FAIL
 
   [test unit: mm - ellipse(50mm) - computed]
     expected: FAIL
 
-  [test unit: mm - ellipse(50mm 100mm) - computed]
-    expected: FAIL
-
-  [test unit: mm - ellipse(100mm 100px) - computed]
-    expected: FAIL
-
-  [test unit: mm - ellipse(50mm 25%) - computed]
-    expected: FAIL
-
-  [test unit: mm - ellipse(25% 50mm) - computed]
-    expected: FAIL
-
   [test unit: mm - ellipse(25mm closest-side) - computed]
     expected: FAIL
 
-  [test unit: mm - ellipse(closest-side 75mm) - computed]
-    expected: FAIL
-
-  [test unit: mm - ellipse(25mm farthest-side) - computed]
-    expected: FAIL
-
-  [test unit: mm - ellipse(farthest-side 75mm) - computed]
-    expected: FAIL
-
   [test unit: in - ellipse(50in) - computed]
     expected: FAIL
 
   [test unit: in - ellipse(25in closest-side) - computed]
     expected: FAIL
 
   [test unit: pt - ellipse(50pt) - computed]
     expected: FAIL
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-ellipse-006.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-ellipse-006.html.ini
@@ -1,12 +1,9 @@
 [shape-outside-ellipse-006.html]
-  [ellipse(+10.00px +20.230px) - computed]
-    expected: FAIL
-
   [ellipse(+30.00px 40.567px) - inline]
     expected: FAIL
 
   [ellipse(+10.00% +20.230%) - inline]
     expected: FAIL
 
   [ellipse(+10% +20%) - inline]
     expected: FAIL
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-001.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-001.html.ini
@@ -1,157 +1,49 @@
 [shape-outside-inset-001.html]
-  [One arg - cm - computed]
-    expected: FAIL
-
-  [Two args - cm cm - computed]
-    expected: FAIL
-
-  [Two args - cm % - computed]
-    expected: FAIL
-
-  [Two args - % cm - computed]
-    expected: FAIL
-
   [Three args - cm cm cm - computed]
     expected: FAIL
 
-  [Three args - cm cm % - computed]
-    expected: FAIL
-
   [Three args - cm % cm - computed]
     expected: FAIL
 
-  [Three args - cm % %  - computed]
-    expected: FAIL
-
   [Three args - % cm cm - computed]
     expected: FAIL
 
-  [Three args - % cm %  - computed]
-    expected: FAIL
-
   [Three args - % % cm  - computed]
     expected: FAIL
 
   [Four args - cm cm cm cm - computed]
     expected: FAIL
 
   [Four args - cm cm cm % - computed]
     expected: FAIL
 
   [Four args - cm cm % cm - computed]
     expected: FAIL
 
-  [Four args - cm cm % % - computed]
-    expected: FAIL
-
   [Four args - cm % cm cm - computed]
     expected: FAIL
 
   [Four args - cm % cm % - computed]
     expected: FAIL
 
   [Four args - cm % % cm - computed]
     expected: FAIL
 
-  [Four args - cm % % % - computed]
-    expected: FAIL
-
   [Four args - % cm cm cm - computed]
     expected: FAIL
 
   [Four args - % cm cm % - computed]
     expected: FAIL
 
   [Four args - % cm % cm - computed]
     expected: FAIL
 
-  [Four args - % cm % % - computed]
-    expected: FAIL
-
   [Four args - % % cm cm - computed]
     expected: FAIL
 
   [Four args - % % cm % - computed]
     expected: FAIL
 
   [Four args - % % % cm - computed]
     expected: FAIL
 
-  [One arg - mm - computed]
-    expected: FAIL
-
-  [Two args - mm mm - computed]
-    expected: FAIL
-
-  [Two args - mm % - computed]
-    expected: FAIL
-
-  [Two args - % mm - computed]
-    expected: FAIL
-
-  [Three args - mm mm mm - computed]
-    expected: FAIL
-
-  [Three args - mm mm % - computed]
-    expected: FAIL
-
-  [Three args - mm % mm - computed]
-    expected: FAIL
-
-  [Three args - mm % %  - computed]
-    expected: FAIL
-
-  [Three args - % mm mm - computed]
-    expected: FAIL
-
-  [Three args - % mm %  - computed]
-    expected: FAIL
-
-  [Three args - % % mm  - computed]
-    expected: FAIL
-
-  [Four args - mm mm mm mm - computed]
-    expected: FAIL
-
-  [Four args - mm mm mm % - computed]
-    expected: FAIL
-
-  [Four args - mm mm % mm - computed]
-    expected: FAIL
-
-  [Four args - mm mm % % - computed]
-    expected: FAIL
-
-  [Four args - mm % mm mm - computed]
-    expected: FAIL
-
-  [Four args - mm % mm % - computed]
-    expected: FAIL
-
-  [Four args - mm % % mm - computed]
-    expected: FAIL
-
-  [Four args - mm % % % - computed]
-    expected: FAIL
-
-  [Four args - % mm mm mm - computed]
-    expected: FAIL
-
-  [Four args - % mm mm % - computed]
-    expected: FAIL
-
-  [Four args - % mm % mm - computed]
-    expected: FAIL
-
-  [Four args - % mm % % - computed]
-    expected: FAIL
-
-  [Four args - % % mm mm - computed]
-    expected: FAIL
-
-  [Four args - % % mm % - computed]
-    expected: FAIL
-
-  [Four args - % % % mm - computed]
-    expected: FAIL
-
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-003.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-003.html.ini
@@ -1,33 +1,15 @@
 [shape-outside-inset-003.html]
-  [inset(10cm round 10cm) - computed]
-    expected: FAIL
-
-  [inset(10cm round 10cm / 10cm) - computed]
-    expected: FAIL
-
-  [inset(10cm round 10cm / 10cm 20cm) - computed]
-    expected: FAIL
-
   [inset(10cm round 10cm / 10cm 20cm 30cm) - computed]
     expected: FAIL
 
   [inset(10cm round 10cm / 10cm 20cm 30cm 40cm) - computed]
     expected: FAIL
 
-  [inset(10cm round 10cm 20cm) - computed]
-    expected: FAIL
-
-  [inset(10cm round 10cm 20cm / 10cm) - computed]
-    expected: FAIL
-
-  [inset(10cm round 10cm 20cm / 10cm 20cm) - computed]
-    expected: FAIL
-
   [inset(10cm round 10cm 20cm / 10cm 20cm 30cm) - computed]
     expected: FAIL
 
   [inset(10cm round 10cm 20cm / 10cm 20cm 30cm 40cm) - computed]
     expected: FAIL
 
   [inset(10cm round 10cm 20cm 30cm) - computed]
     expected: FAIL
@@ -54,76 +36,16 @@
     expected: FAIL
 
   [inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm 30cm) - computed]
     expected: FAIL
 
   [inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm 30cm 40cm) - computed]
     expected: FAIL
 
-  [inset(10mm round 10mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm / 10mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm / 10mm 20mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm / 10mm 20mm 30mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm / 10mm 20mm 30mm 40mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm / 10mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm / 10mm 20mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm / 10mm 20mm 30mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm / 10mm 20mm 30mm 40mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm / 10mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm / 10mm 20mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm / 10mm 20mm 30mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm / 10mm 20mm 30mm 40mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm 40mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm 40mm / 10mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm 30mm) - computed]
-    expected: FAIL
-
-  [inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm 30mm 40mm) - computed]
-    expected: FAIL
-
   [inset(10ex round 10ex) - computed]
     expected:
       if os == "win": PASS
       if os == "mac": PASS
       if (os == "android") and not e10s: PASS
       if (os == "android") and e10s: PASS
       FAIL
 
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-004.html.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[shape-outside-inset-004.html]
-  [inset(10.1200px 20.34px 30.56px 40.780px) - computed]
-    expected: FAIL
-
-  [inset(10.123px 20.00px 30.10px 40.5678px) - computed]
-    expected: FAIL
-
-  [inset(+10.1200px -20.340px +30.56px -40.780px) - computed]
-    expected: FAIL
-
-  [inset(-10.123px +20.00px -30.10px +40.5678px) - computed]
-    expected: FAIL
-
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-polygon-004.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-polygon-004.html.ini
@@ -18,43 +18,28 @@
   [Three vertices - ex ex, em, em, em em - computed]
     expected:
       if os == "win": PASS
       if os == "mac": PASS
       if (os == "android") and not e10s: PASS
       if (os == "android") and e10s: PASS
       FAIL
 
-  [One vertex - cm cm - computed]
-    expected: FAIL
-
-  [One vertex - cm mm - computed]
-    expected: FAIL
-
   [Two vertices - cm cm, cm cm - computed]
     expected: FAIL
 
-  [Two vertices - cm cm, mm mm - computed]
-    expected: FAIL
-
   [Two vertices - mm mm, cm cm - computed]
     expected: FAIL
 
   [Two vertices - cm mm, mm cm - computed]
     expected: FAIL
 
   [Three vertices - cm cm, cm cm, cm cm - computed]
     expected: FAIL
 
-  [Three vertices - mm mm, mm mm, mm mm - computed]
-    expected: FAIL
-
-  [Three vertices - cm cm, mm mm, pc pc - computed]
-    expected: FAIL
-
   [Three vertices - pc pc, cm, cm, mm mm - computed]
     expected: FAIL
 
   [Two vertices - vw vw, vh vh - computed]
     expected:
       if (os == "android") and not e10s: FAIL
       if (os == "android") and e10s: FAIL
 
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-polygon-005.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[shape-outside-polygon-005.html]
-  [polygon(1.0px 2.22px, 3.40px 4.555px, 5.607px 6.99px) - computed]
-    expected: FAIL
-
-  [polygon(+1.0px -2.22px, +3.40px -4.550px, 5.67px -6.99px) - computed]
-    expected: FAIL
-
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000.html.ini
+++ b/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000.html.ini
@@ -8,11 +8,8 @@
       FAIL
 
   [View relative units - computed]
     expected:
       if os == "mac": PASS
       if (os == "win") and (processor == "aarch64"): PASS
       FAIL
 
-  [Fixed units - computed]
-    expected: FAIL
-