<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/html/canvas/resources/canvas-tests.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-transfertoimagebitmap">

<script id="myWorker" type="text/worker">

function testSize(contextType)
{
    var offscreenCanvas = new OffscreenCanvas(100, 50);
    var ctx = offscreenCanvas.getContext(contextType);
    var image = offscreenCanvas.transferToImageBitmap();
    if (image.width == 100 && image.height == 50)
        return true;
    return false;
}

function testImageBitmapClr(shouldCallTwice, alphaVal) {
    var offscreenCanvas = new OffscreenCanvas(100, 50);
    var ctx = offscreenCanvas.getContext('2d', {alpha: alphaVal});
    ctx.fillStyle = "#0f0";
    ctx.fillRect(0, 0, 100, 50);
    var image = offscreenCanvas.transferToImageBitmap();

    if (shouldCallTwice)
        image = offscreenCanvas.transferToImageBitmap();
    return image;
}

function isInvalidStateError(funcStr, offscreenCanvas)
{
    try {
        eval(funcStr);
    } catch (e) {
        if (e instanceof DOMException && e.name == "InvalidStateError")
            return true;
        return false;
    }
}

function testImageBitmapSize()
{
    return testSize('2d') && testSize('webgl');
}

function testLineWidthNotAltered()
{
    var offscreenCanvas = new OffscreenCanvas(100, 50);
    var ctx = offscreenCanvas.getContext('2d');
    ctx.lineWidth = 10;
    var image = offscreenCanvas.transferToImageBitmap();
    return ctx.lineWidth == 10;
}

function testTransformPreserved()
{
    var offscreenCanvas = new OffscreenCanvas(100, 50);
    var ctx = offscreenCanvas.getContext('2d');
    ctx.rect(0, 0, 25, 50);
    ctx.clip();
    ctx.translate(20, 20);

    ctx.fillStyle = '#0f0';
    var image1 = offscreenCanvas.transferToImageBitmap();
    // trasnform should be preserved
    ctx.fillRect(0, 0, 10, 10);
    var image2 = offscreenCanvas.transferToImageBitmap();
    return image2;
}

function testException()
{
    var offscreenCanvas = new OffscreenCanvas(10, 10);
    return isInvalidStateError("offscreenCanvas.transferToImageBitmap()", offscreenCanvas);
}

self.onmessage = function(e) {
    switch (e.data) {
        case 'test1':
            self.postMessage(testImageBitmapSize());
            break;
        case 'test2':
            self.postMessage(testImageBitmapClr(false, true));
            break;
        case 'test3':
            self.postMessage(testImageBitmapClr(true, true));
            break;
        case 'test4':
            self.postMessage(testImageBitmapClr(true, false));
            break;
        case 'test5':
            self.postMessage(testLineWidthNotAltered());
            break;
        case 'test6':
            self.postMessage(testTransformPreserved());
            break;
        case 'test7':
            var offscreenCanvas = new OffscreenCanvas(10, 10);
            self.postMessage({offscreenCanvas: offscreenCanvas}, [offscreenCanvas]);
            self.postMessage(isInvalidStateError("offscreenCanvas.transferToImageBitmap()", offscreenCanvas));
            break;
        case 'test8':
            self.postMessage(testException());
            break;
    }
};

</script>

<script>
function makeWorker(test) {
    var blob = new Blob([document.getElementById("myWorker").textContent]);
    var worker = new Worker(URL.createObjectURL(blob));
    worker.onerror = test.unreached_func("error");
    return worker;
}

function drawImageBitmap(image, x, y)
{
    var drawCanvas = document.createElement('canvas');
    drawCanvas.width = 100;
    drawCanvas.height = 50;
    var dCtx = drawCanvas.getContext('2d');
    dCtx.drawImage(image, 0, 0);
    return dCtx.getImageData(x, y, 1, 1).data;
}

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        assert_true(msg.data);
    }));
    worker.postMessage('test1');
}, "Test that transferToImageBitmap returns an ImageBitmap with correct width and height in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        var clr = drawImageBitmap(msg.data, 50, 25);
        assert_array_equals(clr, [0, 255, 0, 255]);
    }));
    worker.postMessage('test2');
}, "Test that transferToImageBitmap returns an ImageBitmap with correct color in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        var clr = drawImageBitmap(msg.data, 50, 25);
        assert_array_equals(clr, [0, 0, 0, 0]);
    }));
    worker.postMessage('test3');
}, "Test that call transferToImageBitmap twice returns an ImageBitmap with correct color in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        var clr = drawImageBitmap(msg.data, 50, 25);
        assert_array_equals(clr, [0, 0, 0, 255]);
    }));
    worker.postMessage('test4');
}, "Test that call transferToImageBitmap twice on a alpha-disabled context returns an ImageBitmap with correct color in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        assert_true(msg.data);
    }));
    worker.postMessage('test5');
}, "Test that transferToImageBitmap won't change context's property in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        var clr1 = drawImageBitmap(msg.data, 23, 25);
        assert_array_equals(clr1, [0, 255, 0, 255]);
        var clr2 = drawImageBitmap(msg.data, 27, 25);
        assert_array_equals(clr2, [0, 0, 0, 0]);
    }));
    worker.postMessage('test6');
}, "Test that call transferToImageBitmap preserves transform in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        if (msg.data == true || msg.data == false)
            assert_true(msg.data);
    }));
    worker.postMessage('test7');
}, "Test that call transferToImageBitmap on a detached OffscreenCanvas throws an exception in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        assert_true(msg.data);
    }));
    worker.postMessage('test8');
}, "Test that call transferToImageBitmap without a context throws an exception in a worker");

</script>

