Bug 1561738 - Stop using nsStyleSides for -moz-image-rect. r=boris
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 28 Jun 2019 09:46:17 +0000
changeset 480541 ad438d2a0a154498e428740aece0db242955e8cd
parent 480540 40121b4494a089598a1c16421ed5f85b33fb7e9d
child 480542 e0af0c6328746dd6eefa01c51c502ef583c99953
push id113555
push usercsabou@mozilla.com
push dateFri, 28 Jun 2019 16:23:03 +0000
treeherdermozilla-inbound@7e8d43bbeb96 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersboris
bugs1561738
milestone69.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 1561738 - Stop using nsStyleSides for -moz-image-rect. r=boris Differential Revision: https://phabricator.services.mozilla.com/D36119
layout/style/GeckoBindings.cpp
layout/style/ServoBindings.toml
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
servo/components/style/gecko/conversions.rs
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -1165,17 +1165,17 @@ void Gecko_CopyImageValueFrom(nsStyleIma
   MOZ_ASSERT(aImage);
   MOZ_ASSERT(aOther);
 
   *aImage = *aOther;
 }
 
 void Gecko_InitializeImageCropRect(nsStyleImage* aImage) {
   MOZ_ASSERT(aImage);
-  aImage->SetCropRect(MakeUnique<nsStyleSides>());
+  aImage->SetCropRect(MakeUnique<nsStyleImage::CropRect>());
 }
 
 void Gecko_SetCursorArrayLength(nsStyleUI* aStyleUI, size_t aLen) {
   aStyleUI->mCursorImages.Clear();
   aStyleUI->mCursorImages.SetLength(aLen);
 }
 
 void Gecko_SetCursorImageValue(nsCursorImage* aCursor,
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -513,16 +513,17 @@ cbindgen-types = [
     { gecko = "StyleLoadData", servo = "gecko::url::LoadData" },
     { gecko = "StyleGenericFilter", servo = "values::generics::effects::Filter" },
     { gecko = "StyleGenericGradient", servo = "values::generics::image::Gradient" },
     { gecko = "StyleLineDirection", servo = "values::computed::image::LineDirection" },
     { gecko = "StyleGridTemplateAreas", servo = "values::computed::position::GridTemplateAreas" },
     { gecko = "StyleGenericGridLine", servo = "values::generics::grid::GridLine" },
     { gecko = "StyleGenericTrackSize", servo = "values::generics::grid::TrackSize" },
     { gecko = "StyleGenericTrackBreadth", servo = "values::generics::grid::TrackBreadth" },
+    { gecko = "StyleNumberOrPercentage", servo = "values::computed::NumberOrPercentage" },
 ]
 
 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/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1901,19 +1901,19 @@ void nsStyleImage::DoCopy(const nsStyleI
   if (aOther.mType == eStyleImageType_Image) {
     SetImageRequest(do_AddRef(aOther.mImage));
   } else if (aOther.mType == eStyleImageType_Gradient) {
     SetGradientData(MakeUnique<StyleGradient>(*aOther.mGradient));
   } else if (aOther.mType == eStyleImageType_Element) {
     SetElementId(do_AddRef(aOther.mElementId));
   }
 
-  UniquePtr<nsStyleSides> cropRectCopy;
+  UniquePtr<CropRect> cropRectCopy;
   if (aOther.mCropRect) {
-    cropRectCopy = MakeUnique<nsStyleSides>(*aOther.mCropRect.get());
+    cropRectCopy = MakeUnique<CropRect>(*aOther.mCropRect.get());
   }
   SetCropRect(std::move(cropRectCopy));
 }
 
 void nsStyleImage::SetNull() {
   if (mType == eStyleImageType_Gradient) {
     delete mGradient;
     mGradient = nullptr;
@@ -1961,33 +1961,28 @@ void nsStyleImage::SetElementId(already_
   }
 
   if (RefPtr<nsAtom> atom = aElementId) {
     mElementId = atom.forget().take();
     mType = eStyleImageType_Element;
   }
 }
 
-void nsStyleImage::SetCropRect(UniquePtr<nsStyleSides> aCropRect) {
+void nsStyleImage::SetCropRect(UniquePtr<CropRect> aCropRect) {
   mCropRect = std::move(aCropRect);
 }
 
-static int32_t ConvertToPixelCoord(const nsStyleCoord& aCoord,
+static int32_t ConvertToPixelCoord(const StyleNumberOrPercentage& aCoord,
                                    int32_t aPercentScale) {
   double pixelValue;
-  switch (aCoord.GetUnit()) {
-    case eStyleUnit_Percent:
-      pixelValue = aCoord.GetPercentValue() * aPercentScale;
-      break;
-    case eStyleUnit_Factor:
-      pixelValue = aCoord.GetFactorValue();
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected unit for image crop rect");
-      return 0;
+  if (aCoord.IsNumber()) {
+    pixelValue = aCoord.AsNumber();
+  } else {
+    MOZ_ASSERT(aCoord.IsPercentage());
+    pixelValue = aCoord.AsPercentage()._0 * aPercentScale;
   }
   MOZ_ASSERT(pixelValue >= 0, "we ensured non-negative while parsing");
   pixelValue = std::min(pixelValue, double(INT32_MAX));  // avoid overflow
   return NS_lround(pixelValue);
 }
 
 already_AddRefed<nsIURI> nsStyleImageRequest::GetImageURI() const {
   nsCOMPtr<nsIURI> uri;
@@ -2024,21 +2019,23 @@ bool nsStyleImage::ComputeActualCropRect
 
   nsIntSize imageSize;
   imageContainer->GetWidth(&imageSize.width);
   imageContainer->GetHeight(&imageSize.height);
   if (imageSize.width <= 0 || imageSize.height <= 0) {
     return false;
   }
 
-  int32_t left = ConvertToPixelCoord(mCropRect->GetLeft(), imageSize.width);
-  int32_t top = ConvertToPixelCoord(mCropRect->GetTop(), imageSize.height);
-  int32_t right = ConvertToPixelCoord(mCropRect->GetRight(), imageSize.width);
+  int32_t left =
+      ConvertToPixelCoord(mCropRect->Get(eSideLeft), imageSize.width);
+  int32_t top = ConvertToPixelCoord(mCropRect->Get(eSideTop), imageSize.height);
+  int32_t right =
+      ConvertToPixelCoord(mCropRect->Get(eSideRight), imageSize.width);
   int32_t bottom =
-      ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
+      ConvertToPixelCoord(mCropRect->Get(eSideBottom), imageSize.height);
 
   // IntersectRect() returns an empty rect if we get negative width or height
   nsIntRect cropRect(left, top, right - left, bottom - top);
   nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
   aActualCropRect.IntersectRect(imageRect, cropRect);
 
   if (aIsEntireImage) {
     *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
@@ -2138,28 +2135,28 @@ bool nsStyleImage::IsLoaded() const {
              (status & imgIRequest::STATUS_LOAD_COMPLETE);
     }
     default:
       MOZ_ASSERT_UNREACHABLE("unexpected image type");
       return false;
   }
 }
 
-static inline bool EqualRects(const UniquePtr<nsStyleSides>& aRect1,
-                              const UniquePtr<nsStyleSides>& aRect2) {
+static inline bool EqualRects(const nsStyleImage::CropRect* aRect1,
+                              const nsStyleImage::CropRect* aRect2) {
   return aRect1 == aRect2 || /* handles null== null, and optimize */
          (aRect1 && aRect2 && *aRect1 == *aRect2);
 }
 
 bool nsStyleImage::operator==(const nsStyleImage& aOther) const {
   if (mType != aOther.mType) {
     return false;
   }
 
-  if (!EqualRects(mCropRect, aOther.mCropRect)) {
+  if (!EqualRects(mCropRect.get(), aOther.mCropRect.get())) {
     return false;
   }
 
   if (mType == eStyleImageType_Image) {
     return DefinitelyEqualImages(mImage, aOther.mImage);
   }
 
   if (mType == eStyleImageType_Gradient) {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -252,26 +252,28 @@ struct CachedBorderImageData {
  * (2) A CSS linear or radial gradient.
  * (3) An element within a document, or an <img>, <video>, or <canvas> element
  *     not in a document.
  * (*) Optionally a crop rect can be set to paint a partial (rectangular)
  * region of an image. (Currently, this feature is only supported with an
  * image of type (1)).
  */
 struct nsStyleImage {
+  using CropRect = mozilla::StyleRect<mozilla::StyleNumberOrPercentage>;
+
   nsStyleImage();
   ~nsStyleImage();
   nsStyleImage(const nsStyleImage& aOther);
   nsStyleImage& operator=(const nsStyleImage& aOther);
 
   void SetNull();
   void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
   void SetGradientData(mozilla::UniquePtr<mozilla::StyleGradient>);
   void SetElementId(already_AddRefed<nsAtom> aElementId);
-  void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
+  void SetCropRect(mozilla::UniquePtr<CropRect> aCropRect);
 
   void ResolveImage(mozilla::dom::Document& aDocument,
                     const nsStyleImage* aOldImage) {
     MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
     if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
       const nsStyleImageRequest* oldRequest =
           (aOldImage && aOldImage->GetType() == eStyleImageType_Image)
               ? aOldImage->ImageRequest()
@@ -293,20 +295,20 @@ struct nsStyleImage {
   }
   bool IsResolved() const {
     return mType != eStyleImageType_Image || ImageRequest()->IsResolved();
   }
   const nsAtom* GetElementId() const {
     NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
     return mElementId;
   }
-  const mozilla::UniquePtr<nsStyleSides>& GetCropRect() const {
+  const CropRect* GetCropRect() const {
     NS_ASSERTION(mType == eStyleImageType_Image,
                  "Only image data can have a crop rect");
-    return mCropRect;
+    return mCropRect.get();
   }
 
   already_AddRefed<nsIURI> GetImageURI() const;
 
   const mozilla::StyleComputedImageUrl* GetURLValue() const;
 
   /**
    * Compute the actual crop rect in pixels, using the source image bounds.
@@ -389,17 +391,17 @@ struct nsStyleImage {
   nsStyleImageType mType;
   union {
     nsStyleImageRequest* mImage;
     mozilla::StyleGradient* mGradient;
     nsAtom* mElementId;
   };
 
   // This is _currently_ used only in conjunction with eStyleImageType_Image.
-  mozilla::UniquePtr<nsStyleSides> mCropRect;
+  mozilla::UniquePtr<CropRect> mCropRect;
 };
 
 struct nsStyleImageLayers {
   // Indices into kBackgroundLayerTable and kMaskLayerTable
   enum {
     shorthand = 0,
     color,
     image,
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -64,28 +64,17 @@ impl nsStyleImage {
             },
             GenericImage::Rect(ref image_rect) => {
                 unsafe {
                     bindings::Gecko_SetLayerImageImageValue(self, &image_rect.url);
                     bindings::Gecko_InitializeImageCropRect(self);
 
                     // Set CropRect
                     let ref mut rect = *self.mCropRect.mPtr;
-                    image_rect
-                        .top
-                        .to_gecko_style_coord(&mut rect.data_at_mut(0));
-                    image_rect
-                        .right
-                        .to_gecko_style_coord(&mut rect.data_at_mut(1));
-                    image_rect
-                        .bottom
-                        .to_gecko_style_coord(&mut rect.data_at_mut(2));
-                    image_rect
-                        .left
-                        .to_gecko_style_coord(&mut rect.data_at_mut(3));
+                    *rect = Rect(image_rect.top, image_rect.right, image_rect.bottom, image_rect.left);
                 }
             },
             GenericImage::Element(ref element) => unsafe {
                 bindings::Gecko_SetImageElement(self, element.as_ptr());
             },
         }
     }
 
@@ -93,49 +82,33 @@ impl nsStyleImage {
         unsafe {
             bindings::Gecko_SetGradientImageValue(self, Box::into_raw(gradient));
         }
     }
 
     /// Converts into Image.
     pub unsafe fn into_image(self: &nsStyleImage) -> Option<Image> {
         use crate::gecko_bindings::structs::nsStyleImageType;
-        use crate::values::computed::{MozImageRect, NumberOrPercentage};
+        use crate::values::computed::MozImageRect;
 
         match self.mType {
             nsStyleImageType::eStyleImageType_Null => None,
             nsStyleImageType::eStyleImageType_Image => {
                 let url = self.get_image_url();
                 if self.mCropRect.mPtr.is_null() {
                     Some(GenericImage::Url(url))
                 } else {
-                    let ref rect = *self.mCropRect.mPtr;
-                    match (
-                        NumberOrPercentage::from_gecko_style_coord(&rect.data_at(0)),
-                        NumberOrPercentage::from_gecko_style_coord(&rect.data_at(1)),
-                        NumberOrPercentage::from_gecko_style_coord(&rect.data_at(2)),
-                        NumberOrPercentage::from_gecko_style_coord(&rect.data_at(3)),
-                    ) {
-                        (Some(top), Some(right), Some(bottom), Some(left)) => {
-                            Some(GenericImage::Rect(Box::new(MozImageRect {
-                                url,
-                                top,
-                                right,
-                                bottom,
-                                left,
-                            })))
-                        },
-                        _ => {
-                            debug_assert!(
-                                false,
-                                "mCropRect could not convert to NumberOrPercentage"
-                            );
-                            None
-                        },
-                    }
+                    let rect = &*self.mCropRect.mPtr;
+                    Some(GenericImage::Rect(Box::new(MozImageRect {
+                        url,
+                        top: rect.0,
+                        right: rect.1,
+                        bottom: rect.2,
+                        left: rect.3,
+                    })))
                 }
             },
             nsStyleImageType::eStyleImageType_Gradient => {
                 let gradient: &Gradient = &**self.__bindgen_anon_1.mGradient.as_ref();
                 Some(GenericImage::Gradient(Box::new(gradient.clone())))
             },
             nsStyleImageType::eStyleImageType_Element => {
                 use crate::gecko_string_cache::Atom;