Adding a whole bunch of canvas mochitests. Bug 407049, tests contributed by Philip Taylor <philip.taylor@cl.cam.ac.uk>
authorbzbarsky@mit.edu
Wed, 05 Dec 2007 18:51:12 -0800
changeset 8782 5b661d3208bd75df95f0b1d598082ba833b3d4e8
parent 8781 9b74e99d6af9395fa2b5dddf2f092f1b12005175
child 8783 3cb1b09603b1fda58a00047f1ad12641ac4ff332
push idunknown
push userunknown
push dateunknown
bugs407049
milestone1.9b2pre
Adding a whole bunch of canvas mochitests. Bug 407049, tests contributed by Philip Taylor <philip.taylor@cl.cam.ac.uk>
content/canvas/Makefile.in
content/canvas/test/Makefile.in
content/canvas/test/image_broken.png
content/canvas/test/image_ggrr-256x256.png
content/canvas/test/image_green-16x16.png
content/canvas/test/image_green-1x1.png
content/canvas/test/image_green.png
content/canvas/test/image_red-16x16.png
content/canvas/test/image_red.png
content/canvas/test/image_redtransparent.png
content/canvas/test/image_rgrg-256x256.png
content/canvas/test/image_transparent.png
content/canvas/test/image_transparent50.png
content/canvas/test/image_yellow.png
content/canvas/test/image_yellow75.png
content/canvas/test/test_2d.canvas.readonly.html
content/canvas/test/test_2d.canvas.reference.html
content/canvas/test/test_2d.clearRect.basic.html
content/canvas/test/test_2d.clearRect.clip.html
content/canvas/test/test_2d.clearRect.globalalpha.html
content/canvas/test/test_2d.clearRect.globalcomposite.html
content/canvas/test/test_2d.clearRect.path.html
content/canvas/test/test_2d.clearRect.shadow.html
content/canvas/test/test_2d.clearRect.transform.html
content/canvas/test/test_2d.clearRect.zero.html
content/canvas/test/test_2d.composite.globalAlpha.canvas.html
content/canvas/test/test_2d.composite.globalAlpha.canvaspattern.html
content/canvas/test/test_2d.composite.globalAlpha.default.html
content/canvas/test/test_2d.composite.globalAlpha.fill.html
content/canvas/test/test_2d.composite.globalAlpha.image.html
content/canvas/test/test_2d.composite.globalAlpha.imagepattern.html
content/canvas/test/test_2d.composite.globalAlpha.range.html
content/canvas/test/test_2d.composite.image.copy.html
content/canvas/test/test_2d.composite.image.destination-atop.html
content/canvas/test/test_2d.composite.image.destination-in.html
content/canvas/test/test_2d.composite.image.destination-out.html
content/canvas/test/test_2d.composite.image.destination-over.html
content/canvas/test/test_2d.composite.image.lighter.html
content/canvas/test/test_2d.composite.image.source-atop.html
content/canvas/test/test_2d.composite.image.source-in.html
content/canvas/test/test_2d.composite.image.source-out.html
content/canvas/test/test_2d.composite.image.source-over.html
content/canvas/test/test_2d.composite.image.xor.html
content/canvas/test/test_2d.composite.operation.clear.html
content/canvas/test/test_2d.composite.operation.darker.html
content/canvas/test/test_2d.composite.operation.default.html
content/canvas/test/test_2d.composite.operation.get.html
content/canvas/test/test_2d.composite.operation.over.html
content/canvas/test/test_2d.composite.solid.copy.html
content/canvas/test/test_2d.composite.solid.destination-atop.html
content/canvas/test/test_2d.composite.solid.destination-in.html
content/canvas/test/test_2d.composite.solid.destination-out.html
content/canvas/test/test_2d.composite.solid.destination-over.html
content/canvas/test/test_2d.composite.solid.lighter.html
content/canvas/test/test_2d.composite.solid.source-atop.html
content/canvas/test/test_2d.composite.solid.source-in.html
content/canvas/test/test_2d.composite.solid.source-out.html
content/canvas/test/test_2d.composite.solid.source-over.html
content/canvas/test/test_2d.composite.transparent.copy.html
content/canvas/test/test_2d.composite.transparent.destination-atop.html
content/canvas/test/test_2d.composite.transparent.destination-in.html
content/canvas/test/test_2d.composite.transparent.destination-out.html
content/canvas/test/test_2d.composite.transparent.destination-over.html
content/canvas/test/test_2d.composite.transparent.lighter.html
content/canvas/test/test_2d.composite.transparent.source-atop.html
content/canvas/test/test_2d.composite.transparent.source-in.html
content/canvas/test/test_2d.composite.transparent.source-out.html
content/canvas/test/test_2d.composite.transparent.source-over.html
content/canvas/test/test_2d.composite.transparent.xor.html
content/canvas/test/test_2d.drawImage.3arg.html
content/canvas/test/test_2d.drawImage.5arg.html
content/canvas/test/test_2d.drawImage.9arg.basic.html
content/canvas/test/test_2d.drawImage.9arg.destpos.html
content/canvas/test/test_2d.drawImage.9arg.destsize.html
content/canvas/test/test_2d.drawImage.9arg.sourcepos.html
content/canvas/test/test_2d.drawImage.9arg.sourcesize.html
content/canvas/test/test_2d.drawImage.alpha.html
content/canvas/test/test_2d.drawImage.broken.html
content/canvas/test/test_2d.drawImage.clip.html
content/canvas/test/test_2d.drawImage.composite.html
content/canvas/test/test_2d.drawImage.floatsource.html
content/canvas/test/test_2d.drawImage.incomplete.html
content/canvas/test/test_2d.drawImage.negativedest.html
content/canvas/test/test_2d.drawImage.negativesource.html
content/canvas/test/test_2d.drawImage.null.html
content/canvas/test/test_2d.drawImage.outsidesource.html
content/canvas/test/test_2d.drawImage.path.html
content/canvas/test/test_2d.drawImage.transform.html
content/canvas/test/test_2d.drawImage.wrongtype.html
content/canvas/test/test_2d.drawImage.zerosource.html
content/canvas/test/test_2d.fillRect.basic.html
content/canvas/test/test_2d.fillRect.clip.html
content/canvas/test/test_2d.fillRect.negative.html
content/canvas/test/test_2d.fillRect.path.html
content/canvas/test/test_2d.fillRect.shadow.html
content/canvas/test/test_2d.fillRect.transform.html
content/canvas/test/test_2d.fillRect.zero.html
content/canvas/test/test_2d.fillStyle.default.html
content/canvas/test/test_2d.fillStyle.get.semitransparent.html
content/canvas/test/test_2d.fillStyle.get.solid.html
content/canvas/test/test_2d.fillStyle.get.transparent.html
content/canvas/test/test_2d.fillStyle.invalidstring.html
content/canvas/test/test_2d.fillStyle.invalidtype.html
content/canvas/test/test_2d.fillStyle.parse.flavor.html
content/canvas/test/test_2d.fillStyle.parse.hex3.html
content/canvas/test/test_2d.fillStyle.parse.hex6.html
content/canvas/test/test_2d.fillStyle.parse.hsl-1.html
content/canvas/test/test_2d.fillStyle.parse.hsl-2.html
content/canvas/test/test_2d.fillStyle.parse.hsl-3.html
content/canvas/test/test_2d.fillStyle.parse.hsl-4.html
content/canvas/test/test_2d.fillStyle.parse.hsl-5.html
content/canvas/test/test_2d.fillStyle.parse.hsla-1.html
content/canvas/test/test_2d.fillStyle.parse.hsla-2.html
content/canvas/test/test_2d.fillStyle.parse.html4.html
content/canvas/test/test_2d.fillStyle.parse.invalid.hex3.html
content/canvas/test/test_2d.fillStyle.parse.invalid.hex6.html
content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-1.html
content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-2.html
content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-3.html
content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-4.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-1.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-2.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-3.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-4.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgba-1.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgba-2.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgba-3.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgba-4.html
content/canvas/test/test_2d.fillStyle.parse.invalid.rgba-5.html
content/canvas/test/test_2d.fillStyle.parse.rgb-clamp-1.html
content/canvas/test/test_2d.fillStyle.parse.rgb-clamp-2.html
content/canvas/test/test_2d.fillStyle.parse.rgb-num.html
content/canvas/test/test_2d.fillStyle.parse.rgb-percent.html
content/canvas/test/test_2d.fillStyle.parse.rgba-clamp-1.html
content/canvas/test/test_2d.fillStyle.parse.rgba-clamp-2.html
content/canvas/test/test_2d.fillStyle.parse.rgba-num-1.html
content/canvas/test/test_2d.fillStyle.parse.rgba-num-2.html
content/canvas/test/test_2d.fillStyle.parse.rgba-percent.html
content/canvas/test/test_2d.fillStyle.parse.rgba-solid-1.html
content/canvas/test/test_2d.fillStyle.parse.rgba-solid-2.html
content/canvas/test/test_2d.fillStyle.parse.svg-1.html
content/canvas/test/test_2d.fillStyle.parse.svg-2.html
content/canvas/test/test_2d.fillStyle.parse.system.html
content/canvas/test/test_2d.fillStyle.parse.transparent-1.html
content/canvas/test/test_2d.fillStyle.parse.transparent-2.html
content/canvas/test/test_2d.getcontext.exists.html
content/canvas/test/test_2d.getcontext.shared.html
content/canvas/test/test_2d.getcontext.unique.html
content/canvas/test/test_2d.gradient.empty.html
content/canvas/test/test_2d.gradient.interpolate.alpha.html
content/canvas/test/test_2d.gradient.interpolate.colour.html
content/canvas/test/test_2d.gradient.interpolate.colouralpha.html
content/canvas/test/test_2d.gradient.interpolate.multiple.html
content/canvas/test/test_2d.gradient.interpolate.outside.html
content/canvas/test/test_2d.gradient.interpolate.overlap.html
content/canvas/test/test_2d.gradient.interpolate.overlap2.html
content/canvas/test/test_2d.gradient.interpolate.solid.html
content/canvas/test/test_2d.gradient.interpolate.vertical.html
content/canvas/test/test_2d.gradient.interpolate.zerosize.html
content/canvas/test/test_2d.gradient.object.compare.html
content/canvas/test/test_2d.gradient.object.crosscanvas.html
content/canvas/test/test_2d.gradient.object.invalidcolour.html
content/canvas/test/test_2d.gradient.object.invalidoffset.html
content/canvas/test/test_2d.gradient.object.return.html
content/canvas/test/test_2d.gradient.object.update.html
content/canvas/test/test_2d.gradient.radial.cone.bottom.html
content/canvas/test/test_2d.gradient.radial.cone.cylinder.html
content/canvas/test/test_2d.gradient.radial.cone.front.html
content/canvas/test/test_2d.gradient.radial.cone.shape1.html
content/canvas/test/test_2d.gradient.radial.cone.top.html
content/canvas/test/test_2d.gradient.radial.inside1.html
content/canvas/test/test_2d.gradient.radial.inside2.html
content/canvas/test/test_2d.gradient.radial.inside3.html
content/canvas/test/test_2d.gradient.radial.invalid.html
content/canvas/test/test_2d.gradient.radial.negative.html
content/canvas/test/test_2d.gradient.radial.outside1.html
content/canvas/test/test_2d.imageData.get.basic.html
content/canvas/test/test_2d.imageData.get.nonfinite.html
content/canvas/test/test_2d.imageData.get.nonpositive.html
content/canvas/test/test_2d.imageData.get.nonpremul.html
content/canvas/test/test_2d.imageData.get.order.alpha.html
content/canvas/test/test_2d.imageData.get.order.cols.html
content/canvas/test/test_2d.imageData.get.order.rgb.html
content/canvas/test/test_2d.imageData.get.order.rows.html
content/canvas/test/test_2d.imageData.get.properties.html
content/canvas/test/test_2d.imageData.get.smallest.html
content/canvas/test/test_2d.imageData.get.sourcepos.html
content/canvas/test/test_2d.imageData.get.sourcesize.html
content/canvas/test/test_2d.imageData.get.values.html
content/canvas/test/test_2d.imageData.put.alpha.html
content/canvas/test/test_2d.imageData.put.basic.html
content/canvas/test/test_2d.imageData.put.modified.html
content/canvas/test/test_2d.imageData.put.path.html
content/canvas/test/test_2d.imageData.put.type.correct.html
content/canvas/test/test_2d.imageData.put.type.extra.html
content/canvas/test/test_2d.imageData.put.type.invalidsize.html
content/canvas/test/test_2d.imageData.put.type.invalidvalues.html
content/canvas/test/test_2d.imageData.put.type.missing.html
content/canvas/test/test_2d.imageData.put.type.onepixel.html
content/canvas/test/test_2d.imageData.put.unaffected.html
content/canvas/test/test_2d.imageData.put.unchanged.html
content/canvas/test/test_2d.line.cap.closed.html
content/canvas/test/test_2d.line.cap.open.html
content/canvas/test/test_2d.line.cap.zerobezier.round.html
content/canvas/test/test_2d.line.cap.zeroline.round.html
content/canvas/test/test_2d.line.cap.zeroline.square.html
content/canvas/test/test_2d.line.cross.html
content/canvas/test/test_2d.line.defaults.html
content/canvas/test/test_2d.line.invalid.lineWidth.html
content/canvas/test/test_2d.line.invalid.miterLimit.html
content/canvas/test/test_2d.line.join.closed.html
content/canvas/test/test_2d.line.join.open.html
content/canvas/test/test_2d.line.join.parallel.html
content/canvas/test/test_2d.line.join.zeroline.corner.html
content/canvas/test/test_2d.line.join.zeroline.join.html
content/canvas/test/test_2d.line.lineCap.butt.html
content/canvas/test/test_2d.line.lineCap.round.html
content/canvas/test/test_2d.line.lineCap.square.html
content/canvas/test/test_2d.line.lineJoin.bevel.html
content/canvas/test/test_2d.line.lineJoin.miter.html
content/canvas/test/test_2d.line.lineJoin.round.html
content/canvas/test/test_2d.line.lineWidth.basic.html
content/canvas/test/test_2d.line.lineWidth.transformed.html
content/canvas/test/test_2d.line.miter.exceeded.html
content/canvas/test/test_2d.line.miter.lineedge.html
content/canvas/test/test_2d.line.miter.rightangle.html
content/canvas/test/test_2d.line.miter.within.html
content/canvas/test/test_2d.line.union.html
content/canvas/test/test_2d.path.arc.angle.1.html
content/canvas/test/test_2d.path.arc.angle.2.html
content/canvas/test/test_2d.path.arc.angle.3.html
content/canvas/test/test_2d.path.arc.angle.4.html
content/canvas/test/test_2d.path.arc.empty.html
content/canvas/test/test_2d.path.arc.end.html
content/canvas/test/test_2d.path.arc.negative.html
content/canvas/test/test_2d.path.arc.nonempty.html
content/canvas/test/test_2d.path.arc.selfintersect.1.html
content/canvas/test/test_2d.path.arc.selfintersect.2.html
content/canvas/test/test_2d.path.arc.shape.1.html
content/canvas/test/test_2d.path.arc.shape.2.html
content/canvas/test/test_2d.path.arc.shape.3.html
content/canvas/test/test_2d.path.arc.shape.4.html
content/canvas/test/test_2d.path.arc.shape.5.html
content/canvas/test/test_2d.path.arc.zero.1.html
content/canvas/test/test_2d.path.arc.zero.2.html
content/canvas/test/test_2d.path.arc.zero.3.html
content/canvas/test/test_2d.path.arc.zero.4.html
content/canvas/test/test_2d.path.arc.zero.5.html
content/canvas/test/test_2d.path.arc.zero.6.html
content/canvas/test/test_2d.path.arc.zero.html
content/canvas/test/test_2d.path.beginPath.html
content/canvas/test/test_2d.path.bezierCurveTo.basic.html
content/canvas/test/test_2d.path.bezierCurveTo.emptysubpath.html
content/canvas/test/test_2d.path.bezierCurveTo.scaled.html
content/canvas/test/test_2d.path.bezierCurveTo.shape.html
content/canvas/test/test_2d.path.clip.basic.1.html
content/canvas/test/test_2d.path.clip.basic.2.html
content/canvas/test/test_2d.path.clip.empty.html
content/canvas/test/test_2d.path.clip.intersect.html
content/canvas/test/test_2d.path.clip.unaffected.html
content/canvas/test/test_2d.path.clip.winding.1.html
content/canvas/test/test_2d.path.clip.winding.2.html
content/canvas/test/test_2d.path.closePath.empty.html
content/canvas/test/test_2d.path.closePath.newline.html
content/canvas/test/test_2d.path.closePath.nextpoint.html
content/canvas/test/test_2d.path.fill.closed.basic.html
content/canvas/test/test_2d.path.fill.closed.unaffected.html
content/canvas/test/test_2d.path.fill.winding.add.html
content/canvas/test/test_2d.path.fill.winding.subtract.1.html
content/canvas/test/test_2d.path.fill.winding.subtract.2.html
content/canvas/test/test_2d.path.fill.winding.subtract.3.html
content/canvas/test/test_2d.path.initial.html
content/canvas/test/test_2d.path.isPointInPath.basic.1.html
content/canvas/test/test_2d.path.isPointInPath.basic.2.html
content/canvas/test/test_2d.path.isPointInPath.empty.html
content/canvas/test/test_2d.path.isPointInPath.transform.1.html
content/canvas/test/test_2d.path.isPointInPath.transform.2.html
content/canvas/test/test_2d.path.isPointInPath.transform.3.html
content/canvas/test/test_2d.path.isPointInPath.unclosed.html
content/canvas/test/test_2d.path.isPointInPath.winding.html
content/canvas/test/test_2d.path.lineTo.basic.html
content/canvas/test/test_2d.path.lineTo.emptysubpath.html
content/canvas/test/test_2d.path.lineTo.nextpoint.html
content/canvas/test/test_2d.path.moveTo.basic.html
content/canvas/test/test_2d.path.moveTo.multiple.html
content/canvas/test/test_2d.path.moveTo.newsubpath.html
content/canvas/test/test_2d.path.quadraticCurveTo.basic.html
content/canvas/test/test_2d.path.quadraticCurveTo.emptysubpath.html
content/canvas/test/test_2d.path.quadraticCurveTo.scaled.html
content/canvas/test/test_2d.path.quadraticCurveTo.shape.html
content/canvas/test/test_2d.path.rect.basic.html
content/canvas/test/test_2d.path.rect.closed.html
content/canvas/test/test_2d.path.rect.end.1.html
content/canvas/test/test_2d.path.rect.end.2.html
content/canvas/test/test_2d.path.rect.negative.html
content/canvas/test/test_2d.path.rect.newsubpath.html
content/canvas/test/test_2d.path.rect.selfintersect.html
content/canvas/test/test_2d.path.rect.zero.1.html
content/canvas/test/test_2d.path.rect.zero.2.html
content/canvas/test/test_2d.path.rect.zero.3.html
content/canvas/test/test_2d.path.rect.zero.4.html
content/canvas/test/test_2d.path.rect.zero.5.html
content/canvas/test/test_2d.path.rect.zero.6.html
content/canvas/test/test_2d.path.stroke.unaffected.html
content/canvas/test/test_2d.path.stroke.union.html
content/canvas/test/test_2d.path.transformation.basic.html
content/canvas/test/test_2d.path.transformation.multiple.1.html
content/canvas/test/test_2d.path.transformation.multiple.2.html
content/canvas/test/test_2d.path.transformation.multiple.3.html
content/canvas/test/test_2d.pattern.basic.canvas.html
content/canvas/test/test_2d.pattern.basic.image.html
content/canvas/test/test_2d.pattern.basic.nocontext.html
content/canvas/test/test_2d.pattern.basic.type.html
content/canvas/test/test_2d.pattern.crosscanvas.html
content/canvas/test/test_2d.pattern.image.broken.html
content/canvas/test/test_2d.pattern.image.incomplete.html
content/canvas/test/test_2d.pattern.image.null.html
content/canvas/test/test_2d.pattern.image.string.html
content/canvas/test/test_2d.pattern.image.undefined.html
content/canvas/test/test_2d.pattern.modify.canvas1.html
content/canvas/test/test_2d.pattern.modify.canvas2.html
content/canvas/test/test_2d.pattern.modify.image1.html
content/canvas/test/test_2d.pattern.modify.image2.html
content/canvas/test/test_2d.pattern.paint.coord3.html
content/canvas/test/test_2d.pattern.paint.norepeat.basic.html
content/canvas/test/test_2d.pattern.paint.norepeat.coord1.html
content/canvas/test/test_2d.pattern.paint.norepeat.coord2.html
content/canvas/test/test_2d.pattern.paint.norepeat.outside.html
content/canvas/test/test_2d.pattern.paint.repeat.basic.html
content/canvas/test/test_2d.pattern.paint.repeat.coord1.html
content/canvas/test/test_2d.pattern.paint.repeat.coord2.html
content/canvas/test/test_2d.pattern.paint.repeat.coord3.html
content/canvas/test/test_2d.pattern.paint.repeat.outside.html
content/canvas/test/test_2d.pattern.paint.repeatx.basic.html
content/canvas/test/test_2d.pattern.paint.repeatx.coord1.html
content/canvas/test/test_2d.pattern.paint.repeatx.outside.html
content/canvas/test/test_2d.pattern.paint.repeaty.basic.html
content/canvas/test/test_2d.pattern.paint.repeaty.coord1.html
content/canvas/test/test_2d.pattern.paint.repeaty.outside.html
content/canvas/test/test_2d.pattern.repeat.case.html
content/canvas/test/test_2d.pattern.repeat.empty.html
content/canvas/test/test_2d.pattern.repeat.missing.html
content/canvas/test/test_2d.pattern.repeat.null.html
content/canvas/test/test_2d.pattern.repeat.nullsuffix.html
content/canvas/test/test_2d.pattern.repeat.undefined.html
content/canvas/test/test_2d.pattern.repeat.unrecognised.html
content/canvas/test/test_2d.state.saverestore.bitmap.html
content/canvas/test/test_2d.state.saverestore.clip.html
content/canvas/test/test_2d.state.saverestore.fillStyle.html
content/canvas/test/test_2d.state.saverestore.globalAlpha.html
content/canvas/test/test_2d.state.saverestore.globalCompositeOperation.html
content/canvas/test/test_2d.state.saverestore.lineCap.html
content/canvas/test/test_2d.state.saverestore.lineJoin.html
content/canvas/test/test_2d.state.saverestore.lineWidth.html
content/canvas/test/test_2d.state.saverestore.miterLimit.html
content/canvas/test/test_2d.state.saverestore.path.html
content/canvas/test/test_2d.state.saverestore.shadowBlur.html
content/canvas/test/test_2d.state.saverestore.shadowColor.html
content/canvas/test/test_2d.state.saverestore.shadowOffsetX.html
content/canvas/test/test_2d.state.saverestore.shadowOffsetY.html
content/canvas/test/test_2d.state.saverestore.stack.html
content/canvas/test/test_2d.state.saverestore.stackdepth.html
content/canvas/test/test_2d.state.saverestore.strokeStyle.html
content/canvas/test/test_2d.state.saverestore.transformation.html
content/canvas/test/test_2d.strokeRect.basic.html
content/canvas/test/test_2d.strokeRect.clip.html
content/canvas/test/test_2d.strokeRect.globalalpha.html
content/canvas/test/test_2d.strokeRect.globalcomposite.html
content/canvas/test/test_2d.strokeRect.negative.html
content/canvas/test/test_2d.strokeRect.path.html
content/canvas/test/test_2d.strokeRect.shadow.html
content/canvas/test/test_2d.strokeRect.transform.html
content/canvas/test/test_2d.strokeRect.zero.1.html
content/canvas/test/test_2d.strokeRect.zero.2.html
content/canvas/test/test_2d.strokeRect.zero.3.html
content/canvas/test/test_2d.strokeRect.zero.4.html
content/canvas/test/test_2d.strokeRect.zero.5.html
content/canvas/test/test_2d.strokeStyle.default.html
content/canvas/test/test_2d.transformation.order.html
content/canvas/test/test_2d.transformation.rotate.direction.html
content/canvas/test/test_2d.transformation.rotate.infinity.html
content/canvas/test/test_2d.transformation.rotate.nan.html
content/canvas/test/test_2d.transformation.rotate.neginfinity.html
content/canvas/test/test_2d.transformation.rotate.radians.html
content/canvas/test/test_2d.transformation.rotate.wrap.html
content/canvas/test/test_2d.transformation.rotate.wrapnegative.html
content/canvas/test/test_2d.transformation.rotate.zero.html
content/canvas/test/test_2d.transformation.scale.basic.html
content/canvas/test/test_2d.transformation.scale.large.html
content/canvas/test/test_2d.transformation.scale.multiple.html
content/canvas/test/test_2d.transformation.scale.negative.html
content/canvas/test/test_2d.transformation.scale.zero.html
content/canvas/test/test_2d.transformation.setTransform.multiple.html
content/canvas/test/test_2d.transformation.setTransform.skewed.html
content/canvas/test/test_2d.transformation.transform.identity.html
content/canvas/test/test_2d.transformation.transform.multiply.html
content/canvas/test/test_2d.transformation.transform.skewed.html
content/canvas/test/test_2d.transformation.translate.basic.html
content/canvas/test/test_2d.type.delete.html
content/canvas/test/test_2d.type.exists.html
content/canvas/test/test_2d.type.extend.html
content/canvas/test/test_2d.type.name.html
content/canvas/test/test_2d.type.prototype.html
content/canvas/test/test_2d.type.replace.html
content/canvas/test/test_2d.voidreturn.html
content/canvas/test/test_fallback.basic.html
content/canvas/test/test_fallback.multiple.html
content/canvas/test/test_fallback.nested.html
content/canvas/test/test_initial.colour.html
content/canvas/test/test_initial.reset.2dstate.html
content/canvas/test/test_initial.reset.clip.html
content/canvas/test/test_initial.reset.different.html
content/canvas/test/test_initial.reset.gradient.html
content/canvas/test/test_initial.reset.path.html
content/canvas/test/test_initial.reset.pattern.html
content/canvas/test/test_initial.reset.same.html
content/canvas/test/test_initial.reset.transform.html
content/canvas/test/test_size.attributes.default.html
content/canvas/test/test_size.attributes.html
content/canvas/test/test_size.attributes.parse.badsuffix.html
content/canvas/test/test_size.attributes.parse.floatsuffix.html
content/canvas/test/test_size.attributes.parse.negative.html
content/canvas/test/test_size.attributes.parse.nonnumber.html
content/canvas/test/test_size.attributes.parse.percentsuffix.html
content/canvas/test/test_size.attributes.parse.whitespace.html
content/canvas/test/test_size.attributes.parse.zero.html
content/canvas/test/test_size.attributes.parse.zerosuffix.html
content/canvas/test/test_size.attributes.reflect.1.html
content/canvas/test/test_size.attributes.reflect.2.html
content/canvas/test/test_size.attributes.removed.html
content/canvas/test/test_size.attributes.setAttribute.badsuffix.html
content/canvas/test/test_size.attributes.setAttribute.floatsuffix.html
content/canvas/test/test_size.attributes.setAttribute.negative.html
content/canvas/test/test_size.attributes.setAttribute.nonnumber.html
content/canvas/test/test_size.attributes.setAttribute.percentsuffix.html
content/canvas/test/test_size.attributes.setAttribute.whitespace.html
content/canvas/test/test_size.attributes.setAttribute.zero.html
content/canvas/test/test_size.attributes.setAttribute.zerosuffix.html
content/canvas/test/test_size.attributes.style.html
content/canvas/test/test_size.attributes.type.get.html
content/canvas/test/test_size.attributes.type.set.html
content/canvas/test/test_toDataURL.complexcolours.html
content/canvas/test/test_toDataURL.default.html
content/canvas/test/test_toDataURL.nocontext.html
content/canvas/test/test_toDataURL.png.html
content/canvas/test/test_toDataURL.primarycolours.html
content/canvas/test/test_type.delete.html
content/canvas/test/test_type.exists.html
content/canvas/test/test_type.extend.html
content/canvas/test/test_type.name.html
content/canvas/test/test_type.prototype.html
content/canvas/test/test_type.replace.html
--- a/content/canvas/Makefile.in
+++ b/content/canvas/Makefile.in
@@ -39,10 +39,14 @@ DEPTH		= ../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS		= public src
 
