Bug 1284837 - Disallow implicit conversions from float to integer when creating. r=botond
authorNicolas Silva <nsilva@mozilla.com>
Fri, 16 Sep 2016 17:49:39 +0200
changeset 355584 e59f96abc40be4726e79c0409edd173a9d2b17a0
parent 355583 a8b9b1f7675ffbf450858dac44146dd8608024f6
child 355585 eed652d8223d291bd38ed8f6193a21d338ecc4be
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1284837
milestone51.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 1284837 - Disallow implicit conversions from float to integer when creating. r=botond
dom/html/HTMLCanvasElement.cpp
dom/plugins/ipc/PluginUtilsOSX.mm
gfx/2d/BaseRect.h
gfx/2d/Rect.h
gfx/layers/Layers.cpp
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicPaintedLayer.cpp
gfx/layers/client/TiledContentClient.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/thebes/gfxContext.cpp
gfx/thebes/gfxDrawable.cpp
image/OrientedImage.cpp
layout/xul/PopupBoxObject.cpp
widget/gtk/nsWindow.cpp
widget/windows/nsWindow.cpp
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -977,24 +977,17 @@ HTMLCanvasElement::InvalidateCanvasConte
     return;
 
   ActiveLayerTracker::NotifyContentChange(frame);
 
   Layer* layer = nullptr;
   if (damageRect) {
     nsIntSize size = GetWidthHeight();
     if (size.width != 0 && size.height != 0) {
-
-      gfx::Rect realRect(*damageRect);
-      realRect.RoundOut();
-
-      // then make it a nsIntRect
-      nsIntRect invalRect(realRect.X(), realRect.Y(),
-                          realRect.Width(), realRect.Height());
-
+      gfx::IntRect invalRect = gfx::IntRect::Truncate(*damageRect);
       layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS, &invalRect);
     }
   } else {
     layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS);
   }
   if (layer) {
     static_cast<CanvasLayer*>(layer)->Updated();
   }
--- a/dom/plugins/ipc/PluginUtilsOSX.mm
+++ b/dom/plugins/ipc/PluginUtilsOSX.mm
@@ -63,17 +63,17 @@ CGBitmapContextSetDataFunc CGBitmapConte
 }
 
 - (void)drawInContext:(CGContextRef)aCGContext
 {
   ::CGContextSaveGState(aCGContext); 
   ::CGContextTranslateCTM(aCGContext, 0, self.bounds.size.height);
   ::CGContextScaleCTM(aCGContext, (CGFloat) 1, (CGFloat) -1);
 
-  mUpdateRect = nsIntRect(0, 0, self.bounds.size.width, self.bounds.size.height);
+  mUpdateRect = nsIntRect::Truncate(0, 0, self.bounds.size.width, self.bounds.size.height);
 
   mDrawFunc(aCGContext, mPluginInstance, mUpdateRect);
 
   ::CGContextRestoreGState(aCGContext);
 
   mUpdateRect.SetEmpty();
 }
 
