Bug 1129147 - Part 2. Path option to addHitRegion. r=ehsan r=gw280
authorMilan Sreckovic <milan@mozilla.com>
Mon, 02 Mar 2015 15:33:28 -0500
changeset 264325 6f2b97191ec1018f352993b9592bc182a6294872
parent 264324 e27def3ae3a370f04b05098461e6138c66db1f65
child 264326 5cb314c34f241988e334b7a26b0237c77b4afcca
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, gw280
bugs1129147
milestone39.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 1129147 - Part 2. Path option to addHitRegion. r=ehsan r=gw280
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/test/test_hitregion_event.html
dom/webidl/CanvasRenderingContext2D.webidl
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3158,25 +3158,34 @@ CanvasRenderingContext2D::MeasureText(co
   }
 
   return new TextMetrics(width);
 }
 
 void
 CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorResult& error)
 {
-  // check if the path is valid
-  EnsureUserSpacePath(CanvasWindingRule::Nonzero);
-  if(!mPath) {
+  RefPtr<gfx::Path> path;
+  if (options.mPath) {
+    path = options.mPath->GetPath(CanvasWindingRule::Nonzero, mTarget);
+  }
+
+  if (!path) {
+    // check if the path is valid
+    EnsureUserSpacePath(CanvasWindingRule::Nonzero);
+    path = mPath;
+  }
+
+  if(!path) {
     error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return;
   }
 
   // get the bounds of the current path. They are relative to the canvas
-  mgfx::Rect bounds(mPath->GetBounds(mTarget->GetTransform()));
+  mgfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
   if ((bounds.width == 0) || (bounds.height == 0) || !bounds.IsFinite()) {
     // The specified region has no pixels.
     error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return;
   }
 
   // remove old hit region first
   RemoveHitRegion(options.mId);
@@ -3195,17 +3204,17 @@ CanvasRenderingContext2D::AddHitRegion(c
                                 nsINode::DeleteProperty<bool>);
 #endif
   }
 
   // finally, add the region to the list
   RegionInfo info;
   info.mId = options.mId;
   info.mElement = options.mControl;
-  RefPtr<PathBuilder> pathBuilder = mPath->TransformedCopyToBuilder(mTarget->GetTransform());
+  RefPtr<PathBuilder> pathBuilder = path->TransformedCopyToBuilder(mTarget->GetTransform());
   info.mPath = pathBuilder->Finish();
 
   mHitRegionsOptions.InsertElementAt(0, info);
 }
 
 void
 CanvasRenderingContext2D::RemoveHitRegion(const nsAString& id)
 {
--- a/dom/canvas/test/test_hitregion_event.html
+++ b/dom/canvas/test/test_hitregion_event.html
@@ -27,39 +27,55 @@ SpecialPowers.pushPrefEnv({"set": [["can
   function runTests()
   {
     try {
       var ctx = input.getContext("2d");
       ctx.beginPath();
       ctx.rect(20, 20, 100, 75);
       ctx.fill();
       ctx.addHitRegion({id: "a"});
+
       ctx.beginPath();
       ctx.fillStyle = "red";
       ctx.rect(60, 40, 100, 75);
       ctx.fill();
       ctx.addHitRegion({id: "b"});
+
+      var mypath = new Path2D();
+      mypath.rect(80, 60, 10, 10);
+
       ctx.beginPath();
       ctx.fillStyle = "yellow";
       ctx.rect(80, 60, 10, 10);
       ctx.fill();
-      ctx.addHitRegion({id: "c"});
+      ctx.addHitRegion({id: "c", path: mypath});
+
+      ctx.beginPath();
+      ctx.fillStyle = "green";
+      ctx.rect(60, 60, 10, 10); // This region is on purpose not the hit region
+      ctx.fill();
+      var mypath = new Path2D();
+      mypath.rect(70, 30, 10, 10);
+      ctx.addHitRegion({id: "d", path: mypath});
 
       synthesizeMouse(input, 25,25, {type: "mousedown"});
       is(regionId, "a", "Hit region a", ". Found: " + regionId);
 
       synthesizeMouse(input, 5,5, {type: "mousedown", button: 1});
       is(regionId, "", "Hit region null", ". Found: " + regionId);
 
       synthesizeMouse(input, 65,45, {type: "mousedown"});
       is(regionId, "b", "Hit region b", ". Found: " + regionId);
 
       synthesizeMouse(input, 85,65, {type: "mousedown"});
       is(regionId, "c", "Hit region c", ". Found: " + regionId);
 
+      synthesizeMouse(input, 75,35, {type: "mousedown"});
+      is(regionId, "d", "Hit region d", ". Found: " + regionId);
+
       ctx.removeHitRegion("c");
       synthesizeMouse(input, 85,65, {type: "mousedown"});
       is(regionId, "b", "Hit region b", ". Found: " + regionId);
     } catch (e) {
       ok(false, "unexpected exception thrown: " + e);
     }
 
     SimpleTest.finish();
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -16,16 +16,17 @@ enum CanvasWindingRule { "nonzero", "eve
 dictionary ContextAttributes2D {
   // whether or not we're planning to do a lot of readback operations
   boolean willReadFrequently = false;
   // signal if the canvas contains an alpha channel
   boolean alpha = true;
 };
 
 dictionary HitRegionOptions {
+  Path2D? path = null;
   DOMString id = "";
   Element? control = null;
 };
 
 interface CanvasRenderingContext2D {
 
   // back-reference to the canvas.  Might be null if we're not
   // associated with a canvas.