diff --git a/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.p3.html b/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.p3.html index 55d13a173c2dbc4..063012f2826e5c1 100644 --- a/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.p3.html +++ b/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.p3.html @@ -20,9 +20,9 @@

2d.color.space.p3.to.p3

_addTest(function(canvas, ctx) { var color_style = 'rgb(50, 100, 150)'; -var epsilon = 2; // [0.24304, 0.38818, 0.57227, 1.0] * 255 = [62, 99, 146, 255] var pixel_expected = [62, 99, 146, 255]; +var epsilon = 2; ctx.fillStyle = color_style; ctx.fillRect(0, 0, 10, 10); diff --git a/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.srgb.html b/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.srgb.html index adf8810554cf4cd..2cbeaf3b9b07775 100644 --- a/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.srgb.html +++ b/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.srgb.html @@ -20,8 +20,8 @@

2d.color.space.p3.to.srgb

_addTest(function(canvas, ctx) { var color_style = 'rgb(50, 100, 150)'; -var epsilon = 2; var pixel_expected = [50, 100, 150, 255]; +var epsilon = 2; ctx.fillStyle = color_style; ctx.fillRect(0, 0, 10, 10); diff --git a/html/canvas/tools/gentest.py b/html/canvas/tools/gentest.py index 5c223e41fba054c..969602cf2d03216 100644 --- a/html/canvas/tools/gentest.py +++ b/html/canvas/tools/gentest.py @@ -1,4 +1,6 @@ from gentestutils import genTestUtils +from gentestutilsunion import genTestUtils_union -genTestUtils('../element', '../element', 'templates.yaml', 'name2dir.yaml', False) -genTestUtils('../offscreen', '../offscreen', 'templates-offscreen.yaml', 'name2dir-offscreen.yaml', True) +genTestUtils('../element', '../element', 'templates.yaml', 'name2dir-canvas.yaml', False) +genTestUtils('../offscreen', '../offscreen', 'templates.yaml', 'name2dir-offscreen.yaml', True) +genTestUtils_union('templates-new.yaml', 'name2dir-canvas.yaml') \ No newline at end of file diff --git a/html/canvas/tools/gentest_union.py b/html/canvas/tools/gentest_union.py new file mode 100644 index 000000000000000..62c1cde6a1154bc --- /dev/null +++ b/html/canvas/tools/gentest_union.py @@ -0,0 +1,3 @@ +from gentestutilsunion import genTestUtils_union + +genTestUtils_union('templates-new.yaml', 'name2dir-canvas.yaml') diff --git a/html/canvas/tools/gentestutils.py b/html/canvas/tools/gentestutils.py index c4c1cf720a3cebe..7fe21ee061c0222 100644 --- a/html/canvas/tools/gentestutils.py +++ b/html/canvas/tools/gentestutils.py @@ -404,13 +404,15 @@ def expand_test_code(code): 'fallback':fallback, 'attributes':attributes, 'context_args': context_args } - - f = codecs.open('%s/%s%s.html' % (TESTOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') - f.write(templates['w3c'] % template_params) if ISOFFSCREENCANVAS: + f = codecs.open('%s/%s%s.html' % (TESTOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') + f.write(templates['w3coffscreencanvas'] % template_params) timeout = '// META: timeout=%s\n' % test['timeout'] if 'timeout' in test else '' template_params['timeout'] = timeout f = codecs.open('%s/%s%s.worker.js' % (TESTOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') f.write(templates['w3cworker'] % template_params) + else: + f = codecs.open('%s/%s%s.html' % (TESTOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') + f.write(templates['w3ccanvas'] % template_params) print() diff --git a/html/canvas/tools/gentestutilsunion.py b/html/canvas/tools/gentestutilsunion.py new file mode 100644 index 000000000000000..2359ef03a917cdd --- /dev/null +++ b/html/canvas/tools/gentestutilsunion.py @@ -0,0 +1,426 @@ +# Current code status: +# +# This was originally written by Philip Taylor for use at +# http://philip.html5.org/tests/canvas/suite/tests/ +# +# It has been adapted for use with the Web Platform Test Suite suite at +# https://github.com/web-platform-tests/wpt/ +# +# The original version had a number of now-removed features (multiple versions of +# each test case of varying verbosity, Mozilla mochitests, semi-automated test +# harness). It also had a different directory structure. + +# To update or add test cases: +# +# * Modify the tests*.yaml files. +# 'name' is an arbitrary hierarchical name to help categorise tests. +# 'desc' is a rough description of what behaviour the test aims to test. +# 'testing' is a list of references to spec.yaml, to show which spec sentences +# this test case is primarily testing. +# 'code' is JavaScript code to execute, with some special commands starting with '@' +# 'expected' is what the final canvas output should be: a string 'green' or 'clear' +# (100x50 images in both cases), or a string 'size 100 50' (or any other size) +# followed by Python code using Pycairo to generate the image. +# +# * Run "./build.sh". +# This requires a few Python modules which might not be ubiquitous. +# It will usually emit some warnings, which ideally should be fixed but can +# generally be safely ignored. +# +# * Test the tests, add new ones to Git, remove deleted ones from Git, etc. + +from __future__ import print_function + +import re +import codecs +import time +import os +import shutil +import sys +import xml.dom.minidom +from xml.dom.minidom import Node + +try: + import cairocffi as cairo +except ImportError: + import cairo + +try: + import syck as yaml # compatible and lots faster +except ImportError: + import yaml + +def genTestUtils_union(TEMPLATEFILE, NAME2DIRFILE): + CANVASOUTPUTDIR = '../element' + CANVASIMAGEOUTPUTDIR = '../element' + OFFSCREENCANVASOUTPUTDIR = '../offscreen' + OFFSCREENCANVASIMAGEOUTPUTDIR = '../offscreen' + MISCOUTPUTDIR = './output' + SPECOUTPUTDIR = '../' + HTMLCanvas_test = True + OffscreenCanvas_test = True + + SPECOUTPUTPATH = './' # relative to CANVASOUTPUTDIR + + def simpleEscapeJS(str): + return str.replace('\\', '\\\\').replace('"', '\\"') + + def escapeJS(str): + str = simpleEscapeJS(str) + str = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', str) # kind of an ugly hack, for nicer failure-message output + return str + + def escapeHTML(str): + return str.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"') + + def expand_nonfinite(method, argstr, tail): + """ + >>> print expand_nonfinite('f', '<0 a>, <0 b>', ';') + f(a, 0); + f(0, b); + f(a, b); + >>> print expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';') + f(a, 0, 0); + f(0, b, 0); + f(0, c, 0); + f(0, 0, d); + f(a, b, 0); + f(a, b, d); + f(a, 0, d); + f(0, b, d); + """ + # argstr is ", ..." (where usually + # 'invalid' is Infinity/-Infinity/NaN) + args = [] + for arg in argstr.split(', '): + a = re.match('<(.*)>', arg).group(1) + args.append(a.split(' ')) + calls = [] + # Start with the valid argument list + call = [ args[j][0] for j in range(len(args)) ] + # For each argument alone, try setting it to all its invalid values: + for i in range(len(args)): + for a in args[i][1:]: + c2 = call[:] + c2[i] = a + calls.append(c2) + # For all combinations of >= 2 arguments, try setting them to their + # first invalid values. (Don't do all invalid values, because the + # number of combinations explodes.) + def f(c, start, depth): + for i in range(start, len(args)): + if len(args[i]) > 1: + a = args[i][1] + c2 = c[:] + c2[i] = a + if depth > 0: calls.append(c2) + f(c2, i+1, depth+1) + f(call, 0, 0) + + return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail) for c in calls) + + # Run with --test argument to run unit tests + if len(sys.argv) > 1 and sys.argv[1] == '--test': + import doctest + doctest.testmod() + sys.exit() + + templates = yaml.safe_load(open(TEMPLATEFILE, "r").read()) + name_mapping = yaml.safe_load(open(NAME2DIRFILE, "r").read()) + + SPECFILE = 'spec.yaml' + spec_assertions = [] + for s in yaml.safe_load(open(SPECFILE, "r").read())['assertions']: + if 'meta' in s: + eval(compile(s['meta'], '', 'exec'), {}, {'assertions':spec_assertions}) + else: + spec_assertions.append(s) + + tests = [] + test_yaml_directory = "yaml-new" + TESTSFILES = [ + os.path.join(test_yaml_directory, f) for f in os.listdir(test_yaml_directory) + if f.endswith(".yaml")] + for t in sum([ yaml.safe_load(open(f, "r").read()) for f in TESTSFILES], []): + if 'DISABLED' in t: + continue + if 'meta' in t: + eval(compile(t['meta'], '', 'exec'), {}, {'tests':tests}) + else: + tests.append(t) + + category_names = [] + category_contents_direct = {} + category_contents_all = {} + + spec_ids = {} + for t in spec_assertions: spec_ids[t['id']] = True + spec_refs = {} + + def backref_html(name): + backrefs = [] + c = '' + for p in name.split('.')[:-1]: + c += '.'+p + backrefs.append('%s.' % (c, p)) + backrefs.append(name.split('.')[-1]) + return ''.join(backrefs) + + # Ensure the test output directories exist + testdirs = [CANVASOUTPUTDIR, OFFSCREENCANVASOUTPUTDIR, CANVASIMAGEOUTPUTDIR, OFFSCREENCANVASIMAGEOUTPUTDIR, MISCOUTPUTDIR] + for map_dir in set(name_mapping.values()): + testdirs.append("%s/%s" % (CANVASOUTPUTDIR, map_dir)) + testdirs.append("%s/%s" % (OFFSCREENCANVASOUTPUTDIR, map_dir)) + for d in testdirs: + try: os.mkdir(d) + except: pass # ignore if it already exists + + used_images = {} + + def map_name(name): + mapped_name = None + for mn in sorted(name_mapping.keys(), key=len, reverse=True): + if name.startswith(mn): + mapped_name = "%s/%s" % (name_mapping[mn], name) + break + if not mapped_name: + print("LIKELY ERROR: %s has no defined target directory mapping" % name) + if 'manual' in test: + mapped_name += "-manual" + return mapped_name + + def expand_test_code(code, is_offscreencanvas): + code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m: expand_nonfinite(m.group(1), m.group(2), m.group(3)), code) # must come before '@assert throws' + + if is_offscreencanvas: + code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);', + r'_assertPixel(offscreenCanvas, \1, \2, "\1", "\2");', + code) + else: + code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);', + r'_assertPixel(canvas, \1, \2, "\1", "\2");', + code) + + if is_offscreencanvas: + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);', + r'_assertPixelApprox(offscreenCanvas, \1, \2, "\1", "\2", 2);', + code) + else: + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);', + r'_assertPixelApprox(canvas, \1, \2, "\1", "\2", 2);', + code) + + if is_offscreencanvas: + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);', + r'_assertPixelApprox(offscreenCanvas, \1, \2, "\1", "\2", \3);', + code) + else: + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);', + r'_assertPixelApprox(canvas, \1, \2, "\1", "\2", \3);', + code) + + code = re.sub(r'@assert throws (\S+_ERR) (.*);', + r'assert_throws_dom("\1", function() { \2; });', + code) + + code = re.sub(r'@assert throws (\S+Error) (.*);', + r'assert_throws_js(\1, function() { \2; });', + code) + + code = re.sub(r'@assert (.*) === (.*);', + lambda m: '_assertSame(%s, %s, "%s", "%s");' + % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2))) + , code) + + code = re.sub(r'@assert (.*) !== (.*);', + lambda m: '_assertDifferent(%s, %s, "%s", "%s");' + % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2))) + , code) + + code = re.sub(r'@assert (.*) =~ (.*);', + lambda m: 'assert_regexp_match(%s, %s);' + % (m.group(1), m.group(2)) + , code) + + code = re.sub(r'@assert (.*);', + lambda m: '_assert(%s, "%s");' + % (m.group(1), escapeJS(m.group(1))) + , code) + + code = re.sub(r' @moz-todo', '', code) + + code = re.sub(r'@moz-UniversalBrowserRead;', + "" + , code) + + assert('@' not in code) + + return code + + used_tests = {} + for i in range(len(tests)): + test = tests[i] + if test.get('canvasType', []): + HTMLCanvas_test = False + OffscreenCanvas_test = False + for type in test.get('canvasType'): + if type.lower() == 'htmlcanvas': + HTMLCanvas_test = True + elif type.lower() == 'offscreencanvas': + OffscreenCanvas_test = True + + name = test['name'] + print("\r(%s)" % name, " "*32, "\t") + + if name in used_tests: + print("Test %s is defined twice" % name) + used_tests[name] = 1 + + mapped_name = map_name(name) + if not mapped_name: + mapped_name = name + + + cat_total = '' + for cat_part in [''] + name.split('.')[:-1]: + cat_total += cat_part+'.' + if not cat_total in category_names: category_names.append(cat_total) + category_contents_all.setdefault(cat_total, []).append(name) + category_contents_direct.setdefault(cat_total, []).append(name) + + for ref in test.get('testing', []): + if ref not in spec_ids: + print("Test %s uses nonexistent spec point %s" % (name, ref)) + spec_refs.setdefault(ref, []).append(name) + + if not test.get('testing', []): + print("Test %s doesn't refer to any spec points" % name) + + if test.get('expected', '') == 'green' and re.search(r'@assert pixel .* 0,0,0,0;', test['code']): + print("Probable incorrect pixel test in %s" % name) + + code_canvas = expand_test_code(test['code'], False).strip() + code_offscreen = expand_test_code(test['code'], True).strip() + + expectation_html = '' + if 'expected' in test and test['expected'] is not None: + expected = test['expected'] + expected_img = None + if expected == 'green': + expected_img = "/images/green-100x50.png" + elif expected == 'clear': + expected_img = "/images/clear-100x50.png" + else: + if ';' in expected: + print("Found semicolon in %s" % name) + expected = re.sub(r'^size (\d+) (\d+)', + r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)\ncr = cairo.Context(surface)', + expected) + + if mapped_name.endswith("-manual"): + png_name = mapped_name[:-len("-manual")] + else: + png_name = mapped_name + expected_canvas = expected + "\nsurface.write_to_png('%s/%s.png')\n" % (CANVASIMAGEOUTPUTDIR, png_name) + eval(compile(expected_canvas, '' % test['name'], 'exec'), {}, {'cairo':cairo}) + + expected_offscreencanvas = expected + "\nsurface.write_to_png('%s/%s.png')\n" % (OFFSCREENCANVASIMAGEOUTPUTDIR, png_name) + eval(compile(expected_offscreencanvas, '' % test['name'], 'exec'), {}, {'cairo':cairo}) + + expected_img = "%s.png" % name + + if expected_img: + expectation_html = ('

Expected output:' + + '

' % (expected_img)) + + canvas = test.get('canvas', 'width="100" height="50"') + + prev = tests[i-1]['name'] if i != 0 else 'index' + next = tests[i+1]['name'] if i != len(tests)-1 else 'index' + + name_wrapped = name.replace('.', '.​') + + refs = ''.join('

  • %s\n' % (SPECOUTPUTPATH, n,n) for n in test.get('testing', [])) + + notes = '

    %s' % test['notes'] if 'notes' in test else '' + + timeout = '\n' % test['timeout'] if 'timeout' in test else '' + + scripts = '' + for s in test.get('scripts', []): + scripts += '\n' % (s) + + variants = test.get('script-variants', {}) + script_variants = [(v, '\n' % (s)) for (v, s) in variants.items()] + if not script_variants: + script_variants = [('', '')] + + images = '' + for i in test.get('images', []): + id = i.split('/')[-1] + if '/' not in i: + used_images[i] = 1 + i = '../images/%s' % i + images += '\n' % (i,id) + for i in test.get('svgimages', []): + id = i.split('/')[-1] + if '/' not in i: + used_images[i] = 1 + i = '../images/%s' % i + images += '\n' % (i,id) + images = images.replace("../images/", "/images/") + + fonts = '' + fonthack = '' + for i in test.get('fonts', []): + fonts += '@font-face {\n font-family: %s;\n src: url("/fonts/%s.ttf");\n}\n' % (i, i) + # Browsers require the font to actually be used in the page + if test.get('fonthack', 1): + fonthack += 'A\n' % i + if fonts: + fonts = '\n' % fonts + + fallback = test.get('fallback', '

    FAIL (fallback content)

    ') + + desc = test.get('desc', '') + escaped_desc = simpleEscapeJS(desc) + + attributes = test.get('attributes', '') + if attributes: + context_args = "'2d', %s" % attributes.strip() + attributes = ', ' + attributes.strip() + else: + context_args = "'2d'" + + for (variant, extra_script) in script_variants: + name_variant = '' if not variant else '.' + variant + + template_params = { + 'name':name + name_variant, + 'name_wrapped':name_wrapped, 'backrefs':backref_html(name), + 'mapped_name':mapped_name, + 'desc':desc, 'escaped_desc':escaped_desc, + 'prev':prev, 'next':next, 'refs':refs, 'notes':notes, 'images':images, + 'fonts':fonts, 'fonthack':fonthack, 'timeout': timeout, + 'canvas':canvas, 'expected':expectation_html, 'code':code_canvas, + 'scripts':scripts + extra_script, + 'fallback':fallback, 'attributes':attributes, + 'context_args': context_args + } + + # Create test cases for canvas and offscreencanvas. + if HTMLCanvas_test: + f = codecs.open('%s/%s%s.html' % (CANVASOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') + f.write(templates['w3ccanvas'] % template_params) + if OffscreenCanvas_test: + template_params['code'] = code_offscreen + f = codecs.open('%s/%s%s.html' % (OFFSCREENCANVASOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') + f.write(templates['w3coffscreencanvas'] % template_params) + + # Create test case for offscreencanvas worker. + timeout = '// META: timeout=%s\n' % test['timeout'] if 'timeout' in test else '' + template_params['timeout'] = timeout + f = codecs.open('%s/%s%s.worker.js' % (OFFSCREENCANVASOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') + f.write(templates['w3cworker'] % template_params) + + print() diff --git a/html/canvas/tools/name2dir-canvas.yaml b/html/canvas/tools/name2dir-canvas.yaml new file mode 100644 index 000000000000000..f1ebe4b8a9d0c3c --- /dev/null +++ b/html/canvas/tools/name2dir-canvas.yaml @@ -0,0 +1,55 @@ +2d.transformation: "transformations" +2d.color.space: 'wide-gamut-canvas' +2d.composite: "compositing" +2d.coordinatespace: "conformance-requirements" +2d.missingargs: "conformance-requirements" +2d.type.delete: "conformance-requirements" +2d.voidreturn: "conformance-requirements" +2d.drawImage: "drawing-images-to-the-canvas" +2d.clearRect: "drawing-rectangles-to-the-canvas" +2d.fillRect: "drawing-rectangles-to-the-canvas" +2d.strokeRect: "drawing-rectangles-to-the-canvas" +2d.text.draw: "drawing-text-to-the-canvas" +2d.text.draw.space.basic: "drawing-text-to-the-canvas" +2d.text.draw.space.collapse: "drawing-text-to-the-canvas" +2d.text.measure: "drawing-text-to-the-canvas" +2d.fillStyle: "fill-and-stroke-styles" +2d.gradient: "fill-and-stroke-styles" +2d.pattern: "fill-and-stroke-styles" +2d.strokeStyle: "fill-and-stroke-styles" +2d.line: "line-styles" +2d.path: "path-objects" +2d.imageData: "pixel-manipulation" +2d.reset: "reset" +2d.shadow: "shadows" +2d.filter: "filters" +2d.text.align: "text-styles" +2d.text.baseline: "text-styles" +2d.text.font: "text-styles" +2d.text.draw.baseline: "text-styles" +2d.text.draw.space: "text-styles" +2d.text.measure.width.space: "text-styles" +2d.text.draw.space.collapse.end: "text-styles" +2d.text.draw.space.collapse.other: "text-styles" +2d.text.draw.space.collapse.space: "text-styles" +2d.text.draw.space.collapse.start: "text-styles" +2d.state: "the-canvas-state" +2d.scrollPathIntoView: "scroll" +2d.video: "video" +2d.canvas: "../../../html/semantics/embedded-content/the-canvas-element" +2d.getcontext: "../../../html/semantics/embedded-content/the-canvas-element" +2d.scaled: "../../../html/semantics/embedded-content/the-canvas-element" +2d.type: "../../../html/semantics/embedded-content/the-canvas-element" +context: "../../../html/semantics/embedded-content/the-canvas-element" +fallback: "../../../html/semantics/embedded-content/the-canvas-element" +initial: "../../../html/semantics/embedded-content/the-canvas-element" +security: "../../../html/semantics/embedded-content/the-canvas-element" +size: "../../../html/semantics/embedded-content/the-canvas-element" +toBlob: "../../../html/semantics/embedded-content/the-canvas-element" +toDataURL: "../../../html/semantics/embedded-content/the-canvas-element" +type: "../../../html/semantics/embedded-content/the-canvas-element" +2d.offscreencanvas: "the-offscreen-canvas" +2d.offscreencanva.getcontext: "the-offscreen-canvas" +2d.offscreencanva.context: "the-offscreen-canvas" +2d.offscreencanva.initial: "the-offscreen-canvas" +2d.offscreencanva.size: "the-offscreen-canvas" \ No newline at end of file diff --git a/html/canvas/tools/name2dir.yaml b/html/canvas/tools/name2dir.yaml index 8f3c2c9d35eb6fe..e2c4d971a45ac49 100644 --- a/html/canvas/tools/name2dir.yaml +++ b/html/canvas/tools/name2dir.yaml @@ -37,14 +37,9 @@ 2d.scrollPathIntoView: "scroll" 2d.video: "video" 2d.canvas: "../../../html/semantics/embedded-content/the-canvas-element" -2d.getcontext: "../../../html/semantics/embedded-content/the-canvas-element" -2d.scaled: "../../../html/semantics/embedded-content/the-canvas-element" -2d.type: "../../../html/semantics/embedded-content/the-canvas-element" -context: "../../../html/semantics/embedded-content/the-canvas-element" -fallback: "../../../html/semantics/embedded-content/the-canvas-element" -initial: "../../../html/semantics/embedded-content/the-canvas-element" -security: "../../../html/semantics/embedded-content/the-canvas-element" -size: "../../../html/semantics/embedded-content/the-canvas-element" -toBlob: "../../../html/semantics/embedded-content/the-canvas-element" -toDataURL: "../../../html/semantics/embedded-content/the-canvas-element" -type: "../../../html/semantics/embedded-content/the-canvas-element" +2d.canvas.getcontext: "../../../html/semantics/embedded-content/the-canvas-element" +2d.canvas.scaled: "../../../html/semantics/embedded-content/the-canvas-element" +2d.canvas.type: "../../../html/semantics/embedded-content/the-canvas-element" +2d.canvas.initial: "../../../html/semantics/embedded-content/the-canvas-element" +2d.canvas.size: "../../../html/semantics/embedded-content/the-canvas-element" +2d.canvas.type: "../../../html/semantics/embedded-content/the-canvas-element" diff --git a/html/canvas/tools/templates-offscreen.yaml b/html/canvas/tools/templates-new.yaml similarity index 60% rename from html/canvas/tools/templates-offscreen.yaml rename to html/canvas/tools/templates-new.yaml index acf7535ff3dab38..ecf9e68f506bd22 100644 --- a/html/canvas/tools/templates-offscreen.yaml +++ b/html/canvas/tools/templates-new.yaml @@ -1,4 +1,4 @@ -w3c: | +w3coffscreencanvas: | OffscreenCanvas test: %(name)s%(timeout)s @@ -22,6 +22,8 @@ w3c: | var ctx = offscreenCanvas.getContext(%(context_args)s); %(code)s + t.done(); + }); @@ -46,5 +48,37 @@ w3cworker: | var ctx = offscreenCanvas.getContext(%(context_args)s); %(code)s + t.done(); + }); done(); + + +w3ccanvas: | + + + Canvas test: %(name)s + + + + + %(fonts)s + +

    %(name)s

    +

    %(desc)s

    + + %(notes)s + %(fonthack)s

    Actual output:

    + %(fallback)s + %(expected)s +
      + + %(scripts)s%(images)s diff --git a/html/canvas/tools/templates.yaml b/html/canvas/tools/templates.yaml index af0e656dd6d27e9..6d6c4750c10f72b 100644 --- a/html/canvas/tools/templates.yaml +++ b/html/canvas/tools/templates.yaml @@ -1,4 +1,56 @@ -w3c: | +w3coffscreencanvas: | + + + OffscreenCanvas test: %(name)s%(timeout)s + + + + +

      %(name)s

      +

      %(desc)s

      + + %(notes)s + + + +w3cworker: | + %(timeout)s// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. + // OffscreenCanvas test in a worker:%(name)s + // Description:%(desc)s + // Note:%(notes)s + + importScripts("/resources/testharness.js"); + importScripts("/html/canvas/resources/canvas-tests.js"); + + var t = async_test("%(escaped_desc)s"); + var t_pass = t.done.bind(t); + var t_fail = t.step_func(function(reason) { + throw reason; + }); + t.step(function() { + + var offscreenCanvas = new OffscreenCanvas(100, 50); + var ctx = offscreenCanvas.getContext(%(context_args)s); + + %(code)s + }); + done(); + + +w3ccanvas: | Canvas test: %(name)s diff --git a/html/canvas/tools/yaml/element/color_space.yaml b/html/canvas/tools/yaml-new/color_space.yaml similarity index 97% rename from html/canvas/tools/yaml/element/color_space.yaml rename to html/canvas/tools/yaml-new/color_space.yaml index 2709f95017369d7..cce1ff8ca4ba7bd 100644 --- a/html/canvas/tools/yaml/element/color_space.yaml +++ b/html/canvas/tools/yaml-new/color_space.yaml @@ -1,14 +1,14 @@ - name: 2d.color.space.p3.to.p3 testing: - - 2d.color.space.p3.and.uint8 + - 2d.color.space.p3.to.p3 desc: test getImageData with display-p3 and uint8 from display p3 uint8 canvas attributes: | {colorSpace: "display-p3"} code: | var color_style = 'rgb(50, 100, 150)'; - var epsilon = 2; // [0.24304, 0.38818, 0.57227, 1.0] * 255 = [62, 99, 146, 255] var pixel_expected = [62, 99, 146, 255]; + var epsilon = 2; ctx.fillStyle = color_style; ctx.fillRect(0, 0, 10, 10); @@ -21,14 +21,14 @@ - name: 2d.color.space.p3.to.srgb testing: - - 2d.color.space.p3.and.uint8 + - 2d.color.space.p3.to.srgb desc: test getImageData with srsb and uint8 from display p3 uint8 canvas attributes: | {colorSpace: "display-p3"} code: | var color_style = 'rgb(50, 100, 150)'; - var epsilon = 2; var pixel_expected = [50, 100, 150, 255]; + var epsilon = 2; ctx.fillStyle = color_style; ctx.fillRect(0, 0, 10, 10); @@ -45,6 +45,8 @@ desc: test if toblob returns p3 data from p3 color space canvas attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | ctx.fillStyle = "rgba(155, 27, 27, 1)"; ctx.fillRect(0, 0, 1, 1); @@ -78,6 +80,8 @@ desc: test if toDataURL returns p3 data from canvas with p3 color space attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | ctx.fillStyle = "rgba(155, 27, 27, 1)"; ctx.fillRect(0, 0, 1, 1); @@ -107,6 +111,8 @@ desc: test if toDataURL('image/jpeg') returns p3 data from canvas with p3 color space attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | ctx.fillStyle = "rgba(155, 27, 27, 1)"; ctx.fillRect(0, 0, 1, 1); @@ -136,6 +142,8 @@ desc: Use putImageData to put some p3 data in canvas and test if toBlob returns the same data attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | canvas.width = 2; canvas.height = 2; @@ -175,6 +183,8 @@ desc: Use putImageData to put some p3 data in canvas and test if toDataURL returns the same data attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | canvas.width = 2; canvas.height = 2; @@ -211,6 +221,8 @@ desc: Test if fillText can be used with a solid display-p3 color attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | deferTest(); @@ -252,6 +264,8 @@ desc: Test if strokeText can be used with a solid display-p3 color attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | deferTest(); @@ -294,6 +308,8 @@ desc: Test if fillText can be used with a display-p3 shadow color attributes: | {colorSpace: "display-p3"} + canvasType: + ['HTMLCanvas'] code: | deferTest(); diff --git a/html/canvas/tools/yaml/offscreen/color_space.yaml b/html/canvas/tools/yaml/offscreen/color_space.yaml deleted file mode 100644 index 0a1c4474fb49a4d..000000000000000 --- a/html/canvas/tools/yaml/offscreen/color_space.yaml +++ /dev/null @@ -1,42 +0,0 @@ -- name: 2d.color.space.p3.to.p3 - testing: - - 2d.color.space.p3.to.p3 - desc: test getImageData with display-p3 and uint8 from display p3 uint8 canvas - attributes: | - {colorSpace: "display-p3"} - code: | - var color_style = 'rgb(50, 100, 150)'; - // [0.24304, 0.38818, 0.57227, 1.0] * 255 = [62, 99, 146, 255] - var pixel_expected = [62, 99, 146, 255]; - var epsilon = 2; - ctx.fillStyle = color_style; - ctx.fillRect(0, 0, 10, 10); - - var pixel = ctx.getImageData(5, 5, 1, 1, {colorSpace: "display-p3", storageFormat: "uint8"}).data; - @assert pixel.length === pixel_expected.length; - assert_approx_equals(pixel[0], pixel_expected[0], 2); - assert_approx_equals(pixel[1], pixel_expected[1], 2); - assert_approx_equals(pixel[2], pixel_expected[2], 2); - assert_approx_equals(pixel[3], pixel_expected[3], 2); - t.done(); - -- name: 2d.color.space.p3.to.srgb - testing: - - 2d.color.space.p3.to.srgb - desc: test getImageData with srsb and uint8 from display p3 uint8 canvas - attributes: | - {colorSpace: "display-p3"} - code: | - var color_style = 'rgb(50, 100, 150)'; - var pixel_expected = [50, 100, 150, 255]; - var epsilon = 2; - ctx.fillStyle = color_style; - ctx.fillRect(0, 0, 10, 10); - - var pixel = ctx.getImageData(5, 5, 1, 1, {colorSpace: "srgb", storageFormat: "uint8"}).data; - @assert pixel.length === pixel_expected.length; - assert_approx_equals(pixel[0], pixel_expected[0], 2); - assert_approx_equals(pixel[1], pixel_expected[1], 2); - assert_approx_equals(pixel[2], pixel_expected[2], 2); - assert_approx_equals(pixel[3], pixel_expected[3], 2); - t.done();