--- a/gfx/2d/BaseRect.h
+++ b/gfx/2d/BaseRect.h
@@ -555,20 +555,20 @@ struct BaseRect {
   // signed integers, centered around a point at 0,0.  As BaseRect's represent
   // the dimensions as a top-left point with a width and height, the width
   // and height will be the largest positive 32-bit value.  The top-left
   // position coordinate is divided by two to center the rectangle around a
   // point at 0,0.
   static Sub MaxIntRect()
   {
     return Sub(
-      -std::numeric_limits<int32_t>::max() * 0.5,
-      -std::numeric_limits<int32_t>::max() * 0.5,
-      std::numeric_limits<int32_t>::max(),
-      std::numeric_limits<int32_t>::max()
+      static_cast<T>(-std::numeric_limits<int32_t>::max() * 0.5),
+      static_cast<T>(-std::numeric_limits<int32_t>::max() * 0.5),
+      static_cast<T>(std::numeric_limits<int32_t>::max()),
+      static_cast<T>(std::numeric_limits<int32_t>::max())
     );
   };
 
   friend std::ostream& operator<<(std::ostream& stream,
       const BaseRect<T, Sub, Point, SizeT, MarginT>& aRect) {
     return stream << '(' << aRect.x << ',' << aRect.y << ','
                   << aRect.width << ',' << aRect.height << ')';
   }
--- a/gfx/2d/Rect.h
+++ b/gfx/2d/Rect.h
@@ -16,16 +16,18 @@
 #include <cmath>
 
 namespace mozilla {
 
 template <typename> struct IsPixel;
 
 namespace gfx {
 
+template<class units, class F> struct RectTyped;
+
 template<class units>
 struct IntMarginTyped:
     public BaseMargin<int32_t, IntMarginTyped<units> >,
     public units {
     static_assert(IsPixel<units>::value,
                   "'units' must be a coordinate system tag");
 
     typedef BaseMargin<int32_t, IntMarginTyped<units> > Super;
@@ -81,22 +83,66 @@ template<class units>
 struct IntRectTyped :
     public BaseRect<int32_t, IntRectTyped<units>, IntPointTyped<units>, IntSizeTyped<units>, IntMarginTyped<units> >,
     public units {
     static_assert(IsPixel<units>::value,
                   "'units' must be a coordinate system tag");
 
     typedef BaseRect<int32_t, IntRectTyped<units>, IntPointTyped<units>, IntSizeTyped<units>, IntMarginTyped<units> > Super;
     typedef IntRectTyped<units> Self;
+    typedef IntParam<int32_t> ToInt;
 
     IntRectTyped() : Super() {}
     IntRectTyped(const IntPointTyped<units>& aPos, const IntSizeTyped<units>& aSize) :
         Super(aPos, aSize) {}
-    IntRectTyped(int32_t _x, int32_t _y, int32_t _width, int32_t _height) :
-        Super(_x, _y, _width, _height) {}
+
+    IntRectTyped(ToInt aX, ToInt aY, ToInt aWidth, ToInt aHeight) :
+        Super(aX.value, aY.value, aWidth.value, aHeight.value) {}
+
+    static IntRectTyped<units> RoundIn(float aX, float aY, float aW, float aH) {
+      return IntRectTyped<units>::RoundIn(RectTyped<units, float>(aX, aY, aW, aH));
+    }
+
+    static IntRectTyped<units> RoundOut(float aX, float aY, float aW, float aH) {
+      return IntRectTyped<units>::RoundOut(RectTyped<units, float>(aX, aY, aW, aH));
+    }
+
+    static IntRectTyped<units> Round(float aX, float aY, float aW, float aH) {
+      return IntRectTyped<units>::Round(RectTyped<units, float>(aX, aY, aW, aH));
+    }
+
+    static IntRectTyped<units> Truncate(float aX, float aY, float aW, float aH) {
+      return IntRectTyped<units>(IntPointTyped<units>::Truncate(aX, aY),
+                                 IntSizeTyped<units>::Truncate(aW, aH));
+    }
+
+    static IntRectTyped<units> RoundIn(const RectTyped<units, float>& aRect) {
+      auto tmp(aRect);
+      tmp.RoundIn();
+      return IntRectTyped(int32_t(tmp.x), int32_t(tmp.y),
+                          int32_t(tmp.width), int32_t(tmp.height));
+    }
+
+    static IntRectTyped<units> RoundOut(const RectTyped<units, float>& aRect) {
+      auto tmp(aRect);
+      tmp.RoundOut();
+      return IntRectTyped(int32_t(tmp.x), int32_t(tmp.y),
+                          int32_t(tmp.width), int32_t(tmp.height));
+    }
+
+    static IntRectTyped<units> Round(const RectTyped<units, float>& aRect) {
+      auto tmp(aRect);
+      tmp.Round();
+      return IntRectTyped(int32_t(tmp.x), int32_t(tmp.y),
+                          int32_t(tmp.width), int32_t(tmp.height));
+    }
+
+    static IntRectTyped<units> Truncate(const RectTyped<units, float>& aRect) {
+      return IntRectTyped::Truncate(aRect.x, aRect.y, aRect.width, aRect.height);
+    }
 
     // Rounding isn't meaningful on an integer rectangle.
     void Round() {}
     void RoundIn() {}
     void RoundOut() {}
 
     // XXX When all of the code is ported, the following functions to convert
     // to and from unknown types should be removed.
@@ -243,41 +289,28 @@ IntRectTyped<units> RoundedToInt(const R
                              int32_t(copy.y),
                              int32_t(copy.width),
                              int32_t(copy.height));
 }
 
 template<class units>
 IntRectTyped<units> RoundedIn(const RectTyped<units>& aRect)
 {
-  RectTyped<units> copy(aRect);
-  copy.RoundIn();
-  return IntRectTyped<units>(int32_t(copy.x),
-                             int32_t(copy.y),
-                             int32_t(copy.width),
-                             int32_t(copy.height));
+  return IntRectTyped<units>::RoundIn(aRect);
 }
 
 template<class units>
 IntRectTyped<units> RoundedOut(const RectTyped<units>& aRect)
 {
-  RectTyped<units> copy(aRect);
-  copy.RoundOut();
-  return IntRectTyped<units>(int32_t(copy.x),
-                             int32_t(copy.y),
-                             int32_t(copy.width),
-                             int32_t(copy.height));
+  return IntRectTyped<units>::RoundOut(aRect);
 }
 
 template<class units>
 IntRectTyped<units> TruncatedToInt(const RectTyped<units>& aRect) {
-  return IntRectTyped<units>(int32_t(aRect.x),
-                             int32_t(aRect.y),
-                             int32_t(aRect.width),
-                             int32_t(aRect.height));
+  return IntRectTyped<units>::Truncate(aRect);
 }
 
 template<class units>
 RectTyped<units> IntRectToRect(const IntRectTyped<units>& aRect)
 {
   return RectTyped<units>(aRect.x, aRect.y, aRect.width, aRect.height);
 }
 
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2541,15 +2541,13 @@ SetAntialiasingFlags(Layer* aLayer, Draw
   permitSubpixelAA &= !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
                       aTarget->GetOpaqueRect().Contains(intTransformedBounds);
   aTarget->SetPermitSubpixelAA(permitSubpixelAA);
 }
 
 IntRect
 ToOutsideIntRect(const gfxRect &aRect)
 {
-  gfxRect r = aRect;
-  r.RoundOut();
-  return IntRect(r.X(), r.Y(), r.Width(), r.Height());
+  return IntRect::RoundOut(aRect.x, aRect.y, aRect.width, aRect.height);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -204,19 +204,17 @@ BasicLayerManager::PopGroupForLayer(Push
   }
 
   group.mFinalTarget->Restore();
 }
 
 static IntRect
 ToInsideIntRect(const gfxRect& aRect)
 {
-  gfxRect r = aRect;
-  r.RoundIn();
-  return IntRect(r.X(), r.Y(), r.Width(), r.Height());
+  return IntRect::RoundIn(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
 }
 
 // A context helper for BasicLayerManager::PaintLayer() that holds all the
 // painting context together in a data structure so it can be easily passed
 // around. It also uses ensures that the Transform and Opaque rect are restored
 // to their former state on destruction.
 
 class PaintLayerContext {
--- a/gfx/layers/basic/BasicPaintedLayer.cpp
+++ b/gfx/layers/basic/BasicPaintedLayer.cpp
@@ -31,20 +31,19 @@ namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 static nsIntRegion
 IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
 {
   gfxRect clip = aContext->GetClipExtents();
-  clip.RoundOut();
-  IntRect r(clip.X(), clip.Y(), clip.Width(), clip.Height());
   nsIntRegion result;
-  result.And(aRegion, r);
+  result.And(aRegion, IntRect::RoundOut(clip.X(), clip.Y(),
+                                        clip.Width(), clip.Height()));
   return result;
 }
 
 void
 BasicPaintedLayer::PaintThebes(gfxContext* aContext,
                               Layer* aMaskLayer,
                               LayerManager::DrawPaintedLayerCallback aCallback,
                               void* aCallbackData)
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -1108,19 +1108,17 @@ ClientMultiTiledLayerBuffer::ValidateTil
     const IntRect& dirtyRect = iter.Get();
     gfx::Rect drawRect(dirtyRect.x - aTileOrigin.x,
                        dirtyRect.y - aTileOrigin.y,
                        dirtyRect.width,
                        dirtyRect.height);
     drawRect.Scale(mResolution);
 
     // Mark the newly updated area as invalid in the front buffer
-    aTile.mInvalidFront.Or(aTile.mInvalidFront,
-      IntRect(NS_lroundf(drawRect.x), NS_lroundf(drawRect.y),
-                drawRect.width, drawRect.height));
+    aTile.mInvalidFront.Or(aTile.mInvalidFront, IntRect::RoundOut(drawRect));
 
     if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
       dt->FillRect(drawRect, ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
       dtOnWhite->FillRect(drawRect, ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
     } else if (content == gfxContentType::COLOR_ALPHA) {
       dt->ClearRect(drawRect);
     }
   }
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -1190,29 +1190,29 @@ LayerManagerComposite::RenderToPresentat
   Matrix4x4 matrix = Matrix4x4::From2D(viewMatrix);
 
   mRoot->ComputeEffectiveTransforms(matrix);
   nsIntRegion opaque;
   LayerIntRegion visible;
   PostProcessLayers(mRoot, opaque, visible, Nothing());
 
   nsIntRegion invalid;
-  IntRect bounds(0, 0, scale * pageWidth, actualHeight);
+  IntRect bounds = IntRect::Truncate(0, 0, scale * pageWidth, actualHeight);
   IntRect rect, actualBounds;
   MOZ_ASSERT(mRoot->GetOpacity() == 1);
   mCompositor->BeginFrame(invalid, nullptr, bounds, nsIntRegion(), &rect, &actualBounds);
 
   // The Java side of Fennec sets a scissor rect that accounts for
   // chrome such as the URL bar. Override that so that the entire frame buffer
   // is cleared.
   ScopedScissorRect scissorRect(egl, 0, 0, actualWidth, actualHeight);
   egl->fClearColor(0.0, 0.0, 0.0, 0.0);
   egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
 
-  const IntRect clipRect = IntRect(0, 0, actualWidth, actualHeight);
+  const IntRect clipRect = IntRect::Truncate(0, 0, actualWidth, actualHeight);
 
   RootLayer()->Prepare(RenderTargetIntRect::FromUnknownRect(clipRect));
   RootLayer()->RenderLayer(clipRect);
 
   mCompositor->EndFrame();
 #ifdef MOZ_WIDGET_GONK
   mCompositor->SetDispAcquireFence(mRoot); // Call after EndFrame()
 
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -808,17 +808,17 @@ GetRoundOutDeviceClipExtents(gfxContext*
 }
 
 void
 gfxContext::PushGroupAndCopyBackground(gfxContentType content, Float aOpacity, SourceSurface* aMask, const Matrix& aMaskTransform)
 {
   IntRect clipExtents;
   if (mDT->GetFormat() != SurfaceFormat::B8G8R8X8) {
     gfxRect clipRect = GetRoundOutDeviceClipExtents(this);
-    clipExtents = IntRect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
+    clipExtents = IntRect::Truncate(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
   }
   bool pushOpaqueWithCopiedBG = (mDT->GetFormat() == SurfaceFormat::B8G8R8X8 ||
                                  mDT->GetOpaqueRect().Contains(clipExtents)) &&
                                 !mDT->GetUserData(&sDontUseAsSourceKey);
 
   if (gfxPrefs::UseNativePushLayer()) {
     Save();
 
--- a/gfx/thebes/gfxDrawable.cpp
+++ b/gfx/thebes/gfxDrawable.cpp
@@ -40,22 +40,21 @@ gfxSurfaceDrawable::DrawWithSamplingRect
                                          gfxFloat aOpacity)
 {
   if (!mSourceSurface) {
     return true;
   }
 
   // When drawing with CLAMP we can expand the sampling rect to the nearest pixel
   // without changing the result.
-  gfxRect samplingRect = aSamplingRect;
-  samplingRect.RoundOut();
-  IntRect intRect(samplingRect.x, samplingRect.y, samplingRect.width, samplingRect.height);
+  IntRect intRect = IntRect::RoundOut(aSamplingRect.x, aSamplingRect.y,
+                                      aSamplingRect.width, aSamplingRect.height);
 
   IntSize size = mSourceSurface->GetSize();
-  if (!IntRect(0, 0, size.width, size.height).Contains(intRect)) {
+  if (!IntRect(IntPoint(), size).Contains(intRect)) {
     return false;
   }
 
   DrawInternal(aDrawTarget, aOp, aAntialiasMode, aFillRect, intRect,
                ExtendMode::CLAMP, aSamplingFilter, aOpacity, gfxMatrix());
   return true;
 }
 
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -340,16 +340,15 @@ OrientedImage::GetImageSpaceInvalidation
     // Fall back to identity if the width and height aren't available.
     return rect;
   }
 
   // Transform the invalidation rect into the correct orientation.
   gfxMatrix matrix(OrientationMatrix(innerSize));
   gfxRect invalidRect(matrix.TransformBounds(gfxRect(rect.x, rect.y,
                                                      rect.width, rect.height)));
-  invalidRect.RoundOut();
 
-  return nsIntRect(invalidRect.x, invalidRect.y,
-                   invalidRect.width, invalidRect.height);
+  return IntRect::RoundOut(invalidRect.x, invalidRect.y,
+                           invalidRect.width, invalidRect.height);
 }
 
 } // namespace image
 } // namespace mozilla
--- a/layout/xul/PopupBoxObject.cpp
+++ b/layout/xul/PopupBoxObject.cpp
@@ -360,17 +360,17 @@ PopupBoxObject::AlignmentOffset()
 }
 
 void
 PopupBoxObject::SetConstraintRect(dom::DOMRectReadOnly& aRect)
 {
   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (menuPopupFrame) {
     menuPopupFrame->SetOverrideConstraintRect(
-      LayoutDeviceIntRect(aRect.Left(), aRect.Top(), aRect.Width(), aRect.Height()));
+      LayoutDeviceIntRect::Truncate(aRect.Left(), aRect.Top(), aRect.Width(), aRect.Height()));
   }
 }
 
 } // namespace dom
 } // namespace mozilla
 
 // Creation Routine ///////////////////////////////////////////////////////////////////////
 
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -2080,17 +2080,17 @@ ExtractExposeRegion(LayoutDeviceIntRegio
   cairo_rectangle_list_t* rects = cairo_copy_clip_rectangle_list(cr);
   if (rects->status != CAIRO_STATUS_SUCCESS) {
       NS_WARNING("Failed to obtain cairo rectangle list.");
       return false;
   }
 
   for (int i = 0; i < rects->num_rectangles; i++)  {
       const cairo_rectangle_t& r = rects->rectangles[i];
-      aRegion.Or(aRegion, LayoutDeviceIntRect(r.x, r.y, r.width, r.height));
+      aRegion.Or(aRegion, LayoutDeviceIntRect::Truncate(r.x, r.y, r.width, r.height));
       LOGDRAW(("\t%d %d %d %d\n", r.x, r.y, r.width, r.height));
   }
 
   cairo_rectangle_list_destroy(rects);
   return true;
 }
 #endif
 
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3768,26 +3768,26 @@ nsWindow::UpdateThemeGeometries(const ns
   }
 
   // On Win10, force show the top border:
   if (IsWin10OrLater() && mCustomNonClient && mSizeMode == nsSizeMode_Normal) {
     RECT rect;
     ::GetWindowRect(mWnd, &rect);
     // We want 1 pixel of border for every whole 100% of scaling
     double borderSize = std::min(1, RoundDown(GetDesktopToDeviceScale().scale));
-    clearRegion.Or(clearRegion, nsIntRect(0, 0, rect.right - rect.left, borderSize));
+    clearRegion.Or(clearRegion, gfx::IntRect::Truncate(0, 0, rect.right - rect.left, borderSize));
   }
 
   if (!IsWin10OrLater()) {
     for (size_t i = 0; i < aThemeGeometries.Length(); i++) {
       if (aThemeGeometries[i].mType == nsNativeThemeWin::eThemeGeometryTypeWindowButtons) {
         LayoutDeviceIntRect bounds = aThemeGeometries[i].mRect;
-        clearRegion.Or(clearRegion, nsIntRect(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height() - 2.0));
-        clearRegion.Or(clearRegion, nsIntRect(bounds.X() + 1.0, bounds.YMost() - 2.0, bounds.Width() - 1.0, 1.0));
-        clearRegion.Or(clearRegion, nsIntRect(bounds.X() + 2.0, bounds.YMost() - 1.0, bounds.Width() - 3.0, 1.0));
+        clearRegion.Or(clearRegion, gfx::IntRect::Truncate(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height() - 2.0));
+        clearRegion.Or(clearRegion, gfx::IntRect::Truncate(bounds.X() + 1.0, bounds.YMost() - 2.0, bounds.Width() - 1.0, 1.0));
+        clearRegion.Or(clearRegion, gfx::IntRect::Truncate(bounds.X() + 2.0, bounds.YMost() - 1.0, bounds.Width() - 3.0, 1.0));
       }
     }
   }
 
   layerManager->SetRegionToClear(clearRegion);
 }
 
 uint32_t