Bug 966591 - Part 6: Some bug fixes to match spec. r=roc
--- 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()
{