Bug 982480 - Add support + test case for context alpha attribute. r=roc

This commit is contained in:
Rik Cabanier 2014-03-16 15:34:14 -04:00
parent 4225b2e3f4
commit 88be9d21db
7 changed files with 66 additions and 1 deletions

View File

@ -97,6 +97,7 @@ public:
// dst alpha is always 1.0. If this is never called, the context
// defaults to false (not opaque).
NS_IMETHOD SetIsOpaque(bool isOpaque) = 0;
virtual bool GetIsOpaque() = 0;
// Invalidate this context and release any held resources, in preperation
// for possibly reinitializing with SetDimensions/InitializeWithSurface.

View File

@ -988,6 +988,10 @@ CanvasRenderingContext2D::SetIsOpaque(bool isOpaque)
ClearTarget();
}
if (mOpaque) {
EnsureTarget();
}
return NS_OK;
}
@ -1062,6 +1066,10 @@ CanvasRenderingContext2D::SetContextOptions(JSContext* aCx, JS::Handle<JS::Value
mForceSoftware = attributes.mWillReadFrequently;
}
if (!attributes.mAlpha) {
SetIsOpaque(true);
}
return NS_OK;
}
@ -3807,6 +3815,30 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
// inherited from Thebes canvas and is no longer true
uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
if (mOpaque) {
for (int32_t j = 0; j < dstWriteRect.height; ++j) {
for (int32_t i = 0; i < dstWriteRect.width; ++i) {
// XXX Is there some useful swizzle MMX we can use here?
#if MOZ_LITTLE_ENDIAN
uint8_t b = *src++;
uint8_t g = *src++;
uint8_t r = *src++;
src++;
#else
src++;
uint8_t r = *src++;
uint8_t g = *src++;
uint8_t b = *src++;
#endif
*dst++ = r;
*dst++ = g;
*dst++ = b;
*dst++ = 255;
}
src += srcStride - (dstWriteRect.width * 4);
dst += (aWidth * 4) - (dstWriteRect.width * 4);
}
} else
for (int32_t j = 0; j < dstWriteRect.height; ++j) {
for (int32_t i = 0; i < dstWriteRect.width; ++i) {
// XXX Is there some useful swizzle MMX we can use here?

View File

@ -408,6 +408,7 @@ public:
{ EnsureTarget(); return mTarget->Snapshot(); }
NS_IMETHOD SetIsOpaque(bool isOpaque) MOZ_OVERRIDE;
bool GetIsOpaque() MOZ_OVERRIDE { return mOpaque; }
NS_IMETHOD Reset() MOZ_OVERRIDE;
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,

View File

@ -178,6 +178,7 @@ public:
mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot() MOZ_OVERRIDE;
NS_IMETHOD SetIsOpaque(bool b) MOZ_OVERRIDE { return NS_OK; };
bool GetIsOpaque() MOZ_OVERRIDE { return false; }
NS_IMETHOD SetContextOptions(JSContext* aCx,
JS::Handle<JS::Value> aOptions) MOZ_OVERRIDE;

View File

@ -21577,6 +21577,24 @@ function test_linedash() {
}
</script>
<p>Canvas test: test_opaque</p>
<canvas id="c688" width="150" height="50"></canvas>
<script type="text/javascript">
function test_opaque() {
var c = document.getElementById("c688");
var ctx = c.getContext("2d", {alpha: false});
ctx.fillStyle = "green";
ctx.fillRect(0,0,10,10);
ctx.fillStyle = "rgba(255,0,0,.5)";
ctx.fillRect(10,0,10,10);
isPixel(ctx, 20, 20, 0, 0, 0, 255, 0);
isPixel(ctx, 5, 5, 0, 128, 0, 255, 0);
isPixel(ctx, 15, 5, 128, 0, 0, 255, 0);
}
</script>
<script>
function asyncTestsDone() {
@ -24873,6 +24891,12 @@ function runTests() {
throw e;
ok(false, "unexpected exception thrown in: test_linedash");
}
try {
test_opaque();
} catch(e) {
throw e;
ok(false, "unexpected exception thrown in: test_opaque");
}
try {
// run this test last since it replaces the getContext method
test_type_replace();

View File

@ -781,7 +781,7 @@ HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewConte
nsIntSize sz = GetWidthHeight();
nsresult rv = mCurrentContext->SetIsOpaque(GetIsOpaque());
nsresult rv = mCurrentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque));
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
mCurrentContextId.Truncate();
@ -903,6 +903,10 @@ HTMLCanvasElement::GetContextAtIndex(int32_t index)
bool
HTMLCanvasElement::GetIsOpaque()
{
if (mCurrentContext) {
return mCurrentContext->GetIsOpaque();
}
return HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque);
}

View File

@ -16,6 +16,8 @@ enum CanvasWindingRule { "nonzero", "evenodd" };
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 {