3 <title>A canvas globalCompositeOperation test with alpha blending
</title>
4 <!-- This test was inspired by http://canvex.lazyilluminati.com/misc/compositex.html -->
5 <script type=
"application/x-javascript">
6 if (window.testRunner) {
7 testRunner.dumpAsText();
8 testRunner.waitUntilDone();
11 var compositeTypes = [
12 'source-over','source-in','source-out','source-atop',
13 'destination-over','destination-in','destination-out','destination-atop',
14 'lighter','copy','xor'
17 { source: [
255,
0,
0,
255], destination: [
0,
255,
0,
255] },
18 { source: [
255,
0,
0,
255], destination: [
0,
255,
0,
0] },
19 { source: [
255,
0,
0,
255], destination: [
0,
255,
0,
1] },
20 { source: [
0,
255,
0,
0], destination: [
255,
0,
0,
255] },
21 { source: [
0,
255,
0,
1], destination: [
255,
0,
0,
255] },
22 { source: [
255,
0,
0,
0], destination: [
0,
255,
0,
255] },
23 { source: [
255,
0,
0,
127], destination: [
0,
255,
0,
127] },
24 { source: [
255,
0,
0,
255], destination: [
0,
255,
0,
127] },
25 { source: [
255,
0,
0,
127], destination: [
0,
255,
0,
255] },
26 { source: [
127,
0,
0,
255], destination: [
0,
127,
0,
127] },
27 { source: [
127,
0,
0,
127], destination: [
0,
127,
0,
255] },
28 { source: [
255,
0,
0,
127], destination: [
255,
0,
0,
63] },
29 { source: [
255,
127,
0,
32], destination: [
255,
63,
0,
63] },
30 { source: [
255,
0,
0,
191], destination: [
0,
255,
0,
127] },
31 { source: [
255,
0,
255,
191], destination: [
0,
255,
255,
127] }
33 var expectedColors = [
35 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
255,
0,
255] },
36 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
37 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
255,
0,
1] },
38 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
255,
0,
0,
255] },
39 { source: [
0,
255,
0,
1], composition: [
254,
1,
0,
255], destination: [
255,
0,
0,
255] },
40 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
41 { source: [
255,
0,
0,
127], composition: [
170,
84,
0,
190], destination: [
0,
255,
0,
127] },
42 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
255,
0,
127] },
43 { source: [
255,
0,
0,
127], composition: [
127,
128,
0,
255], destination: [
0,
255,
0,
255] },
44 { source: [
127,
0,
0,
255], composition: [
127,
0,
0,
255], destination: [
0,
126,
0,
127] },
45 { source: [
126,
0,
0,
127], composition: [
63,
63,
0,
255], destination: [
0,
127,
0,
255] },
46 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
158], destination: [
255,
0,
0,
63] },
47 { source: [
255,
127,
0,
32], composition: [
255,
85,
0,
87], destination: [
255,
64,
0,
63] },
48 { source: [
255,
0,
0,
191], composition: [
219,
35,
0,
222], destination: [
0,
255,
0,
127] },
49 { source: [
255,
0,
255,
191], composition: [
219,
35,
255,
222], destination: [
0,
255,
255,
127] }
52 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
53 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
54 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
55 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
56 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
57 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
58 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
64], destination: [
0,
0,
0,
0] },
59 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
127], destination: [
0,
0,
0,
0] },
60 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
127], destination: [
0,
0,
0,
0] },
61 { source: [
0,
0,
0,
0], composition: [
128,
0,
0,
127], destination: [
0,
0,
0,
0] },
62 { source: [
0,
0,
0,
0], composition: [
126,
0,
0,
127], destination: [
0,
0,
0,
0] },
63 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
32], destination: [
0,
0,
0,
0] },
64 { source: [
0,
0,
0,
0], composition: [
255,
127,
0,
8], destination: [
0,
0,
0,
0] },
65 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
96], destination: [
0,
0,
0,
0] },
66 { source: [
0,
0,
0,
0], composition: [
255,
0,
255,
96], destination: [
0,
0,
0,
0] }
69 { source: [
255,
0,
0,
255], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
70 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
71 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
254], destination: [
0,
0,
0,
0] },
72 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
73 { source: [
0,
255,
0,
1], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
74 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
75 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
64], destination: [
0,
0,
0,
0] },
76 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
128], destination: [
0,
0,
0,
0] },
77 { source: [
255,
0,
0,
127], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
78 { source: [
127,
0,
0,
255], composition: [
127,
0,
0,
128], destination: [
0,
0,
0,
0] },
79 { source: [
126,
0,
0,
127], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
80 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
96], destination: [
0,
0,
0,
0] },
81 { source: [
255,
127,
0,
32], composition: [
255,
132,
0,
25], destination: [
0,
0,
0,
0] },
82 { source: [
255,
0,
0,
191], composition: [
255,
0,
0,
96], destination: [
0,
0,
0,
0] },
83 { source: [
255,
0,
255,
191], composition: [
255,
0,
255,
96], destination: [
0,
0,
0,
0] }
86 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
0,
255,
0,
255] },
87 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
88 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
1], destination: [
0,
255,
0,
1] },
89 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
255,
0,
0,
255] },
90 { source: [
0,
0,
0,
0], composition: [
254,
1,
0,
255], destination: [
255,
0,
0,
255] },
91 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
92 { source: [
0,
0,
0,
0], composition: [
126,
126,
0,
127], destination: [
0,
255,
0,
127] },
93 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
127], destination: [
0,
255,
0,
127] },
94 { source: [
0,
0,
0,
0], composition: [
127,
128,
0,
255], destination: [
0,
255,
0,
255] },
95 { source: [
0,
0,
0,
0], composition: [
128,
0,
0,
127], destination: [
0,
126,
0,
127] },
96 { source: [
0,
0,
0,
0], composition: [
63,
63,
0,
255], destination: [
0,
127,
0,
255] },
97 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
63], destination: [
255,
0,
0,
63] },
98 { source: [
0,
0,
0,
0], composition: [
255,
68,
0,
63], destination: [
255,
64,
0,
63] },
99 { source: [
0,
0,
0,
0], composition: [
190,
62,
0,
127], destination: [
0,
255,
0,
127] },
100 { source: [
0,
0,
0,
0], composition: [
190,
62,
255,
127], destination: [
0,
255,
255,
127] }
103 { source: [
255,
0,
0,
255], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
104 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
105 { source: [
255,
0,
0,
255], composition: [
254,
1,
0,
255], destination: [
0,
255,
0,
1] },
106 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
255,
0,
0,
255] },
107 { source: [
0,
255,
0,
1], composition: [
255,
0,
0,
255], destination: [
255,
0,
0,
255] },
108 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
109 { source: [
255,
0,
0,
127], composition: [
84,
170,
0,
190], destination: [
0,
255,
0,
127] },
110 { source: [
255,
0,
0,
255], composition: [
128,
127,
0,
255], destination: [
0,
255,
0,
127] },
111 { source: [
255,
0,
0,
127], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
112 { source: [
127,
0,
0,
255], composition: [
63,
63,
0,
255], destination: [
0,
126,
0,
127] },
113 { source: [
126,
0,
0,
127], composition: [
0,
127,
0,
255], destination: [
0,
127,
0,
255] },
114 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
158], destination: [
255,
0,
0,
63] },
115 { source: [
255,
127,
0,
32], composition: [
255,
82,
0,
87], destination: [
255,
64,
0,
63] },
116 { source: [
255,
0,
0,
191], composition: [
109,
145,
0,
222], destination: [
0,
255,
0,
127] },
117 { source: [
255,
0,
255,
191], composition: [
109,
145,
255,
222], destination: [
0,
255,
255,
127] }
120 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
255], destination: [
0,
0,
0,
0] },
121 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
122 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
1], destination: [
0,
0,
0,
0] },
123 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
124 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
1], destination: [
0,
0,
0,
0] },
125 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
126 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
64], destination: [
0,
0,
0,
0] },
127 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
127], destination: [
0,
0,
0,
0] },
128 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
127], destination: [
0,
0,
0,
0] },
129 { source: [
0,
0,
0,
0], composition: [
0,
126,
0,
127], destination: [
0,
0,
0,
0] },
130 { source: [
0,
0,
0,
0], composition: [
0,
128,
0,
127], destination: [
0,
0,
0,
0] },
131 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
32], destination: [
0,
0,
0,
0] },
132 { source: [
0,
0,
0,
0], composition: [
255,
95,
0,
8], destination: [
0,
0,
0,
0] },
133 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
96], destination: [
0,
0,
0,
0] },
134 { source: [
0,
0,
0,
0], composition: [
0,
255,
255,
96], destination: [
0,
0,
0,
0] }
137 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
255,
0,
255] },
138 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
139 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
255,
0,
1] },
140 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
255,
0,
0,
255] },
141 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
254], destination: [
255,
0,
0,
255] },
142 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
143 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
64], destination: [
0,
255,
0,
127] },
144 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
255,
0,
127] },
145 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
128], destination: [
0,
255,
0,
255] },
146 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
126,
0,
127] },
147 { source: [
0,
0,
0,
0], composition: [
0,
127,
0,
128], destination: [
0,
127,
0,
255] },
148 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
32], destination: [
255,
0,
0,
63] },
149 { source: [
0,
0,
0,
0], composition: [
255,
63,
0,
56], destination: [
255,
64,
0,
63] },
150 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
32], destination: [
0,
255,
0,
127] },
151 { source: [
0,
0,
0,
0], composition: [
0,
255,
255,
32], destination: [
0,
255,
255,
127] }
154 { source: [
255,
0,
0,
255], composition: [
0,
255,
0,
255], destination: [
0,
0,
0,
0] },
155 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
156 { source: [
255,
0,
0,
255], composition: [
254,
1,
0,
255], destination: [
0,
0,
0,
0] },
157 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
158 { source: [
0,
255,
0,
1], composition: [
255,
0,
0,
1], destination: [
0,
0,
0,
0] },
159 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
160 { source: [
255,
0,
0,
127], composition: [
126,
126,
0,
127], destination: [
0,
0,
0,
0] },
161 { source: [
255,
0,
0,
255], composition: [
128,
127,
0,
255], destination: [
0,
0,
0,
0] },
162 { source: [
255,
0,
0,
127], composition: [
0,
255,
0,
127], destination: [
0,
0,
0,
0] },
163 { source: [
127,
0,
0,
255], composition: [
63,
63,
0,
255], destination: [
0,
0,
0,
0] },
164 { source: [
126,
0,
0,
127], composition: [
0,
126,
0,
127], destination: [
0,
0,
0,
0] },
165 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
127], destination: [
0,
0,
0,
0] },
166 { source: [
255,
127,
0,
32], composition: [
255,
111,
0,
32], destination: [
0,
0,
0,
0] },
167 { source: [
255,
0,
0,
191], composition: [
126,
126,
0,
191], destination: [
0,
0,
0,
0] },
168 { source: [
255,
0,
255,
191], composition: [
126,
126,
255,
191], destination: [
0,
0,
0,
0] }
171 { source: [
255,
0,
0,
255], composition: [
255,
255,
0,
255], destination: [
0,
255,
0,
255] },
172 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
173 { source: [
255,
0,
0,
255], composition: [
255,
1,
0,
255], destination: [
0,
255,
0,
1] },
174 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
255,
0,
0,
255] },
175 { source: [
0,
255,
0,
1], composition: [
255,
1,
0,
255], destination: [
255,
0,
0,
255] },
176 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
177 { source: [
255,
0,
0,
127], composition: [
127,
127,
0,
254], destination: [
0,
255,
0,
127] },
178 { source: [
255,
0,
0,
255], composition: [
255,
127,
0,
255], destination: [
0,
255,
0,
127] },
179 { source: [
255,
0,
0,
127], composition: [
127,
255,
0,
255], destination: [
0,
255,
0,
255] },
180 { source: [
127,
0,
0,
255], composition: [
127,
63,
0,
255], destination: [
0,
126,
0,
127] },
181 { source: [
126,
0,
0,
127], composition: [
63,
127,
0,
255], destination: [
0,
127,
0,
255] },
182 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
190], destination: [
255,
0,
0,
63] },
183 { source: [
255,
127,
0,
32], composition: [
255,
85,
0,
95], destination: [
255,
64,
0,
63] },
184 { source: [
255,
0,
0,
191], composition: [
191,
127,
0,
255], destination: [
0,
255,
0,
127] },
185 { source: [
255,
0,
255,
191], composition: [
191,
127,
255,
255], destination: [
0,
255,
255,
127] }
188 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
189 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
190 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
191 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
192 { source: [
0,
255,
0,
1], composition: [
0,
255,
0,
1], destination: [
0,
0,
0,
0] },
193 { source: [
0,
0,
0,
0], composition: [
0,
0,
0,
0], destination: [
0,
0,
0,
0] },
194 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
127], destination: [
0,
0,
0,
0] },
195 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
196 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
127], destination: [
0,
0,
0,
0] },
197 { source: [
127,
0,
0,
255], composition: [
127,
0,
0,
255], destination: [
0,
0,
0,
0] },
198 { source: [
126,
0,
0,
127], composition: [
126,
0,
0,
127], destination: [
0,
0,
0,
0] },
199 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
127], destination: [
0,
0,
0,
0] },
200 { source: [
255,
127,
0,
32], composition: [
255,
127,
0,
32], destination: [
0,
0,
0,
0] },
201 { source: [
255,
0,
0,
191], composition: [
255,
0,
0,
191], destination: [
0,
0,
0,
0] },
202 { source: [
255,
0,
255,
191], composition: [
255,
0,
255,
191], destination: [
0,
0,
0,
0] }
205 { source: [
255,
0,
0,
255], composition: [
0,
0,
0,
0], destination: [
0,
255,
0,
255] },
206 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
255], destination: [
0,
0,
0,
0] },
207 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
254], destination: [
0,
255,
0,
1] },
208 { source: [
0,
0,
0,
0], composition: [
255,
0,
0,
255], destination: [
255,
0,
0,
255] },
209 { source: [
0,
255,
0,
1], composition: [
255,
0,
0,
254], destination: [
255,
0,
0,
255] },
210 { source: [
0,
0,
0,
0], composition: [
0,
255,
0,
255], destination: [
0,
255,
0,
255] },
211 { source: [
255,
0,
0,
127], composition: [
126,
126,
0,
127], destination: [
0,
255,
0,
127] },
212 { source: [
255,
0,
0,
255], composition: [
255,
0,
0,
128], destination: [
0,
255,
0,
127] },
213 { source: [
255,
0,
0,
127], composition: [
0,
255,
0,
128], destination: [
0,
255,
0,
255] },
214 { source: [
127,
0,
0,
255], composition: [
127,
0,
0,
128], destination: [
0,
126,
0,
127] },
215 { source: [
126,
0,
0,
127], composition: [
0,
125,
0,
128], destination: [
0,
127,
0,
255] },
216 { source: [
255,
0,
0,
127], composition: [
255,
0,
0,
127], destination: [
255,
0,
0,
63] },
217 { source: [
255,
127,
0,
32], composition: [
255,
83,
0,
79], destination: [
255,
64,
0,
63] },
218 { source: [
255,
0,
0,
191], composition: [
190,
62,
0,
127], destination: [
0,
255,
0,
127] },
219 { source: [
255,
0,
255,
191], composition: [
190,
62,
255,
127], destination: [
0,
255,
255,
127] }
223 var debugString =
"";
225 // Compare two colors with a few margin.
226 function isDifferentColor(actualColor, expectedColor)
228 var actualAlpha = actualColor[
3];
229 var expectedAlpha = expectedColor[
3];
230 if (Math.abs(actualColor - expectedColor)
> 3) return true;
231 // For the value of RGB, we compare the values the users actually see.
232 if (Math.abs(actualColor[
0] * actualAlpha /
256 - expectedColor[
0] * expectedAlpha /
256)
> 3) return true;
233 if (Math.abs(actualColor[
1] * actualAlpha /
256 - expectedColor[
1] * expectedAlpha /
256)
> 3) return true;
234 if (Math.abs(actualColor[
2] * actualAlpha /
256 - expectedColor[
2] * expectedAlpha /
256)
> 3) return true;
238 function getRGBAString(a)
240 return
"rgba(" + [a[
0], a[
1], a[
2], a[
3] /
255.0].join(
",") +
")";
243 function drawTable(drawPolicy)
245 var tableElement = document.createElement(
"table");
247 // Create a header for source color.
248 var trElement = document.createElement(
"tr");
249 tableElement.appendChild(trElement);
250 trElement.appendChild(document.createElement(
"th"));
251 for (var column =
0; column < inputColors.length; column++) {
252 var inputColor = inputColors[column];
253 var thElement = document.createElement(
"th");
254 thElement.setAttribute(
"colspan",
"2");
255 thElement.textContent =
"src " + inputColor.source.join(
", ");
256 trElement.appendChild(thElement);
259 // Create a header for destination color.
260 trElement = document.createElement(
"tr");
261 tableElement.appendChild(trElement);
262 trElement.appendChild(document.createElement(
"th"));
263 for (var column =
0; column < inputColors.length; column++) {
264 var inputColor = inputColors[column];
265 var thElement = document.createElement(
"th");
266 thElement.setAttribute(
"colspan",
"2");
267 thElement.textContent =
"dst " + inputColor.destination.join(
", ");
268 trElement.appendChild(thElement);
271 var resultsElement = document.getElementById(
"results");
272 var titleElement = document.createElement(
"h1");
273 titleElement.textContent =
"Tests for " + drawPolicy.name;
274 resultsElement.appendChild(titleElement);
275 resultsElement.appendChild(tableElement);
277 for (var row =
0; row < compositeTypes.length; row++){
278 var type = compositeTypes[row];
280 var trCanvasElement = document.createElement(
"tr");
281 var thElement = document.createElement(
"th");
282 thElement.setAttribute(
"rowspan",
"2");
283 thElement.textContent = type;
284 trCanvasElement.appendChild(thElement);
285 var trMessageElement = document.createElement(
"tr");
286 tableElement.appendChild(trCanvasElement);
287 tableElement.appendChild(trMessageElement);
289 for (var column =
0; column < inputColors.length; column++) {
290 var test = type +
"-" + column;
291 var inputColor = inputColors[column];
292 var expectedColor = expectedColors[row][column];
294 // Create canvas element for actual color.
295 var actualCanvasElement = document.createElement(
"canvas");
296 actualCanvasElement.setAttribute(
"width",
"25");
297 actualCanvasElement.setAttribute(
"height",
"25");
298 tdElement = document.createElement(
"td");
299 tdElement.appendChild(actualCanvasElement);
300 trCanvasElement.appendChild(tdElement);
302 // Create canvas element for expected color.
303 var expectedCanvasElement = document.createElement(
"canvas");
304 expectedCanvasElement.setAttribute(
"width",
"25");
305 expectedCanvasElement.setAttribute(
"height",
"25");
306 var tdElement = document.createElement(
"td");
307 tdElement.appendChild(expectedCanvasElement);
308 trCanvasElement.appendChild(tdElement);
310 // Create div element for pass/fail messages.
311 var messageElement = document.createElement(
"div");
312 tdElement = document.createElement(
"td");
313 tdElement.setAttribute(
"colspan",
"2");
314 tdElement.appendChild(messageElement);
315 trMessageElement.appendChild(tdElement);
317 var ctx = expectedCanvasElement.getContext(
"2d");
319 // Draw expected image.
320 ctx.globalCompositeOperation =
"copy";
321 ctx.fillStyle = getRGBAString(expectedColor.destination);
322 ctx.strokeStyle = getRGBAString(expectedColor.destination);
323 drawPolicy.drawDestination(ctx);
324 ctx.fillStyle = getRGBAString(expectedColor.source);
325 ctx.strokeStyle = getRGBAString(expectedColor.source);
326 drawPolicy.drawSource(ctx);
327 ctx.fillStyle = getRGBAString(expectedColor.composition);
328 ctx.strokeStyle = getRGBAString(expectedColor.composition);
329 drawPolicy.drawComposition(ctx);
331 ctx = actualCanvasElement.getContext(
"2d");
334 // Draw destination rectangle.
335 ctx.globalCompositeOperation =
"copy";
336 ctx.fillStyle = getRGBAString(inputColor.destination);
337 ctx.strokeStyle = getRGBAString(inputColor.destination);
338 drawPolicy.drawDestination(ctx);
340 // Draw source rectangle.
341 ctx.globalCompositeOperation = type;
342 ctx.fillStyle = getRGBAString(inputColor.source);
343 ctx.strokeStyle = getRGBAString(inputColor.source);
344 drawPolicy.drawSource(ctx);
346 // Let's check if the results are expected or not.
347 var errorSuffix =
", composite type: " + type +
", source: " + inputColor.source +
", destination: " + inputColor.destination +
"<br>";
350 // Note that (
0,
0) may be affected by anti-alias.
351 var img = ctx.getImageData(
1,
1,
1,
1).data;
352 var actualColor = [img[
0], img[
1], img[
2], img[
3]];
353 if (isDifferentColor(actualColor, expectedColor.source)) {
354 results +=
"Unexpected source! expected: " + expectedColor.source +
" actual: " + actualColor + errorSuffix;
356 // Note that (
24,
24) may be affected by anti-alias.
357 img = ctx.getImageData(
23,
23,
1,
1).data;
358 actualColor = [img[
0], img[
1], img[
2], img[
3]];
359 if (isDifferentColor(actualColor, expectedColor.destination)) {
360 results +=
"Unexpected destination! expected: " + expectedColor.destination +
" actual: " + actualColor + errorSuffix;
362 img = ctx.getImageData(
12,
12,
1,
1).data;
363 actualColor = [img[
0], img[
1], img[
2], img[
3]];
364 if (isDifferentColor(actualColor, expectedColor.composition)) {
365 results +=
"Unexpected composition! expected: " + expectedColor.composition +
" actual: " + actualColor + errorSuffix;
369 messageElement.style.backgroundColor =
"green";
370 messageElement.innerHTML = results =
"PASS";
372 messageElement.style.backgroundColor =
"red";
373 messageElement.innerHTML = results;
376 img = ctx.getImageData(
0,
0,
1,
1).data;
377 debugString += img[
0] +
"," + img[
1] +
"," + img[
2] +
"," + img[
3] +
"\n";
378 img = ctx.getImageData(
12,
12,
1,
1).data;
379 debugString += img[
0] +
"," + img[
1] +
"," + img[
2] +
"," + img[
3] +
"\n";
380 img = ctx.getImageData(
24,
24,
1,
1).data;
381 debugString += img[
0] +
"," + img[
1] +
"," + img[
2] +
"," + img[
3] +
"\n";
386 var useStrokeRect = {
387 drawSource: function(ctx) {
388 ctx.strokeRect(
5,
5,
10,
10);
391 drawDestination: function(ctx) {
392 ctx.fillRect(
5,
5,
20,
20);
395 drawComposition: function(ctx) {
396 ctx.fillRect(
5,
5,
15,
15);
402 var usePathAndStroke = {
403 drawSource: function(ctx) {
413 drawDestination: function(ctx) {
414 ctx.fillRect(
5,
5,
20,
20);
417 drawComposition: function(ctx) {
418 ctx.fillRect(
5,
5,
15,
15);
421 name:
"path and stroke"
426 drawTable(useStrokeRect);
427 drawTable(usePathAndStroke);
428 // Dump colors into text area for debugging purpose.
429 document.getElementById(
"debug").value = debugString;
430 if (window.testRunner)
431 testRunner.notifyDone();
434 <style type=
"text/css">
435 body
{ margin: 20px; font-family: arial
,verdana
,helvetica
; background: #fff;}
436 h1
{ font-size: 140%; font-weight:normal
; color: #036; border-bottom: 1px solid
#ccc; }
437 canvas
{ border: 2px solid
#000; margin-bottom: 5px; }
438 table
{ background: #00f; }
439 th
{ font-size: 70%; padding: 0; }
440 td
{ font-size: 70%; padding: 0; }
441 pre
{ float:left
; display:block
; background: rgb
(238,238,238); border: 1px dashed
#666; padding: 15px 20px; margin: 0 0 10px 0; }
444 <body onload=
"draw();">
445 <p>This test exercises a bunch of alpha composition checks with stroking. The top-left rectangles are the source images and bottom-right rectangles are the destination images.
</p>
448 <textarea id=
"debug"></textarea>