+ifdef MOZ_MOCHITEST
+DIRS		+= test
+endif
+
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/Makefile.in
@@ -0,0 +1,526 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Philip Taylor <philip.taylor@cl.cam.ac.uk>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = content/canvas/test
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+	test_fallback.basic.html \
+	test_fallback.multiple.html \
+	test_fallback.nested.html \
+	test_type.name.html \
+	test_type.exists.html \
+	test_type.delete.html \
+	test_type.prototype.html \
+	test_type.replace.html \
+	test_type.extend.html \
+	test_size.attributes.html \
+	test_size.attributes.type.get.html \
+	test_size.attributes.type.set.html \
+	test_size.attributes.default.html \
+	test_size.attributes.reflect.1.html \
+	test_size.attributes.reflect.2.html \
+	test_size.attributes.removed.html \
+	test_size.attributes.parse.whitespace.html \
+	test_size.attributes.parse.nonnumber.html \
+	test_size.attributes.parse.zero.html \
+	test_size.attributes.parse.negative.html \
+	test_size.attributes.parse.zerosuffix.html \
+	test_size.attributes.parse.floatsuffix.html \
+	test_size.attributes.parse.badsuffix.html \
+	test_size.attributes.parse.percentsuffix.html \
+	test_size.attributes.setAttribute.whitespace.html \
+	test_size.attributes.setAttribute.nonnumber.html \
+	test_size.attributes.setAttribute.zero.html \
+	test_size.attributes.setAttribute.negative.html \
+	test_size.attributes.setAttribute.zerosuffix.html \
+	test_size.attributes.setAttribute.floatsuffix.html \
+	test_size.attributes.setAttribute.badsuffix.html \
+	test_size.attributes.setAttribute.percentsuffix.html \
+	test_size.attributes.style.html \
+	test_initial.colour.html \
+	test_initial.reset.different.html \
+	test_initial.reset.same.html \
+	test_initial.reset.path.html \
+	test_initial.reset.clip.html \
+	test_initial.reset.transform.html \
+	test_initial.reset.gradient.html \
+	test_initial.reset.pattern.html \
+	test_toDataURL.default.html \
+	test_toDataURL.png.html \
+	test_toDataURL.nocontext.html \
+	test_toDataURL.primarycolours.html \
+	test_toDataURL.complexcolours.html \
+	test_2d.getcontext.exists.html \
+	test_2d.type.name.html \
+	test_2d.type.exists.html \
+	test_2d.type.delete.html \
+	test_2d.type.prototype.html \
+	test_2d.type.replace.html \
+	test_2d.type.extend.html \
+	test_2d.getcontext.unique.html \
+	test_2d.getcontext.shared.html \
+	test_2d.voidreturn.html \
+	test_2d.canvas.reference.html \
+	test_2d.canvas.readonly.html \
+	test_2d.state.saverestore.strokeStyle.html \
+	test_2d.state.saverestore.fillStyle.html \
+	test_2d.state.saverestore.globalAlpha.html \
+	test_2d.state.saverestore.lineWidth.html \
+	test_2d.state.saverestore.lineCap.html \
+	test_2d.state.saverestore.lineJoin.html \
+	test_2d.state.saverestore.miterLimit.html \
+	test_2d.state.saverestore.shadowOffsetX.html \
+	test_2d.state.saverestore.shadowOffsetY.html \
+	test_2d.state.saverestore.shadowBlur.html \
+	test_2d.state.saverestore.shadowColor.html \
+	test_2d.state.saverestore.globalCompositeOperation.html \
+	test_initial.reset.2dstate.html \
+	test_2d.state.saverestore.transformation.html \
+	test_2d.state.saverestore.clip.html \
+	test_2d.state.saverestore.path.html \
+	test_2d.state.saverestore.bitmap.html \
+	test_2d.state.saverestore.stack.html \
+	test_2d.state.saverestore.stackdepth.html \
+	test_2d.transformation.order.html \
+	test_2d.transformation.scale.basic.html \
+	test_2d.transformation.scale.zero.html \
+	test_2d.transformation.scale.negative.html \
+	test_2d.transformation.scale.large.html \
+	test_2d.transformation.scale.multiple.html \
+	test_2d.transformation.rotate.zero.html \
+	test_2d.transformation.rotate.radians.html \
+	test_2d.transformation.rotate.direction.html \
+	test_2d.transformation.rotate.wrap.html \
+	test_2d.transformation.rotate.wrapnegative.html \
+	test_2d.transformation.rotate.infinity.html \
+	test_2d.transformation.rotate.neginfinity.html \
+	test_2d.transformation.rotate.nan.html \
+	test_2d.transformation.translate.basic.html \
+	test_2d.transformation.transform.identity.html \
+	test_2d.transformation.transform.skewed.html \
+	test_2d.transformation.transform.multiply.html \
+	test_2d.transformation.setTransform.skewed.html \
+	test_2d.transformation.setTransform.multiple.html \
+	test_2d.composite.globalAlpha.range.html \
+	test_2d.composite.globalAlpha.default.html \
+	test_2d.composite.globalAlpha.fill.html \
+	test_2d.composite.globalAlpha.image.html \
+	test_2d.composite.globalAlpha.canvas.html \
+	test_2d.composite.globalAlpha.imagepattern.html \
+	test_2d.composite.globalAlpha.canvaspattern.html \
+	test_2d.composite.solid.source-over.html \
+	test_2d.composite.solid.destination-over.html \
+	test_2d.composite.solid.source-in.html \
+	test_2d.composite.solid.destination-in.html \
+	test_2d.composite.solid.source-out.html \
+	test_2d.composite.solid.destination-out.html \
+	test_2d.composite.solid.source-atop.html \
+	test_2d.composite.solid.destination-atop.html \
+	test_2d.composite.solid.copy.html \
+	test_2d.composite.solid.lighter.html \
+	test_2d.composite.transparent.source-over.html \
+	test_2d.composite.transparent.destination-over.html \
+	test_2d.composite.transparent.source-in.html \
+	test_2d.composite.transparent.destination-in.html \
+	test_2d.composite.transparent.source-out.html \
+	test_2d.composite.transparent.destination-out.html \
+	test_2d.composite.transparent.source-atop.html \
+	test_2d.composite.transparent.destination-atop.html \
+	test_2d.composite.transparent.xor.html \
+	test_2d.composite.transparent.copy.html \
+	test_2d.composite.transparent.lighter.html \
+	test_2d.composite.image.source-over.html \
+	test_2d.composite.image.destination-over.html \
+	test_2d.composite.image.source-in.html \
+	test_2d.composite.image.destination-in.html \
+	test_2d.composite.image.source-out.html \
+	test_2d.composite.image.destination-out.html \
+	test_2d.composite.image.source-atop.html \
+	test_2d.composite.image.destination-atop.html \
+	test_2d.composite.image.xor.html \
+	test_2d.composite.image.copy.html \
+	test_2d.composite.image.lighter.html \
+	test_2d.composite.operation.get.html \
+	test_2d.composite.operation.darker.html \
+	test_2d.composite.operation.over.html \
+	test_2d.composite.operation.clear.html \
+	test_2d.composite.operation.default.html \
+	test_2d.fillStyle.parse.html4.html \
+	test_2d.fillStyle.parse.hex3.html \
+	test_2d.fillStyle.parse.hex6.html \
+	test_2d.fillStyle.parse.rgb-num.html \
+	test_2d.fillStyle.parse.rgb-clamp-1.html \
+	test_2d.fillStyle.parse.rgb-clamp-2.html \
+	test_2d.fillStyle.parse.rgb-percent.html \
+	test_2d.fillStyle.parse.rgba-solid-1.html \
+	test_2d.fillStyle.parse.rgba-solid-2.html \
+	test_2d.fillStyle.parse.rgba-num-1.html \
+	test_2d.fillStyle.parse.rgba-num-2.html \
+	test_2d.fillStyle.parse.rgba-percent.html \
+	test_2d.fillStyle.parse.rgba-clamp-1.html \
+	test_2d.fillStyle.parse.rgba-clamp-2.html \
+	test_2d.fillStyle.parse.transparent-1.html \
+	test_2d.fillStyle.parse.transparent-2.html \
+	test_2d.fillStyle.parse.hsl-1.html \
+	test_2d.fillStyle.parse.hsl-2.html \
+	test_2d.fillStyle.parse.hsl-3.html \
+	test_2d.fillStyle.parse.hsl-4.html \
+	test_2d.fillStyle.parse.hsl-5.html \
+	test_2d.fillStyle.parse.hsla-1.html \
+	test_2d.fillStyle.parse.hsla-2.html \
+	test_2d.fillStyle.parse.svg-1.html \
+	test_2d.fillStyle.parse.svg-2.html \
+	test_2d.fillStyle.parse.invalid.hex3.html \
+	test_2d.fillStyle.parse.invalid.hex6.html \
+	test_2d.fillStyle.parse.invalid.rgb-1.html \
+	test_2d.fillStyle.parse.invalid.rgb-2.html \
+	test_2d.fillStyle.parse.invalid.rgb-3.html \
+	test_2d.fillStyle.parse.invalid.rgb-4.html \
+	test_2d.fillStyle.parse.invalid.rgba-1.html \
+	test_2d.fillStyle.parse.invalid.rgba-2.html \
+	test_2d.fillStyle.parse.invalid.rgba-3.html \
+	test_2d.fillStyle.parse.invalid.rgba-4.html \
+	test_2d.fillStyle.parse.invalid.rgba-5.html \
+	test_2d.fillStyle.parse.invalid.hsl-1.html \
+	test_2d.fillStyle.parse.invalid.hsl-2.html \
+	test_2d.fillStyle.parse.invalid.hsl-3.html \
+	test_2d.fillStyle.parse.invalid.hsl-4.html \
+	test_2d.fillStyle.parse.system.html \
+	test_2d.fillStyle.parse.flavor.html \
+	test_2d.fillStyle.invalidstring.html \
+	test_2d.fillStyle.invalidtype.html \
+	test_2d.fillStyle.get.solid.html \
+	test_2d.fillStyle.get.semitransparent.html \
+	test_2d.fillStyle.get.transparent.html \
+	test_2d.fillStyle.default.html \
+	test_2d.strokeStyle.default.html \
+	test_2d.gradient.object.return.html \
+	test_2d.gradient.interpolate.solid.html \
+	test_2d.gradient.interpolate.colour.html \
+	test_2d.gradient.interpolate.alpha.html \
+	test_2d.gradient.interpolate.colouralpha.html \
+	test_2d.gradient.interpolate.outside.html \
+	test_2d.gradient.interpolate.zerosize.html \
+	test_2d.gradient.interpolate.vertical.html \
+	test_2d.gradient.interpolate.multiple.html \
+	test_2d.gradient.interpolate.overlap.html \
+	test_2d.gradient.interpolate.overlap2.html \
+	test_2d.gradient.object.update.html \
+	test_2d.gradient.object.compare.html \
+	test_2d.gradient.object.crosscanvas.html \
+	test_2d.gradient.object.invalidoffset.html \
+	test_2d.gradient.object.invalidcolour.html \
+	test_2d.gradient.radial.negative.html \
+	test_2d.gradient.radial.invalid.html \
+	test_2d.gradient.radial.inside1.html \
+	test_2d.gradient.radial.inside2.html \
+	test_2d.gradient.radial.inside3.html \
+	test_2d.gradient.radial.outside1.html \
+	test_2d.gradient.radial.cone.front.html \
+	test_2d.gradient.radial.cone.bottom.html \
+	test_2d.gradient.radial.cone.top.html \
+	test_2d.gradient.radial.cone.cylinder.html \
+	test_2d.gradient.radial.cone.shape1.html \
+	test_2d.pattern.basic.type.html \
+	test_2d.pattern.basic.image.html \
+	test_2d.pattern.basic.canvas.html \
+	test_2d.pattern.basic.nocontext.html \
+	test_2d.pattern.image.undefined.html \
+	test_2d.pattern.image.null.html \
+	test_2d.pattern.image.string.html \
+	test_2d.pattern.image.incomplete.html \
+	test_2d.pattern.image.broken.html \
+	test_2d.pattern.repeat.empty.html \
+	test_2d.pattern.repeat.null.html \
+	test_2d.pattern.repeat.undefined.html \
+	test_2d.pattern.repeat.missing.html \
+	test_2d.pattern.repeat.unrecognised.html \
+	test_2d.pattern.repeat.case.html \
+	test_2d.pattern.repeat.nullsuffix.html \
+	test_2d.pattern.modify.image1.html \
+	test_2d.pattern.modify.image2.html \
+	test_2d.pattern.modify.canvas1.html \
+	test_2d.pattern.modify.canvas2.html \
+	test_2d.pattern.crosscanvas.html \
+	test_2d.pattern.paint.norepeat.basic.html \
+	test_2d.pattern.paint.norepeat.outside.html \
+	test_2d.pattern.paint.norepeat.coord1.html \
+	test_2d.pattern.paint.norepeat.coord2.html \
+	test_2d.pattern.paint.coord3.html \
+	test_2d.pattern.paint.repeat.basic.html \
+	test_2d.pattern.paint.repeat.outside.html \
+	test_2d.pattern.paint.repeat.coord1.html \
+	test_2d.pattern.paint.repeat.coord2.html \
+	test_2d.pattern.paint.repeat.coord3.html \
+	test_2d.pattern.paint.repeatx.basic.html \
+	test_2d.pattern.paint.repeatx.outside.html \
+	test_2d.pattern.paint.repeatx.coord1.html \
+	test_2d.pattern.paint.repeaty.basic.html \
+	test_2d.pattern.paint.repeaty.outside.html \
+	test_2d.pattern.paint.repeaty.coord1.html \
+	test_2d.line.defaults.html \
+	test_2d.line.invalid.lineWidth.html \
+	test_2d.line.invalid.miterLimit.html \
+	test_2d.line.lineWidth.basic.html \
+	test_2d.line.lineWidth.transformed.html \
+	test_2d.line.lineCap.butt.html \
+	test_2d.line.lineCap.round.html \
+	test_2d.line.lineCap.square.html \
+	test_2d.line.lineJoin.bevel.html \
+	test_2d.line.lineJoin.round.html \
+	test_2d.line.lineJoin.miter.html \
+	test_2d.line.join.open.html \
+	test_2d.line.join.closed.html \
+	test_2d.line.join.zeroline.corner.html \
+	test_2d.line.join.zeroline.join.html \
+	test_2d.line.cap.open.html \
+	test_2d.line.cap.closed.html \
+	test_2d.line.cap.zeroline.round.html \
+	test_2d.line.cap.zeroline.square.html \
+	test_2d.line.miter.exceeded.html \
+	test_2d.line.miter.within.html \
+	test_2d.line.cross.html \
+	test_2d.line.union.html \
+	test_2d.clearRect.basic.html \
+	test_2d.clearRect.path.html \
+	test_2d.clearRect.zero.html \
+	test_2d.clearRect.transform.html \
+	test_2d.clearRect.globalalpha.html \
+	test_2d.clearRect.globalcomposite.html \
+	test_2d.clearRect.clip.html \
+	test_2d.clearRect.shadow.html \
+	test_2d.fillRect.negative.html \
+	test_2d.fillRect.basic.html \
+	test_2d.fillRect.path.html \
+	test_2d.fillRect.zero.html \
+	test_2d.fillRect.transform.html \
+	test_2d.fillRect.clip.html \
+	test_2d.fillRect.shadow.html \
+	test_2d.strokeRect.negative.html \
+	test_2d.strokeRect.basic.html \
+	test_2d.strokeRect.path.html \
+	test_2d.strokeRect.zero.1.html \
+	test_2d.strokeRect.zero.2.html \
+	test_2d.strokeRect.zero.3.html \
+	test_2d.strokeRect.zero.4.html \
+	test_2d.strokeRect.transform.html \
+	test_2d.strokeRect.globalalpha.html \
+	test_2d.strokeRect.globalcomposite.html \
+	test_2d.strokeRect.clip.html \
+	test_2d.strokeRect.shadow.html \
+	test_2d.path.initial.html \
+	test_2d.path.beginPath.html \
+	test_2d.path.moveTo.basic.html \
+	test_2d.path.moveTo.newsubpath.html \
+	test_2d.path.moveTo.multiple.html \
+	test_2d.path.closePath.empty.html \
+	test_2d.path.closePath.newline.html \
+	test_2d.path.closePath.nextpoint.html \
+	test_2d.path.lineTo.emptysubpath.html \
+	test_2d.path.lineTo.basic.html \
+	test_2d.path.lineTo.nextpoint.html \
+	test_2d.path.quadraticCurveTo.emptysubpath.html \
+	test_2d.path.quadraticCurveTo.basic.html \
+	test_2d.path.quadraticCurveTo.shape.html \
+	test_2d.path.quadraticCurveTo.scaled.html \
+	test_2d.path.bezierCurveTo.emptysubpath.html \
+	test_2d.path.bezierCurveTo.basic.html \
+	test_2d.path.bezierCurveTo.shape.html \
+	test_2d.path.bezierCurveTo.scaled.html \
+	test_2d.path.arc.empty.html \
+	test_2d.path.arc.nonempty.html \
+	test_2d.path.arc.end.html \
+	test_2d.path.arc.angle.1.html \
+	test_2d.path.arc.angle.2.html \
+	test_2d.path.arc.angle.3.html \
+	test_2d.path.arc.angle.4.html \
+	test_2d.path.arc.zero.1.html \
+	test_2d.path.arc.zero.2.html \
+	test_2d.path.arc.zero.3.html \
+	test_2d.path.arc.zero.4.html \
+	test_2d.path.arc.zero.5.html \
+	test_2d.path.arc.zero.6.html \
+	test_2d.path.arc.shape.1.html \
+	test_2d.path.arc.shape.2.html \
+	test_2d.path.arc.shape.3.html \
+	test_2d.path.arc.shape.4.html \
+	test_2d.path.arc.shape.5.html \
+	test_2d.path.arc.selfintersect.1.html \
+	test_2d.path.arc.selfintersect.2.html \
+	test_2d.path.arc.negative.html \
+	test_2d.path.arc.zero.html \
+	test_2d.path.rect.basic.html \
+	test_2d.path.rect.newsubpath.html \
+	test_2d.path.rect.closed.html \
+	test_2d.path.rect.end.1.html \
+	test_2d.path.rect.end.2.html \
+	test_2d.path.rect.zero.1.html \
+	test_2d.path.rect.zero.2.html \
+	test_2d.path.rect.zero.3.html \
+	test_2d.path.rect.zero.4.html \
+	test_2d.path.rect.zero.5.html \
+	test_2d.path.rect.negative.html \
+	test_2d.path.fill.winding.add.html \
+	test_2d.path.fill.winding.subtract.1.html \
+	test_2d.path.fill.winding.subtract.2.html \
+	test_2d.path.fill.winding.subtract.3.html \
+	test_2d.path.fill.closed.basic.html \
+	test_2d.path.fill.closed.unaffected.html \
+	test_2d.path.stroke.union.html \
+	test_2d.path.stroke.unaffected.html \
+	test_2d.path.transformation.basic.html \
+	test_2d.path.transformation.multiple.1.html \
+	test_2d.path.transformation.multiple.2.html \
+	test_2d.path.transformation.multiple.3.html \
+	test_2d.path.clip.empty.html \
+	test_2d.path.clip.basic.1.html \
+	test_2d.path.clip.basic.2.html \
+	test_2d.path.clip.intersect.html \
+	test_2d.path.clip.winding.1.html \
+	test_2d.path.clip.winding.2.html \
+	test_2d.path.clip.unaffected.html \
+	test_2d.path.isPointInPath.basic.1.html \
+	test_2d.path.isPointInPath.basic.2.html \
+	test_2d.path.isPointInPath.empty.html \
+	test_2d.path.isPointInPath.unclosed.html \
+	test_2d.path.isPointInPath.winding.html \
+	test_2d.path.isPointInPath.transform.1.html \
+	test_2d.path.isPointInPath.transform.2.html \
+	test_2d.path.isPointInPath.transform.3.html \
+	test_2d.drawImage.3arg.html \
+	test_2d.drawImage.5arg.html \
+	test_2d.drawImage.9arg.basic.html \
+	test_2d.drawImage.9arg.sourcepos.html \
+	test_2d.drawImage.9arg.sourcesize.html \
+	test_2d.drawImage.9arg.destpos.html \
+	test_2d.drawImage.9arg.destsize.html \
+	test_2d.drawImage.null.html \
+	test_2d.drawImage.wrongtype.html \
+	test_2d.drawImage.floatsource.html \
+	test_2d.drawImage.zerosource.html \
+	test_2d.drawImage.negativesource.html \
+	test_2d.drawImage.negativedest.html \
+	test_2d.drawImage.outsidesource.html \
+	test_2d.drawImage.incomplete.html \
+	test_2d.drawImage.broken.html \
+	test_2d.drawImage.path.html \
+	test_2d.drawImage.transform.html \
+	test_2d.drawImage.alpha.html \
+	test_2d.drawImage.clip.html \
+	test_2d.drawImage.composite.html \
+	test_2d.imageData.get.basic.html \
+	test_2d.imageData.get.sourcepos.html \
+	test_2d.imageData.get.values.html \
+	test_2d.imageData.get.sourcesize.html \
+	test_2d.imageData.get.properties.html \
+	test_2d.imageData.get.nonpremul.html \
+	test_2d.imageData.get.order.cols.html \
+	test_2d.imageData.get.order.rows.html \
+	test_2d.imageData.get.order.rgb.html \
+	test_2d.imageData.get.order.alpha.html \
+	test_2d.imageData.get.smallest.html \
+	test_2d.imageData.get.nonpositive.html \
+	test_2d.imageData.get.nonfinite.html \
+	test_2d.imageData.put.basic.html \
+	test_2d.imageData.put.alpha.html \
+	test_2d.imageData.put.modified.html \
+	test_2d.imageData.put.type.correct.html \
+	test_2d.imageData.put.type.onepixel.html \
+	test_2d.imageData.put.type.extra.html \
+	test_2d.imageData.put.type.missing.html \
+	test_2d.imageData.put.type.invalidsize.html \
+	test_2d.imageData.put.type.invalidvalues.html \
+	test_2d.imageData.put.unchanged.html \
+	test_2d.imageData.put.unaffected.html \
+	test_2d.imageData.put.path.html \
+	image_transparent50.png \
+	image_redtransparent.png \
+	image_yellow.png \
+	image_green-16x16.png \
+	image_red-16x16.png \
+	image_green-1x1.png \
+	image_ggrr-256x256.png \
+	image_yellow75.png \
+	image_broken.png \
+	image_rgrg-256x256.png \
+	image_red.png \
+	image_transparent.png \
+	image_green.png \
+	$(NULL)
+
+# This one test crashes Mac for now
+ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
+_TEST_FILES += \
+	test_2d.gradient.empty.html \
+	$(NULL)
+endif
+
+# Tests that fail on Mac (possibly because spec is underdefined?)
+ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
+_TEST_FILES += \
+	test_2d.line.cap.zerobezier.round.html \
+	test_2d.line.join.parallel.html \
+	test_2d.strokeRect.zero.5.html \
+	$(NULL)
+endif
+
+# Tests that fail on non-Mac (bug 401791)
+ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
+_TEST_FILES += \
+	test_2d.line.miter.rightangle.html \
+	test_2d.line.miter.lineedge.html \
+	$(NULL)
+endif
+
+# Tests that fail on non-Mac (still need bugs)
+ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
+_TEST_FILES += \
+	test_2d.path.rect.selfintersect.html \
+	test_2d.path.rect.zero.6.html \
+	$(NULL)
+endif
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f2581017b43d44664e7137a78c0803554b50f3b1
GIT binary patch
literal 87
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*$P6SW{C@KnNHGWagt-1^V32&oX%6J_d%8G=
RL|_3xIZszVmvv4FO#n416=47X
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0342e4a38425886d5fa9159fcfaa9a06093937e3
GIT binary patch
literal 120
zc%17D@N?(olHy`uVBq!ia0y~yU}OMcMrI(Dw#P~pNU;U@gt#*N2SSF6v%S^<MRYw~
z978hhy*;&&mw|zUdBMN`TjpIjxZ|J?6HxL)4ws_<3k<a+M_gU|;Su*ihhm@{gQu&X
J%Q~loCIHeqA{YPw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e19a3ffddd2567de2be00a9bcede541935d79bd0
GIT binary patch
literal 92
zc%17D@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;bAV5XE5m;VlehybfLswz7srr_
lxTyykfgFa01%FqjueiWqz`&@!Uu6kM$kWx&Wt~$(696W66?^~y
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..862d1dd10cc9f261e0b4df57902258a85b2e6f4b
GIT binary patch
literal 82
zc%17D@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga%mF?jt_=SfOyUl#0CKrJT^vI=
bWRnwsY$gWA^CwK70$B{6u6{1-oD!M<RL&6Z
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..28a1faab37797ef39454aa1deac1b470712f7be4
GIT binary patch
literal 87
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*$P6SW{C@KnNHGWagt#*NXE2F7umZ^C_jGX#
j(GX2ekYHV$kio>jw1<IF`tIWiKq&@KS3j3^P6<r_F*+3V
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9038fef784dacafdcfdce03fb12b90647bb52d2e
GIT binary patch
literal 130
zc%17D@N?(olHy`uVBq!ia0vp^0w65F1SAhIZYc#)oCO|{#X#BvjNMLV+kphj3LMj6
zsu^OAtvw86$a}gthFF|V{_}r+<Fba%ZO8hf46+WcU|lTM6XhVwz)-QAN$v@MVkA&0
NgQu&X%Q~loCIHXaAkY8+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a6e195d59cce3c15ef12512bb58ed4f409eb95ae
GIT binary patch
literal 87
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*$P6SW{C@KnNHGWagt-1^V32&oX%6J_d%8G=
jXow~!NU$zW$Y5e%+QYyoefRMMpcI3rtDnm{r-UW|6k!xK
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..75da08c3d6672e3db0a3fb43394edf42271e7175
GIT binary patch
literal 109
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*$P6SW{C@KnNU;U@gt#&=GyG>@h>8FH2`Iu?
z666=m;PC858jvIE>EaloaX$G6KO4J*Lc$dDQ_@B@3~Z|cQtGFs8~`d{@O1TaS?83{
F1ORLq9D)D<
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e6fba3daa5dfc788eaeedb73636e82abfedc8ae5
GIT binary patch
literal 131
zc%17D@N?(olHy`uVBq!ia0y~yU}OMcMrI(Dw#P~pNU;U@gt#*N2SSF6v%S^<MJzmB
z978hhy}h6)#K6FDc*EcSmmj2C#;jUAYvm=7ei)Ex)JNjkG_!VPet7g?k%<wA>*?y}
Jvd$@?2>{esAxZ!M
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2b498699a80d9189af3aad09ae9e530fe23ab069
GIT binary patch
literal 100
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*$P6SW{C@KnNHGWagt!9f<yE$~fD~g%kY6x^
u!?PP{Kn}mBi(`n!`Q!u%*2M`KObkqW7#MRW$(8`67(8A5T-G@yGywoa#TVWH
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..55f8e69325bc61ff83f769a6524f7f9c3310be1f
GIT binary patch
literal 155
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*!3HE(nbz$CQc0dJjv*Dd-d;3hWH8`3a$xzf
ziF{&KMlmW+vL^MN`=Z03q~O59($T;mD4@VZ2K&oxrrKi0N1NE}*nze&c)I$ztaD0e
F0st6CB*y>%
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..51e8aaf38c1b3a105fc6038c93b5648a4bf9efd4
GIT binary patch
literal 95
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*$P6SW{C@KnNHGWagt-3y&(L-3iz|>T?&;zf
qQW5v|03$Du=V0(R_;h0NA~Qy&Jq(P_g*_*Mf()LnelF{r5}E*PXBuY!
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2bb82c9834790bfeb1a65cf2ef202dc63d2ebac4
GIT binary patch
literal 150
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*!3HE(nbz$CQn8*cjv*CsZ!a1$GB9v3E4-CI
zm9e>LIeW;0$+N1Oi#eQH6j&6U1eBlzhhUQclyK}2Xn_(SRW48huGC535EDadr|fHi
R#BiWR44$rjF6*2Ung9_VBQpR1
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.canvas.readonly.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.canvas.readonly</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var c = document.createElement('canvas');
+var d = ctx.canvas;
+try { ctx.canvas = c; } catch (e) {} // not specified whether this throws, I think
+ok(ctx.canvas === d, "ctx.canvas === d");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.canvas.reference.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.canvas.reference</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ok(ctx.canvas === canvas, "ctx.canvas === canvas");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.basic.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.basic</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.clip.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.clip</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(0, 0, 16, 16);
+ctx.clip();
+
+ctx.clearRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 16, 16);
+
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.globalalpha.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.globalalpha</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.1;
+ctx.clearRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.globalcomposite.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.globalcomposite</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.clearRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.path.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.path</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.rect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 16, 16);
+ctx.fill();
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.shadow</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#f00';
+ctx.shadowBlur = 0;
+ctx.shadowOffsetX = 0;
+ctx.shadowOffsetY = 50;
+ctx.clearRect(0, -50, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.transform.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.transform</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.scale(10, 10);
+ctx.translate(0, 5);
+ctx.clearRect(0, -5, 10, 5);
+isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.zero.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.zero</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 100, 0);
+ctx.clearRect(0, 0, 0, 50);
+ctx.clearRect(0, 0, 0, 0);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.globalAlpha.canvas.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.globalAlpha.canvas</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.drawImage(canvas2, 0, 0);
+isPixel(ctx, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.globalAlpha.canvaspattern.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.globalAlpha.canvaspattern</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+function todo_isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    isPixel(ctx, x,y, r,g,b,a, pos, colour, d, todo);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = ctx.createPattern(canvas2, 'no-repeat');
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.fillRect(0, 0, 100, 50);
+todo_isPixel(ctx, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.globalAlpha.default.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.globalAlpha.default</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ok(ctx.globalAlpha === 1.0, "ctx.globalAlpha === 1.0");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.globalAlpha.fill.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.globalAlpha.fill</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.globalAlpha.image.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.globalAlpha.image</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+isPixel(ctx, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.globalAlpha.imagepattern.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.globalAlpha.imagepattern</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+function todo_isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    isPixel(ctx, x,y, r,g,b,a, pos, colour, d, todo);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = ctx.createPattern(document.getElementById('red.png'), 'no-repeat');
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.fillRect(0, 0, 100, 50);
+todo_isPixel(ctx, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.globalAlpha.range.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.globalAlpha.range</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.globalAlpha = 0.5;
+var a = ctx.globalAlpha; // might not be exactly 0.5, if it is rounded/quantised, so remember for future comparisons
+ctx.globalAlpha = 1.1;
+ok(ctx.globalAlpha == a, "ctx.globalAlpha == a");
+ctx.globalAlpha = -0.1;
+ok(ctx.globalAlpha == a, "ctx.globalAlpha == a");
+ctx.globalAlpha = 0;
+ok(ctx.globalAlpha == 0, "ctx.globalAlpha == 0");
+ctx.globalAlpha = 1;
+ok(ctx.globalAlpha == 1, "ctx.globalAlpha == 1");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.copy.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.copy</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 255,255,0,191, "50,25", "255,255,0,191", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.destination-atop.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.destination-atop</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 127,255,127,191, "50,25", "127,255,127,191", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.destination-in.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.destination-in</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 0,255,255,95, "50,25", "0,255,255,95", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.destination-out.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.destination-out</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 0,255,255,31, "50,25", "0,255,255,31", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.destination-over.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.destination-over</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 109,255,145,223, "50,25", "109,255,145,223", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.lighter.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.lighter</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 191,255,127,255, "50,25", "191,255,127,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.source-atop.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.source-atop</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 191,255,63,127, "50,25", "191,255,63,127", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.source-in.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.source-in</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 255,255,0,95, "50,25", "255,255,0,95", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.source-out.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.source-out</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 255,255,0,95, "50,25", "255,255,0,95", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.source-over.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.source-over</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 218,255,36,223, "50,25", "218,255,36,223", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.image.xor.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.image.xor</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+isPixel(ctx, 50,25, 191,255,63,127, "50,25", "191,255,63,127", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.operation.clear.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.operation.clear</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'clear';
+todo(ctx.globalCompositeOperation == 'xor', "ctx.globalCompositeOperation == 'xor'");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.operation.darker.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.operation.darker</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'darker';
+todo(ctx.globalCompositeOperation == 'xor', "ctx.globalCompositeOperation == 'xor'");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.operation.default.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.operation.default</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ok(ctx.globalCompositeOperation == 'source-over', "ctx.globalCompositeOperation == 'source-over'");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.operation.get.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.operation.get</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var modes = ['source-atop', 'source-in', 'source-out', 'source-over',
+    'destination-atop', 'destination-in', 'destination-out', 'destination-over',
+    'lighter', 'copy', 'xor'];
+for (var i = 0; i < modes.length; ++i)
+{
+    ctx.globalCompositeOperation = modes[i];
+    ok(ctx.globalCompositeOperation == modes[i], "ctx.globalCompositeOperation == modes[\""+(i)+"\"]");
+}
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.operation.over.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.operation.over</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'over';
+todo(ctx.globalCompositeOperation == 'xor', "ctx.globalCompositeOperation == 'xor'");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.copy.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.copy</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.destination-atop.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.destination-atop</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,255,255, "50,25", "0,255,255,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.destination-in.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.destination-in</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,255,255, "50,25", "0,255,255,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.destination-out.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.destination-out</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.destination-over.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.destination-over</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,255,255, "50,25", "0,255,255,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.lighter.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.lighter</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 255,255,255,255, "50,25", "255,255,255,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.source-atop.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.source-atop</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.source-in.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.source-in</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.source-out.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.source-out</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.solid.source-over.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.solid.source-over</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.copy.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.copy</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,255,191, "50,25", "0,0,255,191", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.destination-atop.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.destination-atop</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,127,127,191, "50,25", "0,127,127,191", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.destination-in.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.destination-in</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,95, "50,25", "0,255,0,95", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.destination-out.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.destination-out</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,31, "50,25", "0,255,0,31", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.destination-over.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.destination-over</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,145,109,223, "50,25", "0,145,109,223", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.lighter.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.lighter</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,127,191,255, "50,25", "0,127,191,255", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.source-atop.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.source-atop</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,63,191,127, "50,25", "0,63,191,127", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.source-in.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.source-in</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,255,95, "50,25", "0,0,255,95", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.source-out.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.source-out</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,0,255,95, "50,25", "0,0,255,95", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.source-over.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.source-over</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,36,218,223, "50,25", "0,36,218,223", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.transparent.xor.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.transparent.xor</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,63,191,127, "50,25", "0,63,191,127", 5);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.3arg.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.3arg</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.drawImage(document.getElementById('green.png'), 0, 0);
+ctx.drawImage(document.getElementById('red.png'), -100, 0);
+ctx.drawImage(document.getElementById('red.png'), 100, 0);
+ctx.drawImage(document.getElementById('red.png'), 0, -50);
+ctx.drawImage(document.getElementById('red.png'), 0, 50);
+
+isPixel(ctx, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+isPixel(ctx, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+isPixel(ctx, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+isPixel(ctx, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+<img src="image_green.png" id="green.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.5arg.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.5arg</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 50, 0, 50, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 50, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50);
+
+isPixel(ctx, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+isPixel(ctx, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+isPixel(ctx, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+isPixel(ctx, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+<img src="image_green.png" id="green.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.9arg.basic.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.9arg.basic</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50);
+isPixel(ctx, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+isPixel(ctx, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+isPixel(ctx, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+isPixel(ctx, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_green.png" id="green.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.9arg.destpos.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.9arg.destpos</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -100, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -50, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 50);
+isPixel(ctx, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+isPixel(ctx, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+isPixel(ctx, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+isPixel(ctx, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+<img src="image_green.png" id="green.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.9arg.destsize.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.9arg.destsize</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 1, 1, 1, 1, 0, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -50, 0, 50, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 50, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -25, 100, 25);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 25);
+isPixel(ctx, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+isPixel(ctx, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+isPixel(ctx, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+isPixel(ctx, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+<img src="image_green.png" id="green.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.9arg.sourcepos.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.9arg.sourcepos</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('rgrg-256x256.png'), 140, 20, 100, 50, 0, 0, 100, 50);
+isPixel(ctx, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+isPixel(ctx, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+isPixel(ctx, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+isPixel(ctx, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_rgrg-256x256.png" id="rgrg-256x256.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.9arg.sourcesize.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.9arg.sourcesize</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('rgrg-256x256.png'), 0, 0, 256, 256, 0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 51, 26);
+ctx.fillRect(49, 24, 51, 26);
+isPixel(ctx, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+isPixel(ctx, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+isPixel(ctx, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+isPixel(ctx, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+isPixel(ctx, 20,20, 0,255,0,255, "20,20", "0,255,0,255", 2);
+isPixel(ctx, 80,20, 0,255,0,255, "80,20", "0,255,0,255", 2);
+isPixel(ctx, 20,30, 0,255,0,255, "20,30", "0,255,0,255", 2);
+isPixel(ctx, 80,30, 0,255,0,255, "80,30", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_rgrg-256x256.png" id="rgrg-256x256.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.alpha.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.alpha</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0;
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.broken.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.broken</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var img = document.getElementById('broken.png');
+todo(img.complete === false, "img.complete === false");
+var _thrown = undefined; try {
+  ctx.drawImage(img, 0, 0);
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw INVALID_STATE_ERR");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_broken.png" id="broken.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.clip.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.clip</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.rect(-10, -10, 1, 1);
+ctx.clip();
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.composite.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.composite</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.floatsource.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.floatsource</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.drawImage(document.getElementById('green.png'), 10.1, 10.1, 0.1, 0.1, 0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_green.png" id="green.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.incomplete.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.incomplete</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var img = new Image();
+todo(img.complete === false, "img.complete === false");
+var _thrown = undefined; try {
+  ctx.drawImage(img, 0, 0);
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw INVALID_STATE_ERR");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.negativedest.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.negativedest</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), 10, 10, 1, 1, 0, 50, -100, 50);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), 10, 10, 1, 1, 0, 50, 100, -50);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.negativesource.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.negativesource</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), 10, 10, -1, 1, 0, 0, 100, 50);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.null.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.null</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var _thrown = undefined; try {
+  ctx.drawImage(null, 0, 0);
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.outsidesource.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.outsidesource</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+function todo_isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    isPixel(ctx, x,y, r,g,b,a, pos, colour, d, todo);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.drawImage(document.getElementById('green.png'), 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50);
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), -0.001, 0, 100, 50, 0, 0, 100, 50);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), 0, -0.001, 100, 50, 0, 0, 100, 50);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), 0, 0, 100.001, 50, 0, 0, 100, 50);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50.001, 0, 0, 100, 50);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage(document.getElementById('red.png'), 50, 0, 50.001, 50, 0, 0, 100, 50);
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+todo_isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_green.png" id="green.png" class="resource">
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.path.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.path</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.rect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ctx.fill();
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.transform.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.transform</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.translate(100, 0);
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_red.png" id="red.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.wrongtype.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.wrongtype</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var _thrown = undefined; try {
+  ctx.drawImage(undefined, 0, 0);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage(0, 0, 0);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage("", 0, 0);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
+var _thrown = undefined; try {
+  ctx.drawImage(document.createElement('p'), 0, 0);
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.zerosource.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.zerosource</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+function todo_isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    isPixel(ctx, x,y, r,g,b,a, pos, colour, d, todo);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 10, 10, 0, 1, 0, 0, 30, 50);
+ctx.drawImage(document.getElementById('green.png'), 10, 10, 1, 0, 30, 0, 40, 50);
+ctx.drawImage(document.getElementById('green.png'), 10, 10, 0, 0, 70, 0, 30, 50);
+todo_isPixel(ctx, 15,25, 0,255,0,255, "15,25", "0,255,0,255", 2);
+todo_isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+todo_isPixel(ctx, 85,25, 0,255,0,255, "85,25", "0,255,0,255", 2);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+<img src="image_green.png" id="green.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillRect.basic.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillRect.basic</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillRect.clip.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillRect.clip</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(0, 0, 16, 16);
+ctx.clip();
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 16, 16);
+
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillRect.negative.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillRect.negative</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var _thrown = undefined; try {
+  ctx.fillRect(0, 0, -1, 1);
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+var _thrown = undefined; try {
+  ctx.fillRect(0, 0, 1, -1);
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillRect.path.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillRect.path</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.beginPath();
+ctx.rect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 16, 16);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillRect.shadow.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillRect.shadow</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.shadowBlur = 0;
+ctx.shadowOffsetX = 0;
+ctx.shadowOffsetY = 50;
+
+// Shadows are optional, so just test that if they apply to fill() then they apply to fillRect() too
+ctx.beginPath();
+ctx.rect(0, -50, 100, 50);
+ctx.shadowColor = '#f00';
+ctx.fill();
+
+ctx.shadowColor = '#0f0';
+ctx.fillRect(0, -50, 100, 50);
+
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillRect.transform.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillRect.transform</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.scale(10, 10);
+ctx.translate(0, 5);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, -5, 10, 5);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillRect.zero.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillRect.zero</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 0);
+ctx.fillRect(0, 0, 0, 50);
+ctx.fillRect(0, 0, 0, 0);
+isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.default.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.default</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ok(ctx.fillStyle == '#000000', "ctx.fillStyle == '#000000'");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.get.semitransparent.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.get.semitransparent</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'rgba(255,255,255,0.45)';
+ok(ctx.fillStyle =~ /^rgba\(255, 255, 255, 0\.4\d+\)$/, "ctx.fillStyle =~ /^rgba\\(255, 255, 255, 0\\.4\\d+\\)$/");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.get.solid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.get.solid</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#fa0';
+ok(ctx.fillStyle === '#ffaa00', "ctx.fillStyle === '#ffaa00'");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.get.transparent.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.get.transparent</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'rgba(0,0,0,0)';
+ok(ctx.fillStyle == 'rgba(0, 0, 0, 0.0)', "ctx.fillStyle == 'rgba(0, 0, 0, 0.0)'");
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.invalidstring.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.invalidstring</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillStyle = 'invalid';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.invalidtype.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.invalidtype</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillStyle = null;
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.flavor.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.flavor</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'flavor';
+ok(ctx.fillStyle =~ /^#(?!(FF0000|ff0000|f00)$)/, "ctx.fillStyle =~ /^#(?!(FF0000|ff0000|f00)$)/"); // test that it's not red
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hex3.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hex3</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hex6.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hex6</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = '#00fF00';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hsl-1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hsl-1</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120, 100%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hsl-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hsl-2</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(-240, 100%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hsl-3.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hsl-3</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(360120, 100%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hsl-4.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hsl-4</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(-360240, 100%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hsl-5.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hsl-5</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120.0, 100.0%, 50.0%)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hsla-1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hsla-1</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, 100%, 50%, 0.499)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,127, "50,25", "0,255,0,127", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.hsla-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.hsla-2</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120.0, 100.0%, 50.0%, 1)';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.html4.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.html4</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'limE';
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.hex3.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex3</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#g00'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.hex6.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex6</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#fg0000'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-1</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0%, 100%, 50%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-2</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(z, 100%, 50%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-3.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-3</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0, 0, 50%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.hsl-4.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-4</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0, 100%, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-1</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255.0, 0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-2</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255, 0.0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-3.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-3</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    (f || ok)(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255.0, 0, 0,)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+if (!_deferred) SimpleTest.finish();
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fillStyle.parse.invalid.rgb-4.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-4</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+var _deferred = false;
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+