Bug 966591 - Part 6: Some bug fixes to match spec. r=roc
authorRik Cabanier <cabanier@adobe.com>
Tue, 25 Feb 2014 08:53:42 -0500
changeset 170399 fc089133d229dc28a1c8af60fa28597efe07973b
parent 170398 ec50b53150cac0986eff775cd7beb4c2c46e6fc5
child 170400 675c6efa096fe08402126cf79513439c764353ed
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersroc
bugs966591
milestone30.0a1
Bug 966591 - Part 6: Some bug fixes to match spec. r=roc
content/canvas/src/CanvasRenderingContext2D.cpp
content/canvas/src/CanvasRenderingContext2D.h
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -610,31 +610,43 @@ CanvasRenderingContext2D::ParseColor(con
 
     unused << nsRuleNode::ComputeColor(
       value, presShell ? presShell->GetPresContext() : nullptr, parentContext,
       *aColor);
   }
   return true;
 }
 
+PLDHashOperator
+CanvasRenderingContext2D::RemoveHitRegionProperty(RegionInfo* aEntry, void*)
+{
+  aEntry->mElement->DeleteProperty(nsGkAtoms::hitregion);
+  return PL_DHASH_NEXT;
+}
+
+
 nsresult
 CanvasRenderingContext2D::Reset()
 {
   if (mCanvasElement) {
     mCanvasElement->InvalidateCanvas();
   }
 
   // only do this for non-docshell created contexts,
   // since those are the ones that we created a surface for
   if (mTarget && IsTargetValid() && !mDocShell) {
     gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
   }
 
   mTarget = nullptr;
 
+  // reset hit regions
+  mHitRegionsOptions.EnumerateEntries(RemoveHitRegionProperty, nullptr);
+  mHitRegionsOptions.Clear();
+
   // Since the target changes the backing texture will change, and this will
   // no longer be valid.
   mIsEntireFrameInvalid = false;
   mPredictManyRedrawCalls = false;
 
   return NS_OK;
 }
 
@@ -2376,50 +2388,60 @@ CanvasRenderingContext2D::AddHitRegion(c
   // for now, we require a fallback element
   if (options.mControl == NULL) {
     error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return;
   }
 
   // check if the control is a descendant of our canvas
   HTMLCanvasElement* canvas = GetCanvas();
+  bool isDescendant = true;
   if (!canvas || !nsContentUtils::ContentIsDescendantOf(options.mControl, canvas)) {
-    error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-    return;
+    isDescendant = false;
   }
 
   // check if the path is valid
   EnsureUserSpacePath(CanvasWindingRule::Nonzero);
   if(!mPath) {
     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()));
-  gfxRect rect(bounds.x, bounds.y, bounds.width, bounds.height);
-  nsRect* nsBounds = new nsRect();
-  *nsBounds = nsLayoutUtils::RoundGfxRectToAppRect(rect, AppUnitsPerCSSPixel());
-  options.mControl->SetProperty(nsGkAtoms::hitregion, nsBounds, ReleaseBBoxPropertyValue, true);
+  if ((bounds.width == 0) || (bounds.height == 0) || !bounds.IsFinite()) {
+    // The specified region has no pixels.
+    error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return;
+  }
+
+  if (isDescendant) {
+    nsRect* nsBounds = new nsRect();
+    gfxRect rect(bounds.x, bounds.y, bounds.width, bounds.height);
+    *nsBounds = nsLayoutUtils::RoundGfxRectToAppRect(rect, AppUnitsPerCSSPixel());
+    options.mControl->DeleteProperty(nsGkAtoms::hitregion);
+    options.mControl->SetProperty(nsGkAtoms::hitregion, nsBounds,
+                                  ReleaseBBoxPropertyValue);
+  }
 
   // finally, add the region to the list if it has an ID
   if (options.mId.Length() != 0) {
     mHitRegionsOptions.PutEntry(options.mId)->mElement = options.mControl;
   }
 }
 
 void
 CanvasRenderingContext2D::RemoveHitRegion(const nsAString& id)
 {
   RegionInfo* info = mHitRegionsOptions.GetEntry(id);
   if (!info) {
     return;
   }
 
-  info->mElement->UnsetProperty(nsGkAtoms::hitregion);
+  info->mElement->DeleteProperty(nsGkAtoms::hitregion);
   mHitRegionsOptions.RemoveEntry(id);
 }
 
 /**
  * Used for nsBidiPresUtils::ProcessText
  */
 struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcessor
 {
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -697,16 +697,17 @@ protected:
     RegionInfo(const nsAString *aKey) :
       nsStringHashKey(aKey)
     {
     }
 
     nsRefPtr<Element> mElement;
   };
 
+  static PLDHashOperator RemoveHitRegionProperty(RegionInfo* aEntry, void* aData);
   nsTHashtable<RegionInfo> mHitRegionsOptions;
 
   /**
     * Returns true if a shadow should be drawn along with a
     * drawing operation.
     */
   bool NeedToDrawShadow()
   {