| function _valToString(val) |
| { |
| if (val === undefined || val === null) |
| return '[' + typeof(val) + ']'; |
| return val.toString() + '[' + typeof(val) + ']'; |
| } |
| |
| var _hex2dec_table = { |
| 0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8, 9:9, |
| a:10, b:11, c:12, d:13, e:14, f:15, |
| A:10, B:11, C:12, D:13, E:14, F:15 |
| }; |
| function _hex2dec(hex) |
| { |
| return _hex2dec_table[hex.charAt(0)]*16 + _hex2dec_table[hex.charAt(1)]; |
| } |
| |
| var _failed = false; |
| var _asserted = false; |
| function _warn(text) |
| { |
| document.getElementById('d').appendChild(document.createElement('li')).appendChild(document.createTextNode(text)); |
| } |
| function _fail(text) |
| { |
| _warn(text); |
| _failed = true; |
| } |
| |
| function _assert(cond, text) |
| { |
| _asserted = true; |
| if (! cond) |
| _fail('Failed assertion: ' + text); |
| } |
| |
| function _assertSame(a, b, text_a, text_b) |
| { |
| _asserted = true; |
| if (a !== b) |
| _fail('Failed assertion ' + text_a + ' === ' + text_b + |
| ' (got ' + _valToString(a) + ', expected ' + _valToString(b) + ')'); |
| } |
| |
| function _assertDifferent(a, b, text_a, text_b) |
| { |
| _asserted = true; |
| if (a === b) |
| _fail('Failed assertion ' + text_a + ' !== ' + text_b + |
| ' (got ' + _valToString(a) + ', expected not ' + _valToString(b) + ')'); |
| } |
| |
| function _assertEqual(a, b, text_a, text_b) |
| { |
| _asserted = true; |
| if (a != b) |
| _fail('Failed assertion ' + text_a + ' == ' + text_b + |
| ' (got ' + _valToString(a) + ', expected ' + _valToString(b) + ')'); |
| } |
| |
| function _assertMatch(a, b, text_a, text_b) |
| { |
| _asserted = true; |
| if (! a.match(b)) |
| _fail('Failed assertion ' + text_a + ' matches ' + text_b + |
| ' (got ' + _valToString(a) + ')'); |
| } |
| |
| |
| var _manual_check = false; |
| |
| function _requireManualCheck() |
| { |
| _manual_check = true; |
| } |
| |
| function _crash() |
| { |
| _fail('Aborted due to predicted crash'); |
| } |
| |
| var _getImageDataCalibrated = false; |
| var _getImageDataIsPremul, _getImageDataIsBGRA; |
| |
| function _getPixel(canvas, x,y) |
| { |
| var ctx = canvas.getContext('2d'); |
| if (ctx && typeof(ctx.getImageData) != 'undefined') |
| { |
| try { |
| var imgdata = ctx.getImageData(x, y, 1, 1); |
| } catch (e) { |
| // probably a security exception caused by having drawn |
| // data: URLs onto the canvas |
| imgdata = null; |
| } |
| if (imgdata) |
| { |
| // Work around getImageData bugs, since we want the other tests to |
| // carry on working as well as possible |
| if (! _getImageDataCalibrated) |
| { |
| var c2 = document.createElement('canvas'); |
| c2.width = c2.height = 1; |
| var ctx2 = c2.getContext('2d'); |
| ctx2.fillStyle = 'rgba(0, 255, 255, 0.5)'; |
| ctx2.fillRect(0, 0, 1, 1); |
| var data2 = ctx2.getImageData(0, 0, 1, 1).data; |
| |
| // Firefox returns premultiplied alpha |
| |
| if (data2[1] > 100 && data2[1] < 150) |
| _getImageDataIsPremul = true; |
| else |
| _getImageDataIsPremul = false; |
| |
| // Opera Mini 4 Beta returns BGRA instead of RGBA |
| |
| if (data2[0] > 250 && data2[2] < 5) |
| _getImageDataIsBGRA = true; |
| else |
| _getImageDataIsBGRA = false; |
| |
| _getImageDataCalibrated = true; |
| } |
| |
| // Undo the BGRA flipping |
| var rgba = (_getImageDataIsBGRA |
| ? [ imgdata.data[2], imgdata.data[1], imgdata.data[0], imgdata.data[3] ] |
| : [ imgdata.data[0], imgdata.data[1], imgdata.data[2], imgdata.data[3] ]); |
| |
| if (! _getImageDataIsPremul) |
| return rgba; |
| |
| // Undo the premultiplying |
| if (rgba[3] == 0) |
| return [ 0, 0, 0, 0 ]; |
| else |
| { |
| var a = rgba[3] / 255; |
| return [ |
| Math.round(rgba[0]/a), |
| Math.round(rgba[1]/a), |
| Math.round(rgba[2]/a), |
| rgba[3] |
| ]; |
| } |
| } |
| } |
| |
| try { ctx = canvas.getContext('opera-2dgame'); } catch (e) { /* Firefox throws */ } |
| if (ctx && typeof(ctx.getPixel) != 'undefined') |
| { |
| try { |
| var c = ctx.getPixel(x, y); |
| } catch (e) { |
| // probably a security exception caused by having drawn |
| // data: URLs onto the canvas |
| c = null; |
| } |
| if (c) |
| { |
| var matches = /^rgba\((\d+), (\d+), (\d+), ([\d\.]+)\)$/.exec(c); |
| if (matches) |
| return [ matches[1], matches[2], matches[3], Math.round(matches[4]*255) ]; |
| matches = /^#(..)(..)(..)$/.exec(c); |
| if (matches) |
| return [ _hex2dec(matches[1]), _hex2dec(matches[2]), _hex2dec(matches[3]), 255 ]; |
| } |
| } |
| //_warn("(Can't test pixel value)"); |
| _manual_check = true; |
| return undefined; |
| } |
| |
| function _assertPixel(canvas, x,y, r,g,b,a, pos, colour) |
| { |
| _asserted = true; |
| var c = _getPixel(canvas, x,y); |
| if (c && ! (c[0] == r && c[1] == g && c[2] == b && c[3] == a)) |
| _fail('Failed assertion: got pixel [' + c + '] at ('+x+','+y+'), expected ['+r+','+g+','+b+','+a+']'); |
| } |
| |
| function _assertPixelApprox(canvas, x,y, r,g,b,a, pos, colour, tolerance) |
| { |
| _asserted = true; |
| var c = _getPixel(canvas, x,y); |
| if (c) |
| { |
| var diff = Math.max(Math.abs(c[0]-r), Math.abs(c[1]-g), Math.abs(c[2]-b), Math.abs(c[3]-a)); |
| if (diff > tolerance) |
| _fail('Failed assertion: got pixel [' + c + '] at ('+x+','+y+'), expected ['+r+','+g+','+b+','+a+'] +/- '+tolerance); |
| } |
| } |
| |
| function _addTest(test) |
| { |
| var deferred = false; |
| window.deferTest = function () { deferred = true; }; |
| function endTest() |
| { |
| if (_failed) // test failed |
| { |
| document.documentElement.className += ' fail'; |
| window._testStatus = ['fail', document.getElementById('d').innerHTML]; |
| } |
| else if (_manual_check || !_asserted) |
| { // test case explicitly asked for a manual check, or no automatic assertions were performed |
| document.getElementById('d').innerHTML += '<li>Cannot automatically verify result'; |
| document.documentElement.className += ' needs_check'; |
| window._testStatus = ['check', document.getElementById('d').innerHTML]; |
| } |
| else // test succeeded |
| { |
| document.getElementById('d').innerHTML += '<li>Passed'; |
| document.documentElement.className += ' pass'; |
| window._testStatus = ['pass', document.getElementById('d').innerHTML]; |
| } |
| if (window.testRunner) |
| testRunner.notifyDone(); |
| } |
| window.endTest = endTest; |
| window.wrapFunction = function (f) |
| { |
| return function() |
| { |
| try |
| { |
| f.apply(null, arguments); |
| } |
| catch (e) |
| { |
| _fail('Aborted with exception: ' + e.message); |
| } |
| endTest(); |
| } |
| } |
| |
| window.onload = function () |
| { |
| if (window.testRunner) { |
| testRunner.dumpAsText(); |
| testRunner.waitUntilDone(); |
| } |
| try |
| { |
| var canvas = document.getElementById('c'); |
| var ctx = canvas.getContext('2d'); |
| test(canvas, ctx); |
| } |
| catch (e) |
| { |
| _fail('Aborted with exception: ' + e.message); |
| deferred = false; // cancel any deference |
| } |
| |
| if (! deferred) |
| endTest(); |
| }; |
| } |
| |