summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml')
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml680
1 files changed, 680 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
new file mode 100644
index 0000000000..01c83a33e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
@@ -0,0 +1,680 @@
+- name: 2d.filter.value
+ desc: test if ctx.filter works correctly
+ code: |
+ @assert ctx.filter == 'none';
+ ctx.filter = 'blur(5px)';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.save();
+ ctx.filter = 'none';
+ @assert ctx.filter == 'none';
+ ctx.restore();
+ @assert ctx.filter == 'blur(5px)';
+
+ ctx.filter = 'blur(10)';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = 'blur 10px';
+ @assert ctx.filter == 'blur(5px)';
+
+ ctx.filter = 'inherit';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = 'initial';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = 'unset';
+ @assert ctx.filter == 'blur(5px)';
+
+ ctx.filter = '';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = null;
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = undefined;
+ @assert ctx.filter == 'blur(5px)';
+
+ ctx.filter = 'blur( 5px)';
+ assert_equals(ctx.filter, 'blur( 5px)');
+
+- name: 2d.filter.canvasFilterObject.tentative
+ desc: Test CanvasFilter() object
+ canvasType:
+ ['HTMLCanvas']
+ code: |
+ @assert ctx.filter == 'none';
+ ctx.filter = 'blur(5px)';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 5});
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: [1, 2]});
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ ctx.filter = new CanvasFilter([
+ {name: 'gaussianBlur', stdDeviation: 5},
+ {name: 'gaussianBlur', stdDeviation: 10}
+ ]);
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ var canvas2 = document.createElement('canvas');
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.filter = ctx.filter;
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ ctx.filter = 'blur(5px)';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = 'none';
+ @assert ctx.filter == 'none';
+ ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 5});
+ ctx.filter = 'this string is not a filter and should do nothing';
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+
+- name: 2d.filter.canvasFilterObject.tentative
+ desc: Test CanvasFilter() object
+ canvasType: ['OffscreenCanvas', 'Worker']
+ code: |
+ @assert ctx.filter == 'none';
+ ctx.filter = 'blur(5px)';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 5});
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: [1, 2]});
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ ctx.filter = new CanvasFilter([
+ {name: 'gaussianBlur', stdDeviation: 5},
+ {name: 'gaussianBlur', stdDeviation: 10}
+ ]);
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ var canvas2 = new OffscreenCanvas(100, 50);
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.filter = ctx.filter;
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+ ctx.filter = 'blur(5px)';
+ @assert ctx.filter == 'blur(5px)';
+ ctx.filter = 'none';
+ @assert ctx.filter == 'none';
+ ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 5});
+ ctx.filter = 'this string is not a filter and should do nothing';
+ @assert ctx.filter.toString() == '[object CanvasFilter]';
+
+- name: 2d.filter.canvasFilterObject.blur.exceptions.tentative
+ desc: Test exceptions on CanvasFilter() blur.object
+ code: |
+ @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur'});
+ @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: undefined});
+ @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 'foo'});
+ @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: [1,2,3]});
+ @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: NaN});
+ @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: {}});
+
+- name: 2d.filter.canvasFilterObject.colorMatrix.tentative
+ desc: Test the functionality of ColorMatrix filters in CanvasFilter objects
+ code: |
+ @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: undefined});
+ @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: 'foo'});
+ @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: null});
+ @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3]});
+ @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 'a']});
+ @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, Infinity]});
+ ctx.fillStyle = '#f00';
+ ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 0});
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 10,10 ==~ 255,0,0,255;
+ ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 90});
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 10,10 ==~ 0,91,0,255;
+ ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 180});
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 10,10 ==~ 0,109,109,255;
+ ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 270});
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 10,10 ==~ 109,18,255,255;
+ ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'saturate', values: 0.5});
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 10,10 ==~ 155,27,27,255;
+ ctx.clearRect(0, 0, 100, 50);
+ ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'luminanceToAlpha'});
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 10,10 ==~ 0,0,0,54;
+ ctx.filter = new CanvasFilter({name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]});
+ ctx.fillRect(0, 0, 50, 25);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 25);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 25, 50, 25);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(50, 25, 50, 25);
+ @assert pixel 10,10 ==~ 0,255,0,255;
+ @assert pixel 60,10 ==~ 0,255,0,255;
+ @assert pixel 10,30 ==~ 0,255,0,255;
+ @assert pixel 60,30 ==~ 0,255,0,255;
+
+- name: 2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative
+ desc: Test exceptions on CanvasFilter() convolveMatrix
+ code: |
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix'});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', divisor: 2});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: null});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: 1});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: []});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], []]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 2], []]});
+ @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]});
+ // This should not throw an error
+ ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[]]});
+ ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1]]});
+
+- name: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative
+ desc: Test pixels on CanvasFilter() componentTransfer with linear type
+ code: |
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, slopes, intercepts) {
+ return [
+ Math.max(0, Math.min(1, inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
+ Math.max(0, Math.min(1, inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
+ Math.max(0, Math.min(1, inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
+ ];
+ }
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
+ funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
+ funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (const color of inputColors) {
+ let outputColor = getColor(color, slopes, intercepts);
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(0, 0, 10, 10);
+ _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ }
+
+- name: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative
+ desc: Test pixels on CanvasFilter() componentTransfer with identity type
+ code: |
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'identity'},
+ funcG: {type: 'identity'},
+ funcB: {type: 'identity'},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (const color of inputColors) {
+ ctx.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1)`,
+ ctx.fillRect(0, 0, 10, 10);
+ _assertPixel(canvas, 5, 5, color[0],color[1],color[2],255);
+ }
+
+- name: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative
+ desc: Test pixels on CanvasFilter() componentTransfer with gamma type
+ code: |
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, amplitude, exponent, offset) {
+ return [
+ Math.max(0, Math.min(1, Math.pow(inputColor[0]/255, exponent[0]) * amplitude[0] + offset[0])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[1]/255, exponent[1]) * amplitude[1] + offset[1])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[2]/255, exponent[2]) * amplitude[2] + offset[2])) * 255,
+ ];
+ }
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'gamma', amplitude: amplitudes[0], exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1], exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2], exponent: exponents[2], offset: offsets[2]},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (const color of inputColors) {
+ let outputColor = getColor(color, amplitudes, exponents, offsets);
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(0, 0, 10, 10);
+ _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ }
+
+- name: 2d.filter.canvasFilterObject.componentTransfer.table.tentative
+ desc: Test pixels on CanvasFilter() componentTransfer with table type
+ code: |
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length - 1;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'table', tableValues: tableValuesR},
+ funcG: {type: 'table', tableValues: tableValuesG},
+ funcB: {type: 'table', tableValues: tableValuesB},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (const color of inputColors) {
+ let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(0, 0, 10, 10);
+ _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ }
+
+- name: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative
+ desc: Test pixels on CanvasFilter() componentTransfer with discrete type
+ code: |
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k];
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'discrete', tableValues: tableValuesR},
+ funcG: {type: 'discrete', tableValues: tableValuesG},
+ funcB: {type: 'discrete', tableValues: tableValuesB},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (const color of inputColors) {
+ let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(0, 0, 10, 10);
+ _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ }
+
+- name: 2d.filter.canvasFilterObject.gaussianBlur.tentative
+ desc: Test CanvasFilter() with gaussianBlur.
+ size: [100, 100]
+ code: |
+ ctx.fillStyle = 'teal';
+ ctx.filter = new CanvasFilter({
+ name: 'gaussianBlur',
+ stdDeviation: [{{ blur_x }}, {{blur_y}}],
+ });
+ ctx.fillRect(25, 25, 50, 50);
+ html_reference: |
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="{{ size[0] }}" height="{{ size[1] }}"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="{{ blur_x }} {{blur_y}}" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+ </svg>
+ variants:
+ x-only:
+ blur_x: 4
+ blur_y: 0
+ mostly-x:
+ blur_x: 4
+ blur_y: 1
+ isotropic:
+ blur_x: 4
+ blur_y: 4
+ mostly-y:
+ blur_x: 1
+ blur_y: 4
+ y-only:
+ blur_x: 0
+ blur_y: 4
+
+- name: 2d.filter.canvasFilterObject.dropShadow.tentative
+ desc: Test CanvasFilter() dropShadow object.
+ size: [520, 420]
+ code: |
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(0, 0, {{ size[0] }}, 50);
+ ctx.fillRect(0, 100, {{ size[0] }}, 50);
+ ctx.fillRect(0, 200, {{ size[0] }}, 50);
+ ctx.fillRect(0, 300, {{ size[0] }}, 50);
+
+ ctx.fillStyle = 'crimson';
+
+ // Parameter defaults.
+ ctx.filter = new CanvasFilter({name: 'dropShadow'});
+ ctx.fillRect(10, 10, 80, 80);
+
+ // All parameters specified.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple', floodOpacity: 0.7});
+ ctx.fillRect(110, 10, 80, 80);
+
+ // Named color.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'purple'});
+ ctx.fillRect(10, 110, 80, 80);
+
+ // System color.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'LinkText'});
+ ctx.fillRect(110, 110, 80, 80);
+
+ // Numerical color.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 1)'});
+ ctx.fillRect(210, 110, 80, 80);
+
+ // Transparent floodColor.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)'});
+ ctx.fillRect(310, 110, 80, 80);
+
+ // Transparent floodColor and floodOpacity.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7});
+ ctx.fillRect(410, 110, 80, 80);
+
+ // No blur.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ floodColor: 'purple'});
+ ctx.fillRect(10, 210, 80, 80);
+
+ // Single float blur.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple'});
+ ctx.fillRect(110, 210, 80, 80);
+
+ // Single negative float blur.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ floodColor: 'purple'});
+ ctx.fillRect(210, 210, 80, 80);
+
+ // Two floats (X&Y) blur.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ floodColor: 'purple'});
+ ctx.fillRect(310, 210, 80, 80);
+
+ // Two negative floats (X&Y) blur.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ floodColor: 'purple'});
+ ctx.fillRect(410, 210, 80, 80);
+
+ // Degenerate parameter values.
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ floodColor: 'purple', floodOpacity: [2]});
+ ctx.fillRect(10, 310, 80, 80);
+
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ floodColor: 'purple', floodOpacity: '0.8'});
+ ctx.fillRect(110, 310, 80, 80);
+
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ floodColor: 'purple', floodOpacity: ['0.4']});
+ ctx.fillRect(210, 310, 80, 80);
+ html_reference: |
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width={{ size[0] }} height={{ size[1] }}
+ color-interpolation-filters="sRGB">
+ <rect x=0 y=0 width=100% height=50 fill="teal" />
+ <rect x=0 y=100 width=100% height=50 fill="teal" />
+ <rect x=0 y=200 width=100% height=50 fill="teal" />
+ <rect x=0 y=300 width=100% height=50 fill="teal" />
+
+ <rect x=10 y=10 width=80 height=80 fill="crimson"
+ filter="drop-shadow(2px 2px 2px black)"/>
+ <rect x=110 y=10 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 5px rgba(128, 0, 128, 0.7))"/>
+
+ <rect x=10 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px purple)"/>
+ <rect x=110 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px LinkText)"/>
+ <rect x=210 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 1))"/>
+ <rect x=310 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 0.7))"/>
+ <rect x=410 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 0.49))"/>
+
+ <rect x=10 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+ <rect x=110 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 5px purple)"/>
+ <rect x=210 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+ <filter id="separable-filter"
+ x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx=9 dy=12 stdDeviation="3 5" flood-color="purple"/>
+ </filter>
+ <rect x=310 y=210 width=80 height=80 fill="crimson"
+ filter="url(#separable-filter)"/>
+ <rect x=410 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+
+ <rect x=10 y=310 width=80 height=80 fill="crimson"
+ filter="drop-shadow(-5px 0px 0px purple)"/>
+ <filter id="separable-filter-degenerate"
+ x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx=0 dy=5 stdDeviation="0 3"
+ flood-color="rgba(128, 0, 128, 0.8)"/>
+ </filter>
+ <rect x=110 y=310 width=80 height=80 fill="crimson"
+ filter="url(#separable-filter-degenerate)"/>
+ <rect x=210 y=310 width=80 height=80 fill="crimson"
+ filter="drop-shadow(1px 10px 0px rgba(128, 0, 128, 0.4))"/>
+ </svg>
+
+- name: 2d.filter.canvasFilterObject.dropShadow.exceptions.tentative
+ desc: Test exceptions on CanvasFilter() dropShadow object
+ code: |
+ @unroll @assert new CanvasFilter({\-
+ name: 'dropShadow', \-
+ <dx | dy | floodOpacity>: \-
+ <10 | -1 | 0.5 | null | true | false | [] | [20] | '30'>});
+ @unroll @assert new CanvasFilter({\-
+ name: 'dropShadow', \-
+ <stdDeviation>: \-
+ <10 | -1 | 0.5 | null | true | false | [] | [20] | '30' | \-
+ [10, -1] | [0.5, null] | [true, false] | [[], [20]] | \-
+ ['30', ['40']]>});
+ @unroll @assert new CanvasFilter({\-
+ name: 'dropShadow', \-
+ <floodColor>: \-
+ <'red' | 'canvas' | 'rgba(4, -3, 0.5, 1)' | '#aabbccdd' | '#abcd'>});
+
+ @unroll @assert throws TypeError new CanvasFilter({\-
+ name: 'dropShadow', \-
+ <dx | dy | floodOpacity>: \-
+ <NaN | Infinity | -Infinity | undefined | 'test' | {} | [1, 2]>});
+ @unroll @assert throws TypeError new CanvasFilter({\-
+ name: 'dropShadow', \-
+ <stdDeviation>: \-
+ <NaN | Infinity | -Infinity | undefined | 'test' | {} | [1, 2, 3] | \-
+ [1, NaN] | [1, Infinity] | [1, -Infinity] | [1, undefined] | \-
+ [1, 'test'] | [1, {}] | [1, [2, 3]]>});
+ @unroll @assert throws TypeError new CanvasFilter({\-
+ name: 'dropShadow', \-
+ <floodColor>: \-
+ <'test' | 'rgba(NaN, 3, 2, 1)' | 10 | undefined | null | NaN>});
+
+- name: 2d.filter.canvasFilterObject.turbulence.inputTypes.tentative
+ desc: Test exceptions on CanvasFilter() turbulence object
+ code: |
+ const errorTestCases = [
+ {baseFrequency: {}},
+ {baseFrequency: -1},
+ {baseFrequency: [0, -1]},
+ {baseFrequency: NaN},
+ {baseFrequency: Infinity},
+ {baseFrequency: undefined},
+ {baseFrequency: -Infinity},
+ {baseFrequency: 'test'},
+
+ {numOctaves: {}},
+ {numOctaves: -1},
+ {numOctaves: NaN},
+ {numOctaves: Infinity},
+ {numOctaves: undefined},
+ {numOctaves: -Infinity},
+ {numOctaves: [1, 1]},
+ {numOctaves: 'test'},
+
+ {seed: {}},
+ {seed: NaN},
+ {seed: Infinity},
+ {seed: undefined},
+ {seed: -Infinity},
+ {seed: [1, 1]},
+ {seed: 'test'},
+
+ {stitchTiles: {}},
+ {stitchTiles: NaN},
+ {stitchTiles: Infinity},
+ {stitchTiles: undefined},
+ {stitchTiles: -Infinity},
+ {stitchTiles: [1, 1]},
+ {stitchTiles: 'test'},
+ {stitchTiles: null},
+ {stitchTiles: []},
+ {stitchTiles: [10]},
+ {stitchTiles: 30},
+ {stitchTiles: false},
+ {stitchTiles: true},
+ {stitchTiles: '10'},
+ {stitchTiles: -1},
+
+ {type: {}},
+ {type: NaN},
+ {type: Infinity},
+ {type: undefined},
+ {type: -Infinity},
+ {type: [1, 1]},
+ {type: 'test'},
+ {type: null},
+ {type: []},
+ {type: [10]},
+ {type: 30},
+ {type: false},
+ {type: true},
+ {type: '10'},
+ {type: -1},
+ ]
+
+ // null and [] = 0 when parsed as number
+ const workingTestCases = [
+ {baseFrequency: null},
+ {baseFrequency: []},
+ {baseFrequency: [10]},
+ {baseFrequency: [10, 3]},
+ {baseFrequency: 30},
+ {baseFrequency: false},
+ {baseFrequency: true},
+ {baseFrequency: '10'},
+
+ {numOctaves: null},
+ {numOctaves: []},
+ {numOctaves: [10]},
+ {numOctaves: 30},
+ {numOctaves: false},
+ {numOctaves: true},
+ {numOctaves: '10'},
+
+ {seed: null},
+ {seed: []},
+ {seed: [10]},
+ {seed: 30},
+ {seed: false},
+ {seed: true},
+ {seed: '10'},
+ {seed: -1},
+
+ {stitchTiles: 'stitch'},
+ {stitchTiles: 'noStitch'},
+
+ {type: 'fractalNoise'},
+ {type: 'turbulence'},
+ ]
+
+ for (testCase of errorTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ @assert throws TypeError new CanvasFilter(filterOptions);
+ }
+
+ for (testCase of workingTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ @assert new CanvasFilter(filterOptions) != null;
+ }