diff --git a/scripts/create-reftest-list.js b/scripts/create-reftest-list.js
index 0e4a487..308ab64 100644
--- a/scripts/create-reftest-list.js
+++ b/scripts/create-reftest-list.js
@@ -7,10 +7,16 @@ const slash = require('slash');
 const parseRefTest = require('./parse-reftest');
 const outputPath = 'tests/reftests.js';
 
-const ignoredTests = [
-    '/tests/reftests/background/radial-gradient.html',
-    '/tests/reftests/text/chinese.html'
-];
+const ignoredTests = fs
+    .readFileSync(path.resolve(__dirname, `../tests/reftests/ignore.txt`))
+    .toString()
+    .split('\n')
+    .filter(l => l.length)
+    .reduce((acc, l) => {
+        const m = l.match(/^(\[(.+)\])?(.+)$/i);
+        acc[m[3]] = m[2] ? m[2].split(',') : [];
+        return acc;
+    }, {});
 
 glob(
     '../tests/reftests/**/*.html',
@@ -27,8 +33,7 @@ glob(
         const testList = files.reduce((acc, filename) => {
             const refTestFilename = path.resolve(__dirname, filename.replace(/\.html$/, '.txt'));
             const name = `/${slash(path.relative('../', filename))}`;
-            if (ignoredTests.indexOf(name) === -1) {
-                console.log(name);
+            if (!Array.isArray(ignoredTests[name]) || ignoredTests[name].length) {
                 acc[name] = fs.existsSync(refTestFilename)
                     ? parseRefTest(fs.readFileSync(refTestFilename).toString())
                     : null;
@@ -36,12 +41,11 @@ glob(
                 console.log(`IGNORED: ${name}`);
             }
 
-
             return acc;
         }, {});
         fs.writeFileSync(
             path.resolve(__dirname, `../${outputPath}`),
-            `module.exports = ${JSON.stringify(testList, null, 4)};`
+            `module.exports = ${JSON.stringify({testList, ignoredTests}, null, 4)};`
         );
 
         console.log(`${outputPath} updated`);
diff --git a/scripts/create-reftests.js b/scripts/create-reftests.js
index 9d38f8b..168529a 100644
--- a/scripts/create-reftests.js
+++ b/scripts/create-reftests.js
@@ -10,7 +10,7 @@ app.use('/', express.static(path.resolve(__dirname, '../')));
 const listener = app.listen(0, () => {
     async function run() {
         const chromeless = new Chromeless();
-        const tests = Object.keys(reftests);
+        const tests = Object.keys(reftests.testList);
         let i = 0;
         while (tests[i]) {
             const filename = tests[i];
diff --git a/tests/reftests/ignore.txt b/tests/reftests/ignore.txt
new file mode 100644
index 0000000..f037e33
--- /dev/null
+++ b/tests/reftests/ignore.txt
@@ -0,0 +1,5 @@
+/tests/reftests/background/radial-gradient.html
+/tests/reftests/text/chinese.html
+[Edge]/tests/reftests/acid2.html
+[Edge]/tests/reftests/pseudoelements.html
+[Edge]/tests/reftests/text/multiple.html
diff --git a/tests/testrunner.js b/tests/testrunner.js
index 64f3ec6..ffa9539 100644
--- a/tests/testrunner.js
+++ b/tests/testrunner.js
@@ -1,8 +1,10 @@
 import {expect} from 'chai';
 import parseRefTest from '../scripts/parse-reftest';
 import reftests from './reftests';
+import querystring from 'querystring';
 
 const DOWNLOAD_REFTESTS = true;
+const query = querystring.parse(location.search.replace(/^\?/, ''));
 
 const downloadResult = (filename, data) => {
     const downloadUrl = URL.createObjectURL(new Blob([data], {type: 'text/plain'}));
@@ -32,7 +34,7 @@ const assertPath = (result, expected, desc) => {
                 case 'Circle':
                     expect(r.x).to.be.closeTo(e.x, 10, `${desc} Circle #${i + 1} x`);
                     expect(r.y).to.be.closeTo(e.y, 10, `${desc} Circle #${i + 1} y`);
-                    expect(r.r).to.equal(e.r, `${desc} Circle #${i + 1} r`);
+                    expect(r.r).to.be.closeTo(e.r, 5, `${desc} Circle #${i + 1} r`);
                     break;
                 case 'Vector':
                     expect(r.x).to.be.closeTo(e.x, 10, `${desc} vector #${i + 1} x`);
@@ -67,223 +69,270 @@ const assertPath = (result, expected, desc) => {
             );
         });
     } else {
-        Object.keys(reftests).forEach(url => {
-            describe(url, function() {
-                this.timeout(30000);
-                var windowWidth = 800;
-                var windowHeight = 600;
-                var testContainer = document.createElement('iframe');
-                var REFTEST = reftests[url];
-                testContainer.width = windowWidth;
-                testContainer.height = windowHeight;
-                testContainer.style.visibility = 'hidden';
-                testContainer.style.position = 'fixed';
-                testContainer.style.left = '10000px';
+        Object.keys(reftests.testList)
+            .filter(test => {
+                return (
+                    !Array.isArray(reftests.ignoredTests[test]) ||
+                    reftests.ignoredTests[test].indexOf(query.browser) === -1
+                );
+            })
+            .forEach(url => {
+                describe(url, function() {
+                    this.timeout(30000);
+                    const windowWidth = 800;
+                    const windowHeight = 600;
+                    const testContainer = document.createElement('iframe');
+                    const REFTEST = reftests.testList[url];
+                    testContainer.width = windowWidth;
+                    testContainer.height = windowHeight;
+                    testContainer.style.visibility = 'hidden';
+                    testContainer.style.position = 'fixed';
+                    testContainer.style.left = '10000px';
 
-                before(done => {
-                    testContainer.onload = () => done();
+                    before(done => {
+                        testContainer.onload = () => done();
 
-                    testContainer.src = url + '?selenium&run=false&reftest&' + Math.random();
-                    if (hasHistoryApi) {
-                        // Chrome does not resolve relative background urls correctly inside of a nested iframe
-                        history.replaceState(null, '', url);
-                    }
+                        testContainer.src = url + '?selenium&run=false&reftest&' + Math.random();
+                        if (hasHistoryApi) {
+                            // Chrome does not resolve relative background urls correctly inside of a nested iframe
+                            history.replaceState(null, '', url);
+                        }
 
-                    document.body.appendChild(testContainer);
-                });
-                after(() => {
-                    if (hasHistoryApi) {
-                        history.replaceState(null, '', testRunnerUrl);
-                    }
-                    document.body.removeChild(testContainer);
-                });
-                it('Should render untainted canvas', () => {
-                    return testContainer.contentWindow
-                        .html2canvas(testContainer.contentWindow.document.documentElement, {
-                            removeContainer: true,
-                            target: [
-                                new testContainer.contentWindow.html2canvas.CanvasRenderer(),
-                                new testContainer.contentWindow.RefTestRenderer()
-                            ]
-                        })
-                        .then(([canvas, result]) => {
-                            try {
-                                canvas
-                                    .getContext('2d')
-                                    .getImageData(0, 0, canvas.width, canvas.height);
-                            } catch (e) {
-                                return Promise.reject('Canvas is tainted');
-                            }
+                        document.body.appendChild(testContainer);
+                    });
+                    after(() => {
+                        if (hasHistoryApi) {
+                            history.replaceState(null, '', testRunnerUrl);
+                        }
+                        document.body.removeChild(testContainer);
+                    });
+                    it('Should render untainted canvas', () => {
+                        return testContainer.contentWindow
+                            .html2canvas(testContainer.contentWindow.document.documentElement, {
+                                removeContainer: true,
+                                target: [
+                                    new testContainer.contentWindow.html2canvas.CanvasRenderer(),
+                                    new testContainer.contentWindow.RefTestRenderer()
+                                ]
+                            })
+                            .then(([canvas, result]) => {
+                                try {
+                                    canvas
+                                        .getContext('2d')
+                                        .getImageData(0, 0, canvas.width, canvas.height);
+                                } catch (e) {
+                                    return Promise.reject('Canvas is tainted');
+                                }
 
-                            const delta = 10;
+                                const delta = 10;
 
-                            if (REFTEST) {
-                                const RESULTS = parseRefTest(result);
-                                REFTEST.forEach(({action, line, ...args}, i) => {
-                                    const RESULT = RESULTS[i];
-                                    expect(RESULT.action).to.equal(action, `Line ${line}`);
+                                if (REFTEST) {
+                                    const RESULTS = parseRefTest(result);
+                                    REFTEST.forEach(({action, line, ...args}, i) => {
+                                        const RESULT = RESULTS[i];
+                                        expect(RESULT.action).to.equal(action, `Line ${line}`);
 
-                                    const desc = `Line ${line} ${action}`;
+                                        const desc = `Line ${line} ${action}`;
 
-                                    switch (action) {
-                                        case 'Window':
-                                            expect(RESULT.width).to.equal(
-                                                args.width,
-                                                `${desc} width`
-                                            );
-                                            expect(RESULT.height).to.be.closeTo(
-                                                args.height,
-                                                delta,
-                                                `${desc} height`
-                                            );
-                                            break;
+                                        switch (action) {
+                                            case 'Window':
+                                                expect(RESULT.width).to.equal(
+                                                    args.width,
+                                                    `${desc} width`
+                                                );
+                                                expect(RESULT.height).to.be.closeTo(
+                                                    args.height,
+                                                    delta,
+                                                    `${desc} height`
+                                                );
+                                                break;
 
-                                        case 'Rectangle':
-                                            expect(RESULT.x).to.equal(args.x, `${desc} x`);
-                                            expect(RESULT.y).to.equal(args.y, `${desc} y`);
-                                            expect(RESULT.width).to.equal(
-                                                args.width,
-                                                `${desc} width`
-                                            );
-                                            expect(RESULT.height).to.be.closeTo(
-                                                args.height,
-                                                delta,
-                                                `${desc} height`
-                                            );
-                                            break;
+                                            case 'Rectangle':
+                                                expect(RESULT.x).to.equal(args.x, `${desc} x`);
+                                                expect(RESULT.y).to.equal(args.y, `${desc} y`);
+                                                expect(RESULT.width).to.equal(
+                                                    args.width,
+                                                    `${desc} width`
+                                                );
+                                                expect(RESULT.height).to.be.closeTo(
+                                                    args.height,
+                                                    delta,
+                                                    `${desc} height`
+                                                );
+                                                break;
 
-                                        case 'Fill':
-                                            expect(RESULT.color).to.equal(
-                                                args.color,
-                                                `${desc} color`
-                                            );
-                                            break;
+                                            case 'Fill':
+                                                expect(RESULT.color).to.equal(
+                                                    args.color,
+                                                    `${desc} color`
+                                                );
+                                                break;
 
-                                        case 'Opacity':
-                                            expect(RESULT.opacity).to.equal(
-                                                args.opacity,
-                                                `${desc} opacity`
-                                            );
-                                            break;
+                                            case 'Opacity':
+                                                expect(RESULT.opacity).to.equal(
+                                                    args.opacity,
+                                                    `${desc} opacity`
+                                                );
+                                                break;
 
-                                        case 'Text':
-                                            expect(RESULT.font).to.equal(args.font, `${desc} font`);
-                                            break;
+                                            case 'Text':
+                                                expect(RESULT.font).to.equal(
+                                                    args.font,
+                                                    `${desc} font`
+                                                );
+                                                break;
 
-                                        case 'T':
-                                            expect(RESULT.x).to.be.closeTo(args.x, 10, `${desc} x`);
-                                            expect(RESULT.y).to.be.closeTo(args.y, 10, `${desc} y`);
-                                            expect(RESULT.text).to.equal(args.text, `${desc} text`);
-                                            break;
+                                            case 'T':
+                                                expect(RESULT.x).to.be.closeTo(
+                                                    args.x,
+                                                    10,
+                                                    `${desc} x`
+                                                );
+                                                expect(RESULT.y).to.be.closeTo(
+                                                    args.y,
+                                                    10,
+                                                    `${desc} y`
+                                                );
+                                                expect(RESULT.text).to.equal(
+                                                    args.text,
+                                                    `${desc} text`
+                                                );
+                                                break;
 
-                                        case 'Transform':
-                                            expect(RESULT.x).to.be.closeTo(args.x, 10, `${desc} x`);
-                                            expect(RESULT.y).to.be.closeTo(args.y, 10, `${desc} y`);
-                                            expect(RESULT.matrix).to.equal(
-                                                args.matrix,
-                                                `${desc} matrix`
-                                            );
-                                            break;
+                                            case 'Transform':
+                                                expect(RESULT.x).to.be.closeTo(
+                                                    args.x,
+                                                    10,
+                                                    `${desc} x`
+                                                );
+                                                expect(RESULT.y).to.be.closeTo(
+                                                    args.y,
+                                                    10,
+                                                    `${desc} y`
+                                                );
+                                                expect(RESULT.matrix).to.equal(
+                                                    args.matrix,
+                                                    `${desc} matrix`
+                                                );
+                                                break;
 
-                                        case 'Repeat':
-                                            expect(RESULT.x).to.be.closeTo(args.x, 10, `${desc} x`);
-                                            expect(RESULT.y).to.be.closeTo(args.y, 10, `${desc} y`);
-                                            expect(RESULT.width).to.be.closeTo(
-                                                args.width,
-                                                3,
-                                                `${desc} width`
-                                            );
-                                            expect(RESULT.height).to.be.closeTo(
-                                                args.height,
-                                                3,
-                                                `${desc} height`
-                                            );
-                                            expect(RESULT.imageSrc).to.equal(
-                                                args.imageSrc,
-                                                `${desc} imageSrc`
-                                            );
-                                            assertPath(RESULT.path, args.path, desc);
-                                            break;
+                                            case 'Repeat':
+                                                expect(RESULT.x).to.be.closeTo(
+                                                    args.x,
+                                                    10,
+                                                    `${desc} x`
+                                                );
+                                                expect(RESULT.y).to.be.closeTo(
+                                                    args.y,
+                                                    10,
+                                                    `${desc} y`
+                                                );
+                                                expect(RESULT.width).to.be.closeTo(
+                                                    args.width,
+                                                    3,
+                                                    `${desc} width`
+                                                );
+                                                expect(RESULT.height).to.be.closeTo(
+                                                    args.height,
+                                                    3,
+                                                    `${desc} height`
+                                                );
+                                                expect(RESULT.imageSrc).to.equal(
+                                                    args.imageSrc,
+                                                    `${desc} imageSrc`
+                                                );
+                                                assertPath(RESULT.path, args.path, desc);
+                                                break;
 
-                                        case 'Gradient':
-                                            expect(RESULT.x).to.be.closeTo(args.x, 10, `${desc} x`);
-                                            expect(RESULT.y).to.be.closeTo(args.y, 10, `${desc} y`);
-                                            expect(RESULT.x0).to.be.closeTo(
-                                                args.x0,
-                                                5,
-                                                `${desc} x0`
-                                            );
-                                            expect(RESULT.y0).to.be.closeTo(
-                                                args.y0,
-                                                5,
-                                                `${desc} y0`
-                                            );
-                                            expect(RESULT.x1).to.be.closeTo(
-                                                args.x1,
-                                                5,
-                                                `${desc} x1`
-                                            );
-                                            expect(RESULT.y1).to.be.closeTo(
-                                                args.y1,
-                                                5,
-                                                `${desc} y1`
-                                            );
-                                            expect(RESULT.stops).to.equal(
-                                                args.stops,
-                                                `${desc} stops`
-                                            );
-                                            expect(RESULT.width).to.equal(
-                                                args.width,
-                                                `${desc} width`
-                                            );
-                                            expect(RESULT.height).to.equal(
-                                                args.height,
-                                                `${desc} height`
-                                            );
+                                            case 'Gradient':
+                                                expect(RESULT.x).to.be.closeTo(
+                                                    args.x,
+                                                    10,
+                                                    `${desc} x`
+                                                );
+                                                expect(RESULT.y).to.be.closeTo(
+                                                    args.y,
+                                                    10,
+                                                    `${desc} y`
+                                                );
+                                                expect(RESULT.x0).to.be.closeTo(
+                                                    args.x0,
+                                                    5,
+                                                    `${desc} x0`
+                                                );
+                                                expect(RESULT.y0).to.be.closeTo(
+                                                    args.y0,
+                                                    5,
+                                                    `${desc} y0`
+                                                );
+                                                expect(RESULT.x1).to.be.closeTo(
+                                                    args.x1,
+                                                    5,
+                                                    `${desc} x1`
+                                                );
+                                                expect(RESULT.y1).to.be.closeTo(
+                                                    args.y1,
+                                                    5,
+                                                    `${desc} y1`
+                                                );
+                                                expect(RESULT.stops).to.equal(
+                                                    args.stops,
+                                                    `${desc} stops`
+                                                );
+                                                expect(RESULT.width).to.equal(
+                                                    args.width,
+                                                    `${desc} width`
+                                                );
+                                                expect(RESULT.height).to.equal(
+                                                    args.height,
+                                                    `${desc} height`
+                                                );
 
-                                            break;
+                                                break;
 
-                                        case 'Draw image':
-                                            expect(RESULT.imageSrc).to.equal(
-                                                args.imageSrc,
-                                                `${desc} stops`
-                                            );
-                                            expect(RESULT.sx).to.equal(args.sx, `${desc} sx`);
-                                            expect(RESULT.sy).to.equal(args.sy, `${desc} sy`);
-                                            expect(RESULT.dx).to.equal(args.dx, `${desc} dx`);
-                                            expect(RESULT.dy).to.equal(args.dy, `${desc} dy`);
-                                            expect(RESULT.sw).to.equal(args.sw, `${desc} sw`);
-                                            expect(RESULT.sh).to.equal(args.sh, `${desc} sh`);
-                                            expect(RESULT.dw).to.equal(args.dw, `${desc} dw`);
-                                            expect(RESULT.dh).to.equal(args.dh, `${desc} dh`);
-                                            break;
+                                            case 'Draw image':
+                                                expect(RESULT.imageSrc).to.equal(
+                                                    args.imageSrc,
+                                                    `${desc} stops`
+                                                );
+                                                expect(RESULT.sx).to.equal(args.sx, `${desc} sx`);
+                                                expect(RESULT.sy).to.equal(args.sy, `${desc} sy`);
+                                                expect(RESULT.dx).to.equal(args.dx, `${desc} dx`);
+                                                expect(RESULT.dy).to.equal(args.dy, `${desc} dy`);
+                                                expect(RESULT.sw).to.equal(args.sw, `${desc} sw`);
+                                                expect(RESULT.sh).to.equal(args.sh, `${desc} sh`);
+                                                expect(RESULT.dw).to.equal(args.dw, `${desc} dw`);
+                                                expect(RESULT.dh).to.equal(args.dh, `${desc} dh`);
+                                                break;
 
-                                        case 'Clip':
-                                            assertPath(RESULT.path, args.path, desc);
-                                            break;
+                                            case 'Clip':
+                                                assertPath(RESULT.path, args.path, desc);
+                                                break;
 
-                                        case 'Shape':
-                                            expect(RESULT.color).to.equal(
-                                                args.color,
-                                                `${desc} color`
-                                            );
-                                            assertPath(RESULT.path, args.path, desc);
-                                            break;
+                                            case 'Shape':
+                                                expect(RESULT.color).to.equal(
+                                                    args.color,
+                                                    `${desc} color`
+                                                );
+                                                assertPath(RESULT.path, args.path, desc);
+                                                break;
 
-                                        default:
-                                            console.log(RESULT);
-                                            throw new Error(`Unrecognized action ${action}`);
-                                    }
-                                });
-                            } else if (DOWNLOAD_REFTESTS) {
-                                downloadResult(
-                                    url.slice(url.lastIndexOf('/') + 1).replace(/\.html$/i, '.txt'),
-                                    result
-                                );
-                            }
-                        });
+                                            default:
+                                                console.log(RESULT);
+                                                throw new Error(`Unrecognized action ${action}`);
+                                        }
+                                    });
+                                } else if (DOWNLOAD_REFTESTS) {
+                                    downloadResult(
+                                        url
+                                            .slice(url.lastIndexOf('/') + 1)
+                                            .replace(/\.html$/i, '.txt'),
+                                        result
+                                    );
+                                }
+                            });
+                    });
                 });
             });
-        });
     }
 })();