| <html> |
| <head> |
| <title>A canvas globalCompositeOperation test with alpha blending</title> |
| <!-- This test was inspired by http://canvex.lazyilluminati.com/misc/compositex.html --> |
| <script type="application/x-javascript"> |
| if (window.testRunner) { |
| testRunner.dumpAsText(); |
| testRunner.waitUntilDone(); |
| } |
| |
| var compositeTypes = [ |
| 'source-over','source-in','source-out','source-atop', |
| 'destination-over','destination-in','destination-out','destination-atop', |
| 'lighter','copy','xor' |
| ]; |
| var inputColors = [ |
| { source: [255, 0, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 255], destination: [0, 255, 0, 0] }, |
| { source: [255, 0, 0, 255], destination: [0, 255, 0, 1] }, |
| { source: [0, 255, 0, 0], destination: [255, 0, 0, 255] }, |
| { source: [0, 255, 0, 1], destination: [255, 0, 0, 255] }, |
| { source: [255, 0, 0, 0], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 127], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 255], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 127], destination: [0, 255, 0, 255] }, |
| { source: [127, 0, 0, 255], destination: [0, 127, 0, 127] }, |
| { source: [127, 0, 0, 127], destination: [0, 127, 0, 255] }, |
| { source: [255, 0, 0, 127], destination: [255, 0, 0, 63] }, |
| { source: [255, 127, 0, 32], destination: [255, 63, 0, 63] }, |
| { source: [255, 0, 0, 191], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 255, 191], destination: [0, 255, 255, 127] } |
| ]; |
| var expectedColors = [ |
| [ |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 255, 0, 1] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 255, 0, 1], composition: [254, 1, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [170, 84, 0, 190], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 127], composition: [127, 128, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [127, 0, 0, 255], composition: [127, 0, 0, 255], destination: [0, 126, 0, 127] }, |
| { source: [126, 0, 0, 127], composition: [63, 63, 0, 255], destination: [0, 127, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 158], destination: [255, 0, 0, 63] }, |
| { source: [255, 127, 0, 32], composition: [255, 85, 0, 87], destination: [255, 64, 0, 63] }, |
| { source: [255, 0, 0, 191], composition: [219, 35, 0, 222], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 255, 191], composition: [219, 35, 255, 222], destination: [0, 255, 255, 127] } |
| ], |
| [ |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 64], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [128, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [126, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 32], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 127, 0, 8], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 96], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 255, 96], destination: [0, 0, 0, 0] } |
| ], |
| [ |
| { source: [255, 0, 0, 255], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 254], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 255, 0, 1], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 64], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 128], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 127], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [127, 0, 0, 255], composition: [127, 0, 0, 128], destination: [0, 0, 0, 0] }, |
| { source: [126, 0, 0, 127], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 96], destination: [0, 0, 0, 0] }, |
| { source: [255, 127, 0, 32], composition: [255, 132, 0, 25], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 191], composition: [255, 0, 0, 96], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 255, 191], composition: [255, 0, 255, 96], destination: [0, 0, 0, 0] } |
| ], |
| [ |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 1], destination: [0, 255, 0, 1] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [254, 1, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [126, 126, 0, 127], destination: [0, 255, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 127], destination: [0, 255, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [127, 128, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [128, 0, 0, 127], destination: [0, 126, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [63, 63, 0, 255], destination: [0, 127, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 63], destination: [255, 0, 0, 63] }, |
| { source: [0, 0, 0, 0], composition: [255, 68, 0, 63], destination: [255, 64, 0, 63] }, |
| { source: [0, 0, 0, 0], composition: [190, 62, 0, 127], destination: [0, 255, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [190, 62, 255, 127], destination: [0, 255, 255, 127] } |
| ], |
| [ |
| { source: [255, 0, 0, 255], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [254, 1, 0, 255], destination: [0, 255, 0, 1] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 255, 0, 1], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [84, 170, 0, 190], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 255], composition: [128, 127, 0, 255], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 127], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [127, 0, 0, 255], composition: [63, 63, 0, 255], destination: [0, 126, 0, 127] }, |
| { source: [126, 0, 0, 127], composition: [0, 127, 0, 255], destination: [0, 127, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 158], destination: [255, 0, 0, 63] }, |
| { source: [255, 127, 0, 32], composition: [255, 82, 0, 87], destination: [255, 64, 0, 63] }, |
| { source: [255, 0, 0, 191], composition: [109, 145, 0, 222], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 255, 191], composition: [109, 145, 255, 222], destination: [0, 255, 255, 127] } |
| ], |
| [ |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 1], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 1], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 64], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 126, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 128, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 32], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [255, 95, 0, 8], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 96], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 255, 96], destination: [0, 0, 0, 0] } |
| ], |
| [ |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 255, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 255, 0, 1] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 254], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 64], destination: [0, 255, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 255, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 128], destination: [0, 255, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 126, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [0, 127, 0, 128], destination: [0, 127, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 32], destination: [255, 0, 0, 63] }, |
| { source: [0, 0, 0, 0], composition: [255, 63, 0, 56], destination: [255, 64, 0, 63] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 32], destination: [0, 255, 0, 127] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 255, 32], destination: [0, 255, 255, 127] } |
| ], |
| [ |
| { source: [255, 0, 0, 255], composition: [0, 255, 0, 255], destination: [0,0,0,0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [254, 1, 0, 255], destination: [0,0,0,0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0,0,0,0] }, |
| { source: [0, 255, 0, 1], composition: [255, 0, 0, 1], destination: [0,0,0,0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0,0,0,0] }, |
| { source: [255, 0, 0, 127], composition: [126, 126, 0, 127], destination: [0,0,0,0] }, |
| { source: [255, 0, 0, 255], composition: [128, 127, 0, 255], destination: [0,0,0,0] }, |
| { source: [255, 0, 0, 127], composition: [0, 255, 0, 127], destination: [0,0,0,0] }, |
| { source: [127, 0, 0, 255], composition: [63, 63, 0, 255], destination: [0,0,0,0] }, |
| { source: [126, 0, 0, 127], composition: [0, 126, 0, 127], destination: [0,0,0,0] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0,0,0,0] }, |
| { source: [255, 127, 0, 32], composition: [255, 111, 0, 32], destination: [0,0,0,0] }, |
| { source: [255, 0, 0, 191], composition: [126, 126, 0, 191], destination: [0,0,0,0] }, |
| { source: [255, 0, 255, 191], composition: [126, 126, 255, 191], destination: [0,0,0,0] } |
| ], |
| [ |
| { source: [255, 0, 0, 255], composition: [255, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 1, 0, 255], destination: [0, 255, 0, 1] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 255, 0, 1], composition: [255, 1, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [127, 127, 0, 254], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 255], composition: [255, 127, 0, 255], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 127], composition: [127, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [127, 0, 0, 255], composition: [127, 63, 0, 255], destination: [0, 126, 0, 127] }, |
| { source: [126, 0, 0, 127], composition: [63, 127, 0, 255], destination: [0, 127, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 190], destination: [255, 0, 0, 63] }, |
| { source: [255, 127, 0, 32], composition: [255, 85, 0, 95], destination: [255, 64, 0, 63] }, |
| { source: [255, 0, 0, 191], composition: [191, 127, 0, 255], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 255, 191], composition: [191, 127, 255, 255], destination: [0, 255, 255, 127] } |
| ], |
| [ |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [0, 255, 0, 1], composition: [0, 255, 0, 1], destination: [0, 0, 0, 0] }, |
| { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [127, 0, 0, 255], composition: [127, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [126, 0, 0, 127], composition: [126, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] }, |
| { source: [255, 127, 0, 32], composition: [255, 127, 0, 32], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 191], composition: [255, 0, 0, 191], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 255, 191], composition: [255, 0, 255, 191], destination: [0, 0, 0, 0] } |
| ], |
| [ |
| { source: [255, 0, 0, 255], composition: [0, 0, 0, 0], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 254], destination: [0, 255, 0, 1] }, |
| { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] }, |
| { source: [0, 255, 0, 1], composition: [255, 0, 0, 254], destination: [255, 0, 0, 255] }, |
| { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [126, 126, 0, 127], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 255], composition: [255, 0, 0, 128], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 0, 127], composition: [0, 255, 0, 128], destination: [0, 255, 0, 255] }, |
| { source: [127, 0, 0, 255], composition: [127, 0, 0, 128], destination: [0, 126, 0, 127] }, |
| { source: [126, 0, 0, 127], composition: [0, 125, 0, 128], destination: [0, 127, 0, 255] }, |
| { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [255, 0, 0, 63] }, |
| { source: [255, 127, 0, 32], composition: [255, 83, 0, 79], destination: [255, 64, 0, 63] }, |
| { source: [255, 0, 0, 191], composition: [190, 62, 0, 127], destination: [0, 255, 0, 127] }, |
| { source: [255, 0, 255, 191], composition: [190, 62, 255, 127], destination: [0, 255, 255, 127] } |
| ] |
| ]; |
| |
| // Compare two colors with a few margin. |
| function isDifferentColor(actualColor, expectedColor) |
| { |
| var actualAlpha = actualColor[3]; |
| var expectedAlpha = expectedColor[3]; |
| if (Math.abs(actualColor - expectedColor) > 3) return true; |
| // For the value of RGB, we compare the values the users actually see. |
| if (Math.abs(actualColor[0] * actualAlpha / 256 - expectedColor[0] * expectedAlpha / 256) > 3) return true; |
| if (Math.abs(actualColor[1] * actualAlpha / 256 - expectedColor[1] * expectedAlpha / 256) > 3) return true; |
| if (Math.abs(actualColor[2] * actualAlpha / 256 - expectedColor[2] * expectedAlpha / 256) > 3) return true; |
| return false; |
| } |
| |
| function getRGBAString(a) |
| { |
| return "rgba(" + [a[0], a[1], a[2], a[3] / 255.0].join(",") + ")"; |
| } |
| |
| function drawTable(drawPolicy) |
| { |
| var tableElement = document.createElement("table"); |
| |
| // Create a header for source color. |
| var trElement = document.createElement("tr"); |
| tableElement.appendChild(trElement); |
| trElement.appendChild(document.createElement("th")); |
| for (var column = 0; column < inputColors.length; column++) { |
| var inputColor = inputColors[column]; |
| var thElement = document.createElement("th"); |
| thElement.setAttribute("colspan", "2"); |
| thElement.textContent = "src " + inputColor.source.join(", "); |
| trElement.appendChild(thElement); |
| } |
| |
| // Create a header for destination color. |
| trElement = document.createElement("tr"); |
| tableElement.appendChild(trElement); |
| trElement.appendChild(document.createElement("th")); |
| for (var column = 0; column < inputColors.length; column++) { |
| var inputColor = inputColors[column]; |
| var thElement = document.createElement("th"); |
| thElement.setAttribute("colspan", "2"); |
| thElement.textContent = "dst " + inputColor.destination.join(", "); |
| trElement.appendChild(thElement); |
| } |
| |
| var resultsElement = document.getElementById("results"); |
| var titleElement = document.createElement("h1"); |
| titleElement.textContent = "Tests for " + drawPolicy.name; |
| resultsElement.appendChild(titleElement); |
| resultsElement.appendChild(tableElement); |
| |
| for (var row = 0; row < compositeTypes.length; row++){ |
| var type = compositeTypes[row]; |
| |
| var trCanvasElement = document.createElement("tr"); |
| var thElement = document.createElement("th"); |
| thElement.setAttribute("rowspan", "2"); |
| thElement.textContent = type; |
| trCanvasElement.appendChild(thElement); |
| var trMessageElement = document.createElement("tr"); |
| tableElement.appendChild(trCanvasElement); |
| tableElement.appendChild(trMessageElement); |
| |
| for (var column = 0; column < inputColors.length; column++) { |
| var test = type + "-" + column; |
| var inputColor = inputColors[column]; |
| var expectedColor = expectedColors[row][column]; |
| |
| // Create canvas element for actual color. |
| var actualCanvasElement = document.createElement("canvas"); |
| actualCanvasElement.setAttribute("width", "25"); |
| actualCanvasElement.setAttribute("height", "25"); |
| tdElement = document.createElement("td"); |
| tdElement.appendChild(actualCanvasElement); |
| trCanvasElement.appendChild(tdElement); |
| |
| // Create canvas element for expected color. |
| var expectedCanvasElement = document.createElement("canvas"); |
| expectedCanvasElement.setAttribute("width", "25"); |
| expectedCanvasElement.setAttribute("height", "25"); |
| var tdElement = document.createElement("td"); |
| tdElement.appendChild(expectedCanvasElement); |
| trCanvasElement.appendChild(tdElement); |
| |
| // Create div element for pass/fail messages. |
| var messageElement = document.createElement("div"); |
| tdElement = document.createElement("td"); |
| tdElement.setAttribute("colspan", "2"); |
| tdElement.appendChild(messageElement); |
| trMessageElement.appendChild(tdElement); |
| |
| var ctx = expectedCanvasElement.getContext("2d"); |
| // Draw expected image. |
| ctx.globalCompositeOperation = "copy"; |
| ctx.fillStyle = getRGBAString(expectedColor.destination); |
| ctx.strokeStyle = getRGBAString(expectedColor.destination); |
| drawPolicy.drawDestination(ctx); |
| ctx.fillStyle = getRGBAString(expectedColor.source); |
| ctx.strokeStyle = getRGBAString(expectedColor.source); |
| drawPolicy.drawSource(ctx); |
| ctx.fillStyle = getRGBAString(expectedColor.composition); |
| ctx.strokeStyle = getRGBAString(expectedColor.composition); |
| drawPolicy.drawComposition(ctx); |
| |
| ctx = actualCanvasElement.getContext("2d"); |
| |
| // Draw destination rectangle. |
| ctx.globalCompositeOperation = "copy"; |
| ctx.fillStyle = getRGBAString(inputColor.destination); |
| ctx.strokeStyle = getRGBAString(inputColor.destination); |
| drawPolicy.drawDestination(ctx); |
| |
| // Draw source rectangle. |
| ctx.globalCompositeOperation = type; |
| ctx.fillStyle = getRGBAString(inputColor.source); |
| ctx.strokeStyle = getRGBAString(inputColor.source); |
| drawPolicy.drawSource(ctx); |
| |
| // Let's check if the results are expected or not. |
| var errorSuffix = ", composite type: " + type + ", source: " + inputColor.source + ", destination: " + inputColor.destination + "<br>"; |
| |
| var results = ""; |
| // Note that (0, 0) may be affected by anti-alias. |
| var img = ctx.getImageData(1, 1, 1, 1).data; |
| var actualColor = [img[0], img[1], img[2], img[3]]; |
| if (isDifferentColor(actualColor, expectedColor.source)) { |
| results += "Unexpected source! expected: " + expectedColor.source + " actual: " + actualColor + errorSuffix; |
| } |
| // Note that (24, 24) may be affected by anti-alias. |
| img = ctx.getImageData(23, 23, 1, 1).data; |
| actualColor = [img[0], img[1], img[2], img[3]]; |
| if (isDifferentColor(actualColor, expectedColor.destination)) { |
| results += "Unexpected destination! expected: " + expectedColor.destination + " actual: " + actualColor + errorSuffix; |
| } |
| img = ctx.getImageData(12, 12, 1, 1).data; |
| actualColor = [img[0], img[1], img[2], img[3]]; |
| if (isDifferentColor(actualColor, expectedColor.composition)) { |
| results += "Unexpected composition! expected: " + expectedColor.composition + " actual: " + actualColor + errorSuffix; |
| } |
| |
| if (results == "") { |
| messageElement.style.backgroundColor = "green"; |
| messageElement.innerHTML = results = "PASS"; |
| } else { |
| messageElement.style.backgroundColor = "red"; |
| messageElement.innerHTML = results; |
| } |
| |
| // Dump colors into text area for debugging purpose. |
| var debugText = document.getElementById("debug"); |
| img = ctx.getImageData(0, 0, 1, 1).data; |
| debugText.value += img[0] + "," + img[1] + "," + img[2] + "," + img[3] + "\n"; |
| img = ctx.getImageData(12, 12, 1, 1).data; |
| debugText.value += img[0] + "," + img[1] + "," + img[2] + "," + img[3] + "\n"; |
| img = ctx.getImageData(24, 24, 1, 1).data; |
| debugText.value += img[0] + "," + img[1] + "," + img[2] + "," + img[3] + "\n"; |
| } |
| } |
| } |
| |
| var useFillRect = { |
| drawSource: function(ctx) { |
| ctx.fillRect(0, 0, 20, 20); |
| }, |
| |
| drawDestination: function(ctx) { |
| ctx.fillRect(5, 5, 20, 20); |
| }, |
| |
| drawComposition: function(ctx) { |
| ctx.fillRect(5, 5, 15, 15); |
| }, |
| |
| name: "fill rect" |
| }; |
| |
| var usePathAndFill = { |
| drawSource: function(ctx) { |
| ctx.beginPath(); |
| ctx.moveTo(0, 0); |
| ctx.lineTo(15, 0); |
| ctx.lineTo(15, 15); |
| ctx.lineTo(5, 15); |
| ctx.closePath(); |
| ctx.fill(); |
| }, |
| |
| drawDestination: function(ctx) { |
| ctx.beginPath(); |
| ctx.moveTo(25, 25); |
| ctx.lineTo(10, 25); |
| ctx.lineTo(10, 10); |
| ctx.lineTo(20, 10); |
| ctx.closePath(); |
| ctx.fill(); |
| }, |
| |
| drawComposition: function(ctx) { |
| ctx.fillRect(10, 10, 5, 5); |
| |
| ctx.beginPath(); |
| ctx.closePath(); |
| ctx.fill(); |
| }, |
| |
| name: "path and fill" |
| }; |
| |
| function draw() |
| { |
| drawTable(useFillRect); |
| drawTable(usePathAndFill); |
| if (window.testRunner) |
| testRunner.notifyDone(); |
| } |
| </script> |
| <style type="text/css"> |
| body { margin: 20px; font-family: arial,verdana,helvetica; background: #fff;} |
| h1 { font-size: 140%; font-weight:normal; color: #036; border-bottom: 1px solid #ccc; } |
| canvas { border: 2px solid #000; margin-bottom: 5px; } |
| table { background: #00f; } |
| th { font-size: 70%; padding: 0; } |
| td { font-size: 70%; padding: 0; } |
| pre { float:left; display:block; background: rgb(238,238,238); border: 1px dashed #666; padding: 15px 20px; margin: 0 0 10px 0; } |
| </style> |
| </head> |
| <body onload="draw();"> |
| <p>This test exercises a bunch of color composition with alpha blending. The top-left rectangles are the source images and bottom-right rectangles are the destination images.</p> |
| <div id="results"> |
| </div> |
| <textarea id="debug"></textarea> |
| </body> |
| </html> |