summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/2dcontext/tools/tests.yaml
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/2dcontext/tools/tests.yaml')
-rw-r--r--testing/web-platform/tests/2dcontext/tools/tests.yaml1068
1 files changed, 1068 insertions, 0 deletions
diff --git a/testing/web-platform/tests/2dcontext/tools/tests.yaml b/testing/web-platform/tests/2dcontext/tools/tests.yaml
new file mode 100644
index 000000000..083dfd1bd
--- /dev/null
+++ b/testing/web-platform/tests/2dcontext/tools/tests.yaml
@@ -0,0 +1,1068 @@
+# Copyright (c) 2010 Philip Taylor
+# Released under the BSD license and W3C Test Suite License: see LICENSE.txt
+
+- name: fallback.basic
+ desc: Fallback content is inserted into the DOM
+ testing:
+ - fallback
+ code: |
+ @assert canvas.childNodes.length === 1;
+
+- name: fallback.multiple
+ desc: Fallback content with multiple elements
+ testing:
+ - fallback
+ fallback: '<p class="fallback">FAIL</p><p class="fallback">FAIL</p>'
+ code: |
+ @assert canvas.childNodes.length === 2;
+
+- name: fallback.nested
+ desc: Fallback content containing another canvas (mostly testing parsers)
+ testing:
+ - fallback
+ fallback: '<canvas><p class="fallback">FAIL (fallback content)</p></canvas><p class="fallback">FAIL (fallback content)</p>'
+ code: |
+ @assert canvas.childNodes.length === 2;
+
+- name: type.name
+ desc: HTMLCanvasElement type and toString
+ testing:
+ - canvas.type
+ code: |
+ @assert Object.prototype.toString.call(canvas) === '[object HTMLCanvasElement]';
+
+- name: type.exists
+ desc: HTMLCanvasElement is a property of window
+ notes: &bindings Defined in "Web IDL" (draft)
+ testing:
+ - canvas.type
+ code: |
+ @assert window.HTMLCanvasElement;
+
+- name: type.delete
+ desc: window.HTMLCanvasElement interface object is [[Configurable]]
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ @assert delete window.HTMLCanvasElement === true;
+ @assert window.HTMLCanvasElement === undefined;
+
+- name: type.prototype
+ desc: window.HTMLCanvasElement has prototype, which is { ReadOnly, DontDelete }. prototype has getContext, which is not
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ @assert window.HTMLCanvasElement.prototype;
+ @assert window.HTMLCanvasElement.prototype.getContext;
+ window.HTMLCanvasElement.prototype = null;
+ @assert window.HTMLCanvasElement.prototype;
+ delete window.HTMLCanvasElement.prototype;
+ @assert window.HTMLCanvasElement.prototype;
+ window.HTMLCanvasElement.prototype.getContext = 1;
+ @assert window.HTMLCanvasElement.prototype.getContext === 1;
+ delete window.HTMLCanvasElement.prototype.getContext;
+ @assert window.HTMLCanvasElement.prototype.getContext === undefined;
+
+- name: type.replace
+ desc: HTMLCanvasElement methods can be replaced, and the replacement methods used by canvases
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ window.HTMLCanvasElement.prototype.getContext = function (name) { return 0; };
+ @assert canvas.getContext('2d') === 0;
+
+- name: type.extend
+ desc: HTMLCanvasElement methods can be added, and the new methods used by canvases
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ window.HTMLCanvasElement.prototype.getZero = function () { return 0; };
+ @assert canvas.getZero() === 0;
+
+
+- name: size.attributes.idl.set.zero
+ desc: Setting width/height IDL attributes to 0
+ testing:
+ - size.width
+ - size.height
+ code: |
+ canvas.width = 0;
+ canvas.height = 0;
+ @assert canvas.width === 0;
+ @assert canvas.height === 0;
+# expected: size 0 0 # can't generate zero-sized PNG
+
+- name: size.attributes.idl
+ desc: Getting/setting width/height IDL attributes
+ testing:
+ - size.width
+ - size.height
+ webidl:
+ - es-unsigned-long
+ code: |
+ canvas.width = "100";
+ canvas.height = "100";
+ @assert canvas.width === 100;
+ @assert canvas.height === 100;
+
+ canvas.width = "+1.5e2";
+ canvas.height = "0x96";
+ @assert canvas.width === 150;
+ @assert canvas.height === 150;
+
+ canvas.width = 200 - Math.pow(2, 32);
+ canvas.height = 200 - Math.pow(2, 32);
+ @assert canvas.width === 200;
+ @assert canvas.height === 200;
+
+ canvas.width = 301.999;
+ canvas.height = 301.001;
+ @assert canvas.width === 301;
+ @assert canvas.height === 301;
+
+ canvas.width = "400x";
+ canvas.height = "foo";
+ @assert canvas.width === 0;
+ @assert canvas.height === 0;
+
+- name: size.attributes.default
+ desc: Default width/height when attributes are missing
+ testing:
+ - size.default
+ - size.missing
+ canvas: ""
+ code: |
+ @assert canvas.width === 300;
+ @assert canvas.height === 150;
+ @assert !canvas.hasAttribute('width');
+ @assert !canvas.hasAttribute('height');
+ expected: size 300 150
+
+- name: size.attributes.reflect.setidl
+ desc: Setting IDL attributes updates IDL and content attributes
+ testing:
+ - size.reflect
+ code: |
+ canvas.width = 120;
+ canvas.height = 60;
+ @assert canvas.getAttribute('width') === '120';
+ @assert canvas.getAttribute('height') === '60';
+ @assert canvas.width === 120;
+ @assert canvas.height === 60;
+ expected: size 120 60
+
+- name: size.attributes.reflect.setidlzero
+ desc: Setting IDL attributes to 0 updates IDL and content attributes
+ testing:
+ - size.reflect
+ code: |
+ canvas.width = 0;
+ canvas.height = 0;
+ @assert canvas.getAttribute('width') === '0';
+ @assert canvas.getAttribute('height') === '0';
+ @assert canvas.width === 0;
+ @assert canvas.height === 0;
+# expected: size 0 0 # can't generate zero-sized PNG
+
+- name: size.attributes.reflect.setcontent
+ desc: Setting content attributes updates IDL and content attributes
+ testing:
+ - size.reflect
+ code: |
+ canvas.setAttribute('width', '120');
+ canvas.setAttribute('height', '60');
+ @assert canvas.getAttribute('width') === '120';
+ @assert canvas.getAttribute('height') === '60';
+ @assert canvas.width === 120;
+ @assert canvas.height === 60;
+ expected: size 120 60
+
+- name: size.attributes.removed
+ desc: Removing content attributes reverts to default size
+ testing:
+ - size.missing
+ canvas: width="120" height="60"
+ code: |
+ @assert canvas.width === 120;
+ canvas.removeAttribute('width');
+ @assert canvas.width === 300;
+ expected: size 300 60
+
+- meta: |
+ cases = [
+ ("zero", "0", 0),
+ ("empty", "", None),
+ ("onlyspace", " ", None),
+ ("space", " 100", 100),
+ ("whitespace", "\n\t\f100", 100),
+ ("plus", "+100", 100),
+ ("minus", "-100", None),
+ ("octal", "0100", 100),
+ ("hex", "0x100", 0),
+ ("exp", "100e1", 100),
+ ("decimal", "100.999", 100),
+ ("percent", "100%", 100),
+ ("em", "100em", 100),
+ ("junk", "#!?", None),
+ ("trailingjunk", "100#!?", 100),
+ ]
+ def gen(name, string, exp, code):
+ testing = ["size.nonnegativeinteger"]
+ if exp is None:
+ testing.append("size.error")
+ code += "@assert canvas.width === 300;\n@assert canvas.height === 150;\n"
+ expected = "size 300 150"
+ else:
+ code += "@assert canvas.width === %s;\n@assert canvas.height === %s;\n" % (exp, exp)
+ expected = "size %s %s" % (exp, exp)
+
+ # With "100%", Opera gets canvas.width = 100 but renders at 100% of the frame width,
+ # so check the CSS display width
+ code += '@assert window.getComputedStyle(canvas, null).getPropertyValue("width") === "%spx";\n' % (exp, )
+
+ code += "@assert canvas.getAttribute('width') === %r;\n" % string
+ code += "@assert canvas.getAttribute('height') === %r;\n" % string
+
+ if exp == 0:
+ expected = None # can't generate zero-sized PNGs for the expected image
+
+ return code, testing, expected
+
+ for name, string, exp in cases:
+ code = ""
+ code, testing, expected = gen(name, string, exp, code)
+ tests.append( {
+ "name": "size.attributes.parse.%s" % name,
+ "desc": "Parsing of non-negative integers",
+ "testing": testing,
+ "canvas": 'width="%s" height="%s"' % (string, string),
+ "code": code,
+ "expected": expected
+ } )
+
+ for name, string, exp in cases:
+ code = "canvas.setAttribute('width', %r);\ncanvas.setAttribute('height', %r);\n" % (string, string)
+ code, testing, expected = gen(name, string, exp, code)
+ tests.append( {
+ "name": "size.attributes.setAttribute.%s" % name,
+ "desc": "Parsing of non-negative integers in setAttribute",
+ "testing": testing,
+ "canvas": 'width="50" height="50"',
+ "code": code,
+ "expected": expected
+ } )
+
+- name: size.attributes.style
+ desc: Canvas size is independent of CSS resizing
+ testing:
+ - size.css
+ canvas: 'width="50" height="30" style="width: 100px; height: 50px"'
+ code: |
+ @assert canvas.width === 50;
+ @assert canvas.height === 30;
+ expected: size 100 50
+
+- name: size.large
+ DISABLED: |
+ "User agents may impose implementation-specific limits on otherwise unconstrained
+ inputs, e.g. to prevent denial of service attacks, to guard against running out of memory,
+ or to work around platform-specific limitations."
+ testing:
+ - size.width
+ - size.height
+ notes: Not sure how reasonable this is, but the spec doesn't say there's an upper limit on the size.
+ code: |
+ var n = 2147483647; // 2^31 - 1, which should be supported by any sensible definition of "long"
+ canvas.width = n;
+ canvas.height = n;
+ @assert canvas.width === n;
+ @assert canvas.height === n;
+# expected: size 2147483647 2147483647 # not a good idea to generate the expected image in this case...
+
+- name: initial.colour
+ desc: Initial state is transparent black
+ testing:
+ - initial.colour
+ notes: |
+ Output should be transparent black (not transparent anything-else), but manual
+ verification can only confirm that it's transparent - it's not possible to make
+ the actual blackness visible.
+ code: |
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 100 50 # transparent
+
+- name: initial.reset.different
+ desc: Changing size resets canvas to transparent black
+ testing:
+ - initial.reset
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ @assert pixel 20,20 == 255,0,0,255;
+ canvas.width = 50;
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 50 50 # transparent
+
+- name: initial.reset.same
+ desc: Setting size (not changing the value) resets canvas to transparent black
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ @assert pixel 20,20 == 255,0,0,255;
+ canvas.width = 100;
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 100 50 # transparent
+
+- name: initial.reset.path
+ desc: Resetting the canvas state resets the current path
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.rect(0, 0, 100, 50);
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fill();
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 100 50 # transparent
+
+- name: initial.reset.clip
+ desc: Resetting the canvas state resets the current clip region
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.rect(0, 0, 1, 1);
+ ctx.clip();
+ canvas.width = 100;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 20,20 == 0,255,0,255;
+ expected: green
+
+- name: initial.reset.transform
+ desc: Resetting the canvas state resets the current transformation matrix
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.scale(0.1, 0.1);
+ canvas.width = 100;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 20,20 == 0,255,0,255;
+ expected: green
+
+- name: initial.reset.gradient
+ desc: Resetting the canvas state does not invalidate any existing gradients
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 50;
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#0f0');
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: initial.reset.pattern
+ desc: Resetting the canvas state does not invalidate any existing patterns
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 30;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 30, 50);
+ var p = ctx.createPattern(canvas, 'repeat-x');
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = p;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+# See tests2d.yaml for initial.reset.2dstate
+
+
+- name: context.emptystring
+ desc: getContext with empty string returns null
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("") === null;
+
+- name: context.unrecognised.badname
+ desc: getContext with unrecognised context name returns null
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext('This is not an implemented context in any real browser') === null;
+
+- name: context.unrecognised.badsuffix
+ desc: Context name "2d" plus a suffix is unrecognised
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("2d#") === null;
+
+- name: context.unrecognised.nullsuffix
+ desc: Context name "2d" plus a "\0" suffix is unrecognised
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("2d\0") === null;
+
+- name: context.unrecognised.unicode
+ desc: Context name which kind of looks like "2d" is unrecognised
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("2\uFF44") === null; // Fullwidth Latin Small Letter D
+
+- name: context.casesensitive
+ desc: Context name "2D" is unrecognised; matching is case sensitive
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext('2D') === null;
+
+- name: context.arguments.missing
+ notes: *bindings
+ testing:
+ - canvas.getContext
+ code: |
+ @assert throws TypeError canvas.getContext(); @moz-todo
+
+
+
+- name: toBlob.png
+ desc: toBlob with image/png returns a PNG Blob
+ testing:
+ - toBlob.png
+ code: |
+ canvas.toBlob(function(data){
+ @assert data.type === "image/png";
+ }, 'image/png');
+
+- name: toBlob.jpeg
+ desc: toBlob with image/jpeg returns a JPEG Blob
+ testing:
+ - toBlob.jpeg
+ code: |
+ canvas.toBlob(function(data){
+ @assert data.type === "image/jpeg";
+ }, 'image/jpeg');
+
+- name: toDataURL.default
+ desc: toDataURL with no arguments returns a PNG
+ testing:
+ - toDataURL.noarguments
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.png
+ desc: toDataURL with image/png returns a PNG
+ testing:
+ - toDataURL.png
+ - toDataURL.witharguments
+ code: |
+ var data = canvas.toDataURL('image/png');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.jpg
+ desc: toDataURL with image/jpg is invalid type hence returns a PNG
+ testing:
+ - toDataURL.jpg
+ - toDataURL.witharguments
+ code: |
+ var data = canvas.toDataURL('image/jpg');
+ @assert data =~ /^data:image\/png[;,]/;
+
+
+- name: toDataURL.bogustype
+ desc: toDataURL with a syntactically invalid type returns a PNG
+ testing:
+ - toDataURL.unrecognised
+ code: |
+ var data = canvas.toDataURL('bogus');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.unrecognised
+ desc: toDataURL with an unhandled type returns a PNG
+ testing:
+ - toDataURL.unrecognised
+ code: |
+ var data = canvas.toDataURL('image/example');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.lowercase.ascii
+ desc: toDataURL type is case-insensitive
+ testing:
+ - toDataURL.lowercase
+ code: |
+ var data = canvas.toDataURL('ImAgE/PnG');
+ @assert data =~ /^data:image\/png[;,]/;
+
+ // If JPEG is supported at all, it must be supported case-insensitively
+ data = canvas.toDataURL('image/jpeg');
+ if (data.match(/^data:image\/jpeg[;,]/)) {
+ data = canvas.toDataURL('ImAgE/JpEg');
+ @assert data =~ /^data:image\/jpeg[;,]/;
+ }
+
+- name: toDataURL.lowercase.unicode
+ desc: toDataURL type is ASCII-case-insensitive
+ testing:
+ - toDataURL.lowercase
+ code: |
+ // Use LATIN CAPITAL LETTER I WITH DOT ABOVE (Unicode lowercase is "i")
+ var data = canvas.toDataURL('\u0130mage/png');
+ @assert data =~ /^data:image\/png[;,]/;
+
+ var data = canvas.toDataURL('\u0130mage/jpeg');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.arguments.1
+ desc: toDataURL ignores extra arguments
+ testing:
+ - toDataURL.arguments
+ code: |
+ var data = canvas.toDataURL('image/png', 'another argument that should not raise an exception');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.arguments.2
+ desc: toDataURL ignores extra arguments
+ testing:
+ - toDataURL.arguments
+ code: |
+ var data = canvas.toDataURL('image/png', 'another argument that should not raise an exception', 'and another');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.arguments.3
+ desc: toDataURL ignores extra arguments
+ testing:
+ - toDataURL.arguments
+ code: |
+ // More arguments that should not raise exceptions
+ var data = canvas.toDataURL('image/png', null, null, null);
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.nocontext
+ desc: toDataURL works before any context has been got
+ testing:
+ - toDataURL.noarguments
+ code: |
+ var canvas2 = document.createElement('canvas');
+ var data = canvas2.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.zerosize
+ desc: toDataURL on zero-size canvas returns 'data:,'
+ testing:
+ - toDataURL.zerosize
+ canvas: width="0" height="0"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data === 'data:,';
+
+- name: toDataURL.zerowidth
+ desc: toDataURL on zero-size canvas returns 'data:,'
+ testing:
+ - toDataURL.zerosize
+ canvas: width="0"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data === 'data:,';
+
+- name: toDataURL.zeroheight
+ desc: toDataURL on zero-size canvas returns 'data:,'
+ testing:
+ - toDataURL.zerosize
+ canvas: height="0"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data === 'data:,';
+
+- name: toDataURL.large1
+ DISABLED: just testing implementation limits, and tends to crash
+ canvas: width="30000" height="1"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.large2
+ DISABLED: just testing implementation limits, and tends to crash
+ canvas: width="32767" height="1"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.large3
+ DISABLED: just testing implementation limits, and tends to crash
+ canvas: width="32768" height="1"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.png.primarycolours
+ desc: toDataURL with PNG handles simple colours correctly
+ testing:
+ - toDataURL.png
+ code: |
+ ctx.fillStyle = '#ff0';
+ ctx.fillRect(0, 0, 25, 40);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(25, 0, 50, 40);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(75, 0, 25, 40);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(0, 40, 100, 10);
+ var data = canvas.toDataURL();
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 12,20 == 255,255,0,255;
+ @assert pixel 50,20 == 0,255,255,255;
+ @assert pixel 87,20 == 0,0,255,255;
+ @assert pixel 50,45 == 255,255,255,255;
+ });
+ img.src = data;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(1, 1, 0)
+ cr.rectangle(0, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(25, 0, 50, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(75, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(1, 1, 1)
+ cr.rectangle(0, 40, 100, 10)
+ cr.fill()
+
+- name: toDataURL.png.complexcolours
+ desc: toDataURL with PNG handles non-primary and non-solid colours correctly
+ testing:
+ - toDataURL.png
+ code: |
+ // (These values are chosen to survive relatively alright through being premultiplied)
+ ctx.fillStyle = 'rgba(1, 3, 254, 1)';
+ ctx.fillRect(0, 0, 25, 25);
+ ctx.fillStyle = 'rgba(8, 252, 248, 0.75)';
+ ctx.fillRect(25, 0, 25, 25);
+ ctx.fillStyle = 'rgba(6, 10, 250, 0.502)';
+ ctx.fillRect(50, 0, 25, 25);
+ ctx.fillStyle = 'rgba(12, 16, 244, 0.25)';
+ ctx.fillRect(75, 0, 25, 25);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 25);
+ // (The alpha values do not really survive float->int conversion, so just
+ // do approximate comparisons)
+ @assert pixel 12,40 == 1,3,254,255;
+ @assert pixel 37,40 ==~ 8,252,248,191 +/- 2;
+ @assert pixel 62,40 ==~ 6,10,250,127 +/- 4;
+ @assert pixel 87,40 ==~ 12,16,244,63 +/- 8;
+ });
+ img.src = canvas.toDataURL();
+ expected: |
+ size 100 50
+ cr.set_source_rgba(1/255., 3/255., 254/255., 1)
+ cr.rectangle(0, 0, 25, 50)
+ cr.fill()
+ cr.set_source_rgba(8/255., 252/255., 248/255., 191/255.)
+ cr.rectangle(25, 0, 25, 50)
+ cr.fill()
+ cr.set_source_rgba(6/255., 10/255., 250/255., 127/255.)
+ cr.rectangle(50, 0, 25, 50)
+ cr.fill()
+ cr.set_source_rgba(12/255., 16/255., 244/255., 63/255.)
+ cr.rectangle(75, 0, 25, 50)
+ cr.fill()
+
+- name: toDataURL.jpeg.primarycolours
+ desc: toDataURL with JPEG handles simple colours correctly
+ testing:
+ - toDataURL.jpeg
+ code: |
+ ctx.fillStyle = '#ff0';
+ ctx.fillRect(0, 0, 25, 40);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(25, 0, 50, 40);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(75, 0, 25, 40);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(0, 40, 100, 10);
+ var data = canvas.toDataURL('image/jpeg'); // it is okay if this returns a PNG instead
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 12,20 ==~ 255,255,0,255 +/- 8;
+ @assert pixel 50,20 ==~ 0,255,255,255 +/- 8;
+ @assert pixel 87,20 ==~ 0,0,255,255 +/- 8;
+ @assert pixel 50,45 ==~ 255,255,255,255 +/- 8;
+ });
+ img.src = data;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(1, 1, 0)
+ cr.rectangle(0, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(25, 0, 50, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(75, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(1, 1, 1)
+ cr.rectangle(0, 40, 100, 10)
+ cr.fill()
+
+- name: toDataURL.jpeg.alpha
+ desc: toDataURL with JPEG composites onto black
+ testing:
+ - toDataURL.jpeg
+ - toDataURL.noalpha
+ code: |
+ ctx.fillStyle = 'rgba(128, 255, 128, 0.5)';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = 'destination-over'; // should be ignored by toDataURL
+ var data = canvas.toDataURL('image/jpeg');
+ ctx.globalCompositeOperation = 'source-over';
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 63,127,63,255 +/- 8;
+ });
+ img.src = data;
+ }
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.25, 0.5, 0.25)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: toDataURL.jpeg.quality.basic
+ desc: toDataURL with JPEG uses the quality parameter
+ testing:
+ - toDataURL.jpeg.quality
+ mozilla: { throws }
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 3, 100, 1);
+ // Check for JPEG support first
+ var data = canvas.toDataURL('image/jpeg');
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ var data_hi = canvas.toDataURL('image/jpeg', 0.99);
+ var data_lo = canvas.toDataURL('image/jpeg', 0.01);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ deferTest();
+ var img_hi = new Image();
+ img_hi.onload = function ()
+ {
+ var img_lo = new Image();
+ img_lo.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img_hi, 0, 0, 50, 50, 0, 0, 50, 50);
+ ctx.drawImage(img_lo, 0, 0, 50, 50, 50, 0, 50, 50);
+ @assert data_hi.length > data_lo.length;
+ @assert pixel 25,25 ==~ 0,0,255,255 +/- 8;
+ @assert pixel 75,25 ==~ 0,0,255,255 +/- 32;
+ });
+ img_lo.src = data_lo;
+ };
+ img_hi.src = data_hi;
+ }
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(0, 3, 100, 1)
+ cr.fill()
+
+- name: toDataURL.jpeg.quality.notnumber
+ desc: toDataURL with JPEG handles non-numeric quality parameters
+ testing:
+ - toDataURL.jpeg.nan
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 3, 100, 1);
+ // Check for JPEG support first
+ var data = canvas.toDataURL('image/jpeg');
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ @assert canvas.toDataURL('image/jpeg', 'bogus') === data;
+ @assert canvas.toDataURL('image/jpeg', {}) === data;
+ @assert canvas.toDataURL('image/jpeg', null) === data;
+ @assert canvas.toDataURL('image/jpeg', undefined) === data;
+ @assert canvas.toDataURL('image/jpeg', true) === data;
+ @assert canvas.toDataURL('image/jpeg', '0.01') === data;
+ }
+
+- name: toDataURL.jpeg.quality.outsiderange
+ desc: toDataURL with JPEG handles out-of-range quality parameters
+ testing:
+ - toDataURL.jpeg.range
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 3, 100, 1);
+ // Check for JPEG support first
+ var data = canvas.toDataURL('image/jpeg');
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ @assert canvas.toDataURL('image/jpeg', 10) === data;
+ @assert canvas.toDataURL('image/jpeg', -10) === data;
+ @assert canvas.toDataURL('image/jpeg', 1.01) === data;
+ @assert canvas.toDataURL('image/jpeg', -0.01) === data;
+
+ @assert canvas.toDataURL('image/jpeg', 1).length >= canvas.toDataURL('image/jpeg', 0.9).length;
+ @assert canvas.toDataURL('image/jpeg', 0).length <= canvas.toDataURL('image/jpeg', 0.1).length;
+ }
+
+
+# TODO: work out what security exception should be thrown
+# TODO: test same-origin vs same-host
+
+- name: security.drawImage.image
+ desc: drawImage of different-origin image makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.drawImage.image
+ - security.toDataURL
+ - security.getImageData
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.drawImage.canvas
+ desc: drawImage of unclean canvas makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.drawImage.canvas
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+ ctx.drawImage(canvas2, 0, 0);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.create
+ desc: Creating an unclean pattern does not make the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.start
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ canvas.toDataURL();
+ ctx.getImageData(0, 0, 1, 1);
+ @assert true; // okay if there was no exception
+
+- name: security.pattern.cross
+ desc: Using an unclean pattern makes the target canvas origin-unclean, not the pattern canvas
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.start
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ var p = ctx2.createPattern(document.getElementById('yellow.png'), 'repeat');
+ ctx.fillStyle = p;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+ canvas2.toDataURL();
+ ctx2.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.canvas.timing
+ desc: Pattern safety depends on whether the source was origin-clean, not on whether it still is clean
+ notes: Disagrees with spec on "is" vs "was"
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.start
+ - security.fillStyle.canvas
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 0, 100, 50);
+ var p = ctx.createPattern(canvas2, 'repeat');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0); // make canvas2 origin-unclean
+ ctx.fillStyle = p;
+ ctx.fillRect(0, 0, 100, 50);
+ canvas.toDataURL();
+ ctx.getImageData(0, 0, 1, 1);
+ @assert true; // okay if there was no exception
+
+- name: security.pattern.image.fillStyle
+ desc: Setting fillStyle to a pattern of a different-origin image makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.fillStyle.image
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ ctx.fillStyle = p;
+ ctx.fillStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.canvas.fillStyle
+ desc: Setting fillStyle to a pattern of an unclean canvas makes the canvas origin-unclean
+ mozilla: { bug: 354127, disabled } # relies on external resources
+ testing:
+ - security.fillStyle.canvas
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+ var p = ctx.createPattern(canvas2, 'repeat');
+ ctx.fillStyle = p;
+ ctx.fillStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.image.strokeStyle
+ desc: Setting strokeStyle to a pattern of a different-origin image makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.strokeStyle.image
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ ctx.strokeStyle = p;
+ ctx.strokeStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.canvas.strokeStyle
+ desc: Setting strokeStyle to a pattern of an unclean canvas makes the canvas origin-unclean
+ mozilla: { bug: 354127, disabled } # relies on external resources
+ testing:
+ - security.strokeStyle.canvas
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+ var p = ctx.createPattern(canvas2, 'repeat');
+ ctx.strokeStyle = p;
+ ctx.strokeStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.dataURI
+ desc: 'data: URIs do not count as different-origin, and do not taint the canvas'
+ mozilla: { disabled, bug: 417836 } # can't do "todo" so just disable it
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var data = canvas.toDataURL();
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ canvas.toDataURL(); // should be permitted
+ @assert pixel 50,25 == 0,255,0,255;
+ });
+ img.src = data;
+ expected: green
+
+- name: security.reset
+ desc: Resetting the canvas state does not reset the origin-clean flag
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - initial.reset
+ scripts:
+ - /common/get-host-info.sub.js
+ - data:text/javascript,addCrossOriginYellowImage()
+ code: |
+ canvas.width = 50;
+ ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ canvas.width = 100;
+ @assert throws SECURITY_ERR canvas.toDataURL();