fill-and-stroke-styles.yaml (81698B)
1 # Try most of the CSS3 Color <color> values. 2 # http://www.w3.org/TR/css3-color/#colorunits 3 - name: 2d.fillStyle.parse 4 macros: | 5 {% macro js_format(color) %} 6 {% set r, g, b, a = color %} 7 {{- '%d,%d,%d,%d' | format(r, g, b, a) -}} 8 {% endmacro %} 9 10 {% macro cairo_format(color) %} 11 {% set r, g, b, a = color %} 12 {{- '%f, %f, %f, %f' | 13 format(r / 255.0, g / 255.0, b / 255.0, a / 255.0) -}} 14 {% endmacro %} 15 code: | 16 {% import 'macros' as m %} 17 ctx.fillStyle = '#f00'; 18 ctx.fillStyle = '{{ string }}'; 19 ctx.fillRect(0, 0, 100, 50); 20 @assert pixel 50,25 == {{ m.js_format(color) }}; 21 expected: | 22 {% import 'macros' as m %} 23 size 100 50 24 cr.set_source_rgba({{ m.cairo_format(color) }}) 25 cr.rectangle(0, 0, 100, 50) 26 cr.fill() 27 big_float: '1{% for i in range(39) %}0{% endfor %}' 28 big_double: '1{% for i in range(310) %}0{% endfor %}' 29 variants: 30 - html4: {string: 'limE', color: [0, 255, 0, 255]} 31 hex3: {string: '#0f0', color: [0, 255, 0, 255]} 32 hex4: {string: '#0f0f', color: [0, 255, 0, 255]} 33 hex6: {string: '#00fF00', color: [0, 255, 0, 255]} 34 hex8: {string: '#00ff00ff', color: [0, 255, 0, 255]} 35 rgb-num: {string: 'rgb(0,255,0)', color: [0, 255, 0, 255]} 36 rgb-clamp-1: {string: 'rgb(-1000, 1000, -1000)', color: [0, 255, 0, 255], 37 notes: 'Assumes colors are clamped to [0,255].'} 38 rgb-clamp-2: {string: 'rgb(-200%, 200%, -200%)', color: [0, 255, 0, 255], 39 notes: 'Assumes colors are clamped to [0,255].'} 40 rgb-clamp-3: {string: 'rgb(-2147483649, 4294967298, -18446744073709551619)', 41 color: [0, 255, 0, 255], 42 notes: 'Assumes colors are clamped to [0,255].'} 43 rgb-clamp-4: 44 string: 'rgb(-{{ big_float }}, {{ big_float }}, -{{ big_float }})' 45 color: [0, 255, 0, 255] 46 notes: 'Assumes colors are clamped to [0,255].' 47 rgb-clamp-5: 48 string: 'rgb(-{{ big_double }}, {{ big_double }}, -{{ big_double }})' 49 color: [0, 255, 0, 255] 50 notes: 'Assumes colors are clamped to [0,255].' 51 rgb-percent: 52 string: 'rgb(0% ,100% ,0%)' 53 color: [0, 255, 0, 255] 54 notes: >- 55 CSS3 Color says "The integer value 255 corresponds to 100%". (In 56 particular, it is not 254...) 57 # See CSS2.1 4.2 "Unexpected end of style sheet". 58 rgb-eof: {string: 'rgb(0, 255, 0', color: [0, 255, 0, 255]} 59 rgba-solid-1: {string: 'rgba( 0 , 255 , 0 , 1 )', 60 color: [0, 255, 0, 255]} 61 rgba-solid-2: {string: 'rgba( 0 , 255 , 0 , 1.0 )', 62 color: [0, 255, 0, 255]} 63 rgba-solid-3: {string: 'rgba( 0 , 255 , 0 , +1 )', 64 color: [0, 255, 0, 255]} 65 rgba-solid-4: {string: 'rgba( -0 , 255 , +0 , 1 )', 66 color: [0, 255, 0, 255]} 67 rgba-num-1: {string: 'rgba( 0 , 255 , 0 , .499 )', 68 color: [0, 255, 0, 127]} 69 rgba-num-2: {string: 'rgba( 0 , 255 , 0 , 0.499 )', 70 color: [0, 255, 0, 127]} 71 rgba-percent: 72 string: 'rgba(0%,100%,0%,0.499)' 73 # 0.499*255 rounds to 127, both down and nearest, so it should be safe. 74 color: [0, 255, 0, 127] 75 rgba-clamp-1: {string: 'rgba(0, 255, 0, -2)', color: [0, 0, 0, 0]} 76 rgba-clamp-2: {string: 'rgba(0, 255, 0, 2)', color: [0, 255, 0, 255]} 77 rgba-eof: {string: 'rgba(0, 255, 0, 1', color: [0, 255, 0, 255]} 78 transparent-1: {string: 'transparent', color: [0, 0, 0, 0]} 79 transparent-2: {string: 'TrAnSpArEnT', color: [0, 0, 0, 0]} 80 hsl-1: {string: 'hsl(120, 100%, 50%)', color: [0, 255, 0, 255]} 81 hsl-2: {string: 'hsl( -240 , 100% , 50% )', color: [0, 255, 0, 255]} 82 hsl-3: {string: 'hsl(360120, 100%, 50%)', color: [0, 255, 0, 255]} 83 hsl-4: {string: 'hsl(-360240, 100%, 50%)', color: [0, 255, 0, 255]} 84 hsl-5: {string: 'hsl(120.0, 100.0%, 50.0%)', color: [0, 255, 0, 255]} 85 hsl-6: {string: 'hsl(+120, +100%, +50%)', color: [0, 255, 0, 255]} 86 hsl-clamp-negative-saturation: {string: 'hsl(120, -200%, 49.9%)', 87 color: [127, 127, 127, 255]} 88 hsla-1: {string: 'hsla(120, 100%, 50%, 0.499)', color: [0, 255, 0, 127]} 89 hsla-2: {string: 'hsla( 120.0 , 100.0% , 50.0% , 1 )', 90 color: [0, 255, 0, 255]} 91 hsla-clamp-negative-saturation: {string: 'hsla(120, -200%, 49.9%, 1)', 92 color: [127, 127, 127, 255]} 93 hsla-clamp-alpha-1: {string: 'hsla(120, 100%, 50%, 2)', 94 color: [0, 255, 0, 255]} 95 hsla-clamp-alpha-2: {string: 'hsla(120, 100%, 0%, -2)', 96 color: [0, 0, 0, 0]} 97 svg-1: {string: 'gray', color: [128, 128, 128, 255]} 98 svg-2: {string: 'grey', color: [128, 128, 128, 255]} 99 # css-color-4 rgb() color function. 100 # https://drafts.csswg.org/css-color/#numeric-rgb 101 css-color-4-rgb-1: {string: 'rgb(0, 255.0, 0)', color: [0, 255, 0, 255]} 102 css-color-4-rgb-2: {string: 'rgb(0, 255, 0, 0.2)', color: [0, 255, 0, 51]} 103 css-color-4-rgb-3: {string: 'rgb(0, 255, 0, 20%)', color: [0, 255, 0, 51]} 104 css-color-4-rgb-4: {string: 'rgb(0 255 0)', color: [0, 255, 0, 255]} 105 css-color-4-rgb-5: {string: 'rgb(0 255 0 / 0.2)', color: [0, 255, 0, 51]} 106 css-color-4-rgb-6: {string: 'rgb(0 255 0 / 20%)', color: [0, 255, 0, 51]} 107 css-color-4-rgba-1: {string: 'rgba(0, 255.0, 0)', color: [0, 255, 0, 255]} 108 css-color-4-rgba-2: {string: 'rgba(0, 255, 0, 0.2)', color: [0, 255, 0, 51]} 109 css-color-4-rgba-3: {string: 'rgba(0, 255, 0, 20%)', color: [0, 255, 0, 51]} 110 css-color-4-rgba-4: {string: 'rgba(0 255 0)', color: [0, 255, 0, 255]} 111 css-color-4-rgba-5: {string: 'rgba(0 255 0 / 0.2)', color: [0, 255, 0, 51]} 112 css-color-4-rgba-6: {string: 'rgba(0 255 0 / 20%)', color: [0, 255, 0, 51]} 113 # css-color-4 hsl() color function. 114 # https://drafts.csswg.org/css-color/#the-hsl-notation 115 css-color-4-hsl-1: {string: 'hsl(120 100.0% 50.0%)', 116 color: [0, 255, 0, 255]} 117 css-color-4-hsl-2: {string: 'hsl(120 100.0% 50.0% / 0.2)', 118 color: [0, 255, 0, 51]} 119 css-color-4-hsl-3: {string: 'hsl(120.0, 100.0%, 50.0%, 0.2)', 120 color: [0, 255, 0, 51]} 121 css-color-4-hsl-4: {string: 'hsl(120.0, 100.0%, 50.0%, 20%)', 122 color: [0, 255, 0, 51]} 123 css-color-4-hsl-5: {string: 'hsl(120deg, 100.0%, 50.0%, 0.2)', 124 color: [0, 255, 0, 51]} 125 css-color-4-hsl-6: {string: 'hsl(120deg, 100.0%, 50.0%)', 126 color: [0, 255, 0, 255]} 127 css-color-4-hsl-7: {string: 'hsl(133.33333333grad, 100.0%, 50.0%)', 128 color: [0, 255, 0, 255]} 129 css-color-4-hsl-8: {string: 'hsl(2.0943951024rad, 100.0%, 50.0%)', 130 color: [0, 255, 0, 255]} 131 css-color-4-hsl-9: {string: 'hsl(0.3333333333turn, 100.0%, 50.0%)', 132 color: [0, 255, 0, 255]} 133 css-color-4-hsla-1: {string: 'hsl(120 100.0% 50.0%)', 134 color: [0, 255, 0, 255]} 135 css-color-4-hsla-2: {string: 'hsl(120 100.0% 50.0% / 0.2)', 136 color: [0, 255, 0, 51]} 137 css-color-4-hsla-3: {string: 'hsl(120.0, 100.0%, 50.0%, 0.2)', 138 color: [0, 255, 0, 51]} 139 css-color-4-hsla-4: {string: 'hsl(120.0, 100.0%, 50.0%, 20%)', 140 color: [0, 255, 0, 51]} 141 css-color-4-hsla-5: {string: 'hsl(120deg, 100.0%, 50.0%, 0.2)', 142 color: [0, 255, 0, 51]} 143 css-color-4-hsla-6: {string: 'hsl(120deg, 100.0%, 50.0%)', 144 color: [0, 255, 0, 255]} 145 css-color-4-hsla-7: {string: 'hsl(133.33333333grad, 100.0%, 50.0%)', 146 color: [0, 255, 0, 255]} 147 css-color-4-hsla-8: {string: 'hsl(2.0943951024rad, 100.0%, 50.0%)', 148 color: [0, 255, 0, 255]} 149 css-color-4-hsla-9: {string: 'hsl(0.3333333333turn, 100.0%, 50.0%)', 150 color: [0, 255, 0, 255]} 151 # currentColor is handled later. 152 153 # Test that invalid colors are ignored. 154 - name: 2d.fillStyle.parse.invalid 155 code: | 156 ctx.fillStyle = '#0f0'; 157 try { ctx.fillStyle = '{{ string }}'; } catch (e) { } \- 158 // this shouldn't throw, but it shouldn't matter here if it does 159 ctx.fillRect(0, 0, 100, 50); 160 @assert pixel 50,25 == 0,255,0,255; 161 expected: 'green' 162 variants: 163 - hex1: {string: '#f'} 164 hex2: {string: '#f0'} 165 hex3: {string: '#g00'} 166 hex4: {string: '#fg00'} 167 hex5: {string: '#ff000'} 168 hex6: {string: '#fg0000'} 169 hex7: {string: '#ff0000f'} 170 hex8: {string: '#fg0000ff'} 171 rgb-1: {string: 'rgb(255.0, 0, 0,)'} 172 rgb-2: {string: 'rgb(100%, 0, 0)'} 173 rgb-3: {string: 'rgb(255, - 1, 0)'} 174 rgba-1: {string: 'rgba(100%, 0, 0, 1)'} 175 rgba-2: {string: 'rgba(255, 0, 0, 1. 0)'} 176 rgba-3: {string: 'rgba(255, 0, 0, 1.)'} 177 rgba-4: {string: 'rgba(255, 0, 0, '} 178 rgba-5: {string: 'rgba(255, 0, 0, 1,)'} 179 hsl-1: {string: 'hsl(0%, 100%, 50%)'} 180 hsl-2: {string: 'hsl(z, 100%, 50%)'} 181 hsl-3: {string: 'hsl(0, 0, 50%)'} 182 hsl-4: {string: 'hsl(0, 100%, 0)'} 183 hsl-5: {string: 'hsl(0, 100.%, 50%)'} 184 hsl-6: {string: 'hsl(0, 100%, 50%,)'} 185 hsla-1: {string: 'hsla(0%, 100%, 50%, 1)'} 186 hsla-2: {string: 'hsla(0, 0, 50%, 1)'} 187 hsla-3: {string: 'hsla(0, 0, 50%, 1,)'} 188 name-1: {string: 'darkbrown'} 189 name-2: {string: 'firebrick1'} 190 name-3: {string: 'red blue'} 191 name-4: {string: '"red"'} 192 name-5: {string: '"red'} 193 # css-color-4 color function. 194 # Comma and comma-less expressions should not mix together. 195 css-color-4-rgb-1: {string: 'rgb(255, 0, 0 / 1)'} 196 css-color-4-rgb-2: {string: 'rgb(255 0 0, 1)'} 197 css-color-4-rgb-3: {string: 'rgb(255, 0 0)'} 198 css-color-4-rgba-1: {string: 'rgba(255, 0, 0 / 1)'} 199 css-color-4-rgba-2: {string: 'rgba(255 0 0, 1)'} 200 css-color-4-rgba-3: {string: 'rgba(255, 0 0)'} 201 css-color-4-hsl-1: {string: 'hsl(0, 100%, 50% / 1)'} 202 css-color-4-hsl-2: {string: 'hsl(0 100% 50%, 1)'} 203 css-color-4-hsl-3: {string: 'hsl(0, 100% 50%)'} 204 css-color-4-hsla-1: {string: 'hsla(0, 100%, 50% / 1)'} 205 css-color-4-hsla-2: {string: 'hsla(0 100% 50%, 1)'} 206 css-color-4-hsla-3: {string: 'hsla(0, 100% 50%)'} 207 # Trailing slash. 208 css-color-4-rgb-4: {string: 'rgb(0 0 0 /)'} 209 css-color-4-rgb-5: {string: 'rgb(0, 0, 0 /)'} 210 css-color-4-hsl-4: {string: 'hsl(0 100% 50% /)'} 211 css-color-4-hsl-5: {string: 'hsl(0, 100%, 50% /)'} 212 # Malformed functions. 213 css-color-4-rgb-6: {string: 'rgb(from #ffffff r g b) 100%'} 214 css-color-4-rgb-7: {string: 'rgb(from #ffffff r g b) currentColor'} 215 css-color-4-hsl-6: {string: 'hsl(from #ffffff h s l) red'} 216 css-color-4-hsl-7: {string: 'hsl(from #ffffff h s l) /'} 217 218 # Implemented as a negative test because we don't know what color it's meant to 219 # be. 220 - name: 2d.fillStyle.parse.system 221 code: | 222 ctx.fillStyle = '#f00'; 223 ctx.fillStyle = 'ThreeDDarkShadow'; 224 @assert ctx.fillStyle =~ /^#(?!(FF0000|ff0000|f00)$)/; // test that it's \- 225 not red 226 227 - name: 2d.fillStyle.parse.current.basic 228 desc: currentColor is computed from the canvas element 229 canvas_types: ['HtmlCanvas'] 230 code: | 231 canvas.setAttribute('style', 'color: #0f0'); 232 ctx.fillStyle = '#f00'; 233 ctx.fillStyle = 'currentColor'; 234 ctx.fillRect(0, 0, 100, 50); 235 @assert pixel 50,25 == 0,255,0,255; 236 expected: green 237 238 - name: 2d.fillStyle.parse.current.changed 239 desc: currentColor is computed when the attribute is set, not when it is painted 240 canvas_types: ['HtmlCanvas'] 241 code: | 242 canvas.setAttribute('style', 'color: #0f0'); 243 ctx.fillStyle = '#f00'; 244 ctx.fillStyle = 'currentColor'; 245 canvas.setAttribute('style', 'color: #f00'); 246 ctx.fillRect(0, 0, 100, 50); 247 @assert pixel 50,25 == 0,255,0,255; 248 expected: green 249 250 - name: 2d.fillStyle.parse.current.removed 251 desc: currentColor is solid black when the canvas element is not in a document 252 canvas_types: ['HtmlCanvas'] 253 code: | 254 // Try not to let it undetectably incorrectly pick up opaque-black 255 // from other parts of the document: 256 document.body.parentNode.setAttribute('style', 'color: #f00'); 257 document.body.setAttribute('style', 'color: #f00'); 258 canvas.setAttribute('style', 'color: #f00'); 259 260 var canvas2 = document.createElement('canvas'); 261 var ctx2 = canvas2.getContext('2d'); 262 ctx2.fillStyle = '#f00'; 263 ctx2.fillStyle = 'currentColor'; 264 ctx2.fillRect(0, 0, 100, 50); 265 ctx.drawImage(canvas2, 0, 0); 266 267 document.body.parentNode.removeAttribute('style'); 268 document.body.removeAttribute('style'); 269 270 @assert pixel 50,25 == 0,0,0,255; 271 expected: | 272 size 100 50 273 cr.set_source_rgb(0, 0, 0) 274 cr.rectangle(0, 0, 100, 50) 275 cr.fill() 276 277 - name: 2d.fillStyle.invalidstring 278 code: | 279 ctx.fillStyle = '#f00'; 280 ctx.fillRect(0, 0, 100, 50); 281 ctx.fillStyle = '#0f0'; 282 ctx.fillStyle = 'invalid'; 283 ctx.fillRect(0, 0, 100, 50); 284 @assert pixel 50,25 == 0,255,0,255; 285 expected: green 286 287 - name: 2d.fillStyle.invalidtype 288 code: | 289 ctx.fillStyle = '#f00'; 290 ctx.fillRect(0, 0, 100, 50); 291 ctx.fillStyle = '#0f0'; 292 ctx.fillStyle = null; 293 ctx.fillRect(0, 0, 100, 50); 294 @assert pixel 50,25 == 0,255,0,255; 295 expected: green 296 297 - name: 2d.fillStyle.get.solid 298 code: | 299 ctx.fillStyle = '#fa0'; 300 @assert ctx.fillStyle === '#ffaa00'; 301 302 - name: 2d.fillStyle.get.semitransparent 303 code: | 304 ctx.fillStyle = 'rgba(255,255,255,0.45)'; 305 @assert ctx.fillStyle =~ /^rgba\(255, 255, 255, 0\.4\d+\)$/; 306 307 - name: 2d.fillStyle.get.halftransparent 308 code: | 309 ctx.fillStyle = 'rgba(255,255,255,0.5)'; 310 @assert ctx.fillStyle === 'rgba(255, 255, 255, 0.5)'; 311 312 - name: 2d.fillStyle.get.transparent 313 code: | 314 ctx.fillStyle = 'rgba(0,0,0,0)'; 315 @assert ctx.fillStyle === 'rgba(0, 0, 0, 0)'; 316 317 - name: 2d.fillStyle.default 318 code: | 319 @assert ctx.fillStyle === '#000000'; 320 321 - name: 2d.fillStyle.toStringFunctionCallback 322 desc: Passing a function in to ctx.fillStyle or ctx.strokeStyle with a toString callback works as specified 323 code: | 324 ctx.fillStyle = { toString: function() { return "#008000"; } }; 325 @assert ctx.fillStyle === "#008000"; 326 ctx.fillStyle = {}; 327 @assert ctx.fillStyle === "#008000"; 328 ctx.fillStyle = 800000; 329 @assert ctx.fillStyle === "#008000"; 330 @assert throws TypeError ctx.fillStyle = { toString: function() { throw new TypeError; } }; 331 ctx.strokeStyle = { toString: function() { return "#008000"; } }; 332 @assert ctx.strokeStyle === "#008000"; 333 ctx.strokeStyle = {}; 334 @assert ctx.strokeStyle === "#008000"; 335 ctx.strokeStyle = 800000; 336 @assert ctx.strokeStyle === "#008000"; 337 @assert throws TypeError ctx.strokeStyle = { toString: function() { throw new TypeError; } }; 338 339 - name: 2d.strokeStyle.default 340 code: | 341 @assert ctx.strokeStyle === '#000000'; 342 343 344 - name: 2d.gradient.object.type 345 desc: window.CanvasGradient exists and has the right properties 346 notes: &bindings Defined in "Web IDL" (draft) 347 code: | 348 {% set root = 'self' if canvas_type == 'Worker' else 'window' %} 349 @assert {{ root }}.CanvasGradient !== undefined; 350 @assert {{ root }}.CanvasGradient.prototype.addColorStop !== undefined; 351 352 - name: 2d.gradient.object.return 353 desc: createLinearGradient() and createRadialGradient() returns objects implementing 354 CanvasGradient 355 code: | 356 {% set root = 'self' if canvas_type == 'Worker' else 'window' %} 357 {{ root }}.CanvasGradient.prototype.thisImplementsCanvasGradient = true; 358 359 var g1 = ctx.createLinearGradient(0, 0, 100, 0); 360 @assert g1.addColorStop !== undefined; 361 @assert g1.thisImplementsCanvasGradient === true; 362 363 var g2 = ctx.createRadialGradient(0, 0, 10, 0, 0, 20); 364 @assert g2.addColorStop !== undefined; 365 @assert g2.thisImplementsCanvasGradient === true; 366 367 - name: 2d.gradient.interpolate.solid 368 code: | 369 var g = ctx.createLinearGradient(0, 0, 100, 0); 370 g.addColorStop(0, '#0f0'); 371 g.addColorStop(1, '#0f0'); 372 ctx.fillStyle = g; 373 ctx.fillRect(0, 0, 100, 50); 374 @assert pixel 50,25 == 0,255,0,255; 375 expected: green 376 377 - name: 2d.gradient.interpolate.color 378 code: | 379 var g = ctx.createLinearGradient(0, 0, 100, 0); 380 g.addColorStop(0, '#ff0'); 381 g.addColorStop(1, '#00f'); 382 ctx.fillStyle = g; 383 ctx.fillRect(0, 0, 100, 50); 384 @assert pixel 25,25 ==~ 191,191,63,255 +/- 3; 385 @assert pixel 50,25 ==~ 127,127,127,255 +/- 3; 386 @assert pixel 75,25 ==~ 63,63,191,255 +/- 3; 387 expected: | 388 size 100 50 389 g = cairo.LinearGradient(0, 0, 100, 0) 390 g.add_color_stop_rgb(0, 1,1,0) 391 g.add_color_stop_rgb(1, 0,0,1) 392 cr.set_source(g) 393 cr.rectangle(0, 0, 100, 50) 394 cr.fill() 395 396 - name: 2d.gradient.interpolate.alpha 397 code: | 398 ctx.fillStyle = '#ff0'; 399 ctx.fillRect(0, 0, 100, 50); 400 var g = ctx.createLinearGradient(0, 0, 100, 0); 401 g.addColorStop(0, 'rgba(0,0,255, 0)'); 402 g.addColorStop(1, 'rgba(0,0,255, 1)'); 403 ctx.fillStyle = g; 404 ctx.fillRect(0, 0, 100, 50); 405 @assert pixel 25,25 ==~ 191,191,63,255 +/- 3; 406 @assert pixel 50,25 ==~ 127,127,127,255 +/- 3; 407 @assert pixel 75,25 ==~ 63,63,191,255 +/- 3; 408 expected: | 409 size 100 50 410 g = cairo.LinearGradient(0, 0, 100, 0) 411 g.add_color_stop_rgb(0, 1,1,0) 412 g.add_color_stop_rgb(1, 0,0,1) 413 cr.set_source(g) 414 cr.rectangle(0, 0, 100, 50) 415 cr.fill() 416 417 - name: 2d.gradient.interpolate.coloralpha 418 code: | 419 var g = ctx.createLinearGradient(0, 0, 100, 0); 420 g.addColorStop(0, 'rgba(255,255,0, 0)'); 421 g.addColorStop(1, 'rgba(0,0,255, 1)'); 422 ctx.fillStyle = g; 423 ctx.fillRect(0, 0, 100, 50); 424 @assert pixel 25,25 ==~ 190,190,65,65 +/- 3; 425 @assert pixel 50,25 ==~ 126,126,128,128 +/- 3; 426 @assert pixel 75,25 ==~ 62,62,192,192 +/- 3; 427 expected: | 428 size 100 50 429 g = cairo.LinearGradient(0, 0, 100, 0) 430 g.add_color_stop_rgba(0, 1,1,0, 0) 431 g.add_color_stop_rgba(1, 0,0,1, 1) 432 cr.set_source(g) 433 cr.rectangle(0, 0, 100, 50) 434 cr.fill() 435 436 - name: 2d.gradient.interpolate.outside 437 code: | 438 ctx.fillStyle = '#f00'; 439 ctx.fillRect(0, 0, 100, 50); 440 441 var g = ctx.createLinearGradient(25, 0, 75, 0); 442 g.addColorStop(0.4, '#0f0'); 443 g.addColorStop(0.6, '#0f0'); 444 445 ctx.fillStyle = g; 446 ctx.fillRect(0, 0, 100, 50); 447 @assert pixel 20,25 ==~ 0,255,0,255; 448 @assert pixel 50,25 ==~ 0,255,0,255; 449 @assert pixel 80,25 ==~ 0,255,0,255; 450 expected: green 451 452 - name: 2d.gradient.interpolate.zerosize.fill 453 code: | 454 ctx.fillStyle = '#0f0'; 455 ctx.fillRect(0, 0, 100, 50); 456 457 var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) 458 g.addColorStop(0, '#f00'); 459 g.addColorStop(1, '#f00'); 460 ctx.fillStyle = g; 461 ctx.rect(0, 0, 100, 50); 462 ctx.fill(); 463 @assert pixel 40,20 == 0,255,0,255; 464 expected: green 465 466 - name: 2d.gradient.interpolate.zerosize.stroke 467 code: | 468 ctx.fillStyle = '#0f0'; 469 ctx.fillRect(0, 0, 100, 50); 470 471 var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) 472 g.addColorStop(0, '#f00'); 473 g.addColorStop(1, '#f00'); 474 ctx.strokeStyle = g; 475 ctx.rect(20, 20, 60, 10); 476 ctx.stroke(); 477 @assert pixel 19,19 == 0,255,0,255; 478 @assert pixel 20,19 == 0,255,0,255; 479 @assert pixel 21,19 == 0,255,0,255; 480 @assert pixel 19,20 == 0,255,0,255; 481 @assert pixel 20,20 == 0,255,0,255; 482 @assert pixel 21,20 == 0,255,0,255; 483 @assert pixel 19,21 == 0,255,0,255; 484 @assert pixel 20,21 == 0,255,0,255; 485 @assert pixel 21,21 == 0,255,0,255; 486 expected: green 487 488 - name: 2d.gradient.interpolate.zerosize.fillRect 489 code: | 490 ctx.fillStyle = '#0f0'; 491 ctx.fillRect(0, 0, 100, 50); 492 493 var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) 494 g.addColorStop(0, '#f00'); 495 g.addColorStop(1, '#f00'); 496 ctx.fillStyle = g; 497 ctx.fillRect(0, 0, 100, 50); 498 @assert pixel 40,20 == 0,255,0,255; @moz-todo 499 expected: green 500 501 - name: 2d.gradient.interpolate.zerosize.strokeRect 502 code: | 503 ctx.fillStyle = '#0f0'; 504 ctx.fillRect(0, 0, 100, 50); 505 506 var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) 507 g.addColorStop(0, '#f00'); 508 g.addColorStop(1, '#f00'); 509 ctx.strokeStyle = g; 510 ctx.strokeRect(20, 20, 60, 10); 511 @assert pixel 19,19 == 0,255,0,255; 512 @assert pixel 20,19 == 0,255,0,255; 513 @assert pixel 21,19 == 0,255,0,255; 514 @assert pixel 19,20 == 0,255,0,255; 515 @assert pixel 20,20 == 0,255,0,255; 516 @assert pixel 21,20 == 0,255,0,255; 517 @assert pixel 19,21 == 0,255,0,255; 518 @assert pixel 20,21 == 0,255,0,255; 519 @assert pixel 21,21 == 0,255,0,255; 520 expected: green 521 522 - name: 2d.gradient.interpolate.zerosize.fillText 523 code: | 524 ctx.fillStyle = '#0f0'; 525 ctx.fillRect(0, 0, 100, 50); 526 527 var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) 528 g.addColorStop(0, '#f00'); 529 g.addColorStop(1, '#f00'); 530 ctx.fillStyle = g; 531 ctx.font = '100px sans-serif'; 532 ctx.fillText("AA", 0, 50); 533 _assertGreen(ctx, 100, 50); 534 expected: green 535 536 - name: 2d.gradient.interpolate.zerosize.strokeText 537 code: | 538 ctx.fillStyle = '#0f0'; 539 ctx.fillRect(0, 0, 100, 50); 540 541 var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) 542 g.addColorStop(0, '#f00'); 543 g.addColorStop(1, '#f00'); 544 ctx.strokeStyle = g; 545 ctx.font = '100px sans-serif'; 546 ctx.strokeText("AA", 0, 50); 547 _assertGreen(ctx, 100, 50); 548 expected: green 549 550 551 - name: 2d.gradient.interpolate.vertical 552 code: | 553 var g = ctx.createLinearGradient(0, 0, 0, 50); 554 g.addColorStop(0, '#ff0'); 555 g.addColorStop(1, '#00f'); 556 ctx.fillStyle = g; 557 ctx.fillRect(0, 0, 100, 50); 558 @assert pixel 50,12 ==~ 191,191,63,255 +/- 10; 559 @assert pixel 50,25 ==~ 127,127,127,255 +/- 5; 560 @assert pixel 50,37 ==~ 63,63,191,255 +/- 10; 561 expected: | 562 size 100 50 563 g = cairo.LinearGradient(0, 0, 0, 50) 564 g.add_color_stop_rgb(0, 1,1,0) 565 g.add_color_stop_rgb(1, 0,0,1) 566 cr.set_source(g) 567 cr.rectangle(0, 0, 100, 50) 568 cr.fill() 569 570 - name: 2d.gradient.interpolate.multiple 571 code: | 572 canvas.width = 200; 573 var g = ctx.createLinearGradient(0, 0, 200, 0); 574 g.addColorStop(0, '#ff0'); 575 g.addColorStop(0.5, '#0ff'); 576 g.addColorStop(1, '#f0f'); 577 ctx.fillStyle = g; 578 ctx.fillRect(0, 0, 200, 50); 579 @assert pixel 50,25 ==~ 127,255,127,255 +/- 3; 580 @assert pixel 100,25 ==~ 0,255,255,255 +/- 3; 581 @assert pixel 150,25 ==~ 127,127,255,255 +/- 3; 582 expected: | 583 size 200 50 584 g = cairo.LinearGradient(0, 0, 200, 0) 585 g.add_color_stop_rgb(0.0, 1,1,0) 586 g.add_color_stop_rgb(0.5, 0,1,1) 587 g.add_color_stop_rgb(1.0, 1,0,1) 588 cr.set_source(g) 589 cr.rectangle(0, 0, 200, 50) 590 cr.fill() 591 592 - name: 2d.gradient.interpolate.overlap 593 code: | 594 canvas.width = 200; 595 var g = ctx.createLinearGradient(0, 0, 200, 0); 596 g.addColorStop(0, '#f00'); 597 g.addColorStop(0, '#ff0'); 598 g.addColorStop(0.25, '#00f'); 599 g.addColorStop(0.25, '#0f0'); 600 g.addColorStop(0.25, '#0f0'); 601 g.addColorStop(0.25, '#0f0'); 602 g.addColorStop(0.25, '#ff0'); 603 g.addColorStop(0.5, '#00f'); 604 g.addColorStop(0.5, '#0f0'); 605 g.addColorStop(0.75, '#00f'); 606 g.addColorStop(0.75, '#f00'); 607 g.addColorStop(0.75, '#ff0'); 608 g.addColorStop(0.5, '#0f0'); 609 g.addColorStop(0.5, '#0f0'); 610 g.addColorStop(0.5, '#ff0'); 611 g.addColorStop(1, '#00f'); 612 ctx.fillStyle = g; 613 ctx.fillRect(0, 0, 200, 50); 614 @assert pixel 49,25 ==~ 0,0,255,255 +/- 16; 615 @assert pixel 51,25 ==~ 255,255,0,255 +/- 16; 616 @assert pixel 99,25 ==~ 0,0,255,255 +/- 16; 617 @assert pixel 101,25 ==~ 255,255,0,255 +/- 16; 618 @assert pixel 149,25 ==~ 0,0,255,255 +/- 16; 619 @assert pixel 151,25 ==~ 255,255,0,255 +/- 16; 620 expected: | 621 size 200 50 622 g = cairo.LinearGradient(0, 0, 50, 0) 623 g.add_color_stop_rgb(0, 1,1,0) 624 g.add_color_stop_rgb(1, 0,0,1) 625 cr.set_source(g) 626 cr.rectangle(0, 0, 50, 50) 627 cr.fill() 628 629 g = cairo.LinearGradient(50, 0, 100, 0) 630 g.add_color_stop_rgb(0, 1,1,0) 631 g.add_color_stop_rgb(1, 0,0,1) 632 cr.set_source(g) 633 cr.rectangle(50, 0, 50, 50) 634 cr.fill() 635 636 g = cairo.LinearGradient(100, 0, 150, 0) 637 g.add_color_stop_rgb(0, 1,1,0) 638 g.add_color_stop_rgb(1, 0,0,1) 639 cr.set_source(g) 640 cr.rectangle(100, 0, 50, 50) 641 cr.fill() 642 643 g = cairo.LinearGradient(150, 0, 200, 0) 644 g.add_color_stop_rgb(0, 1,1,0) 645 g.add_color_stop_rgb(1, 0,0,1) 646 cr.set_source(g) 647 cr.rectangle(150, 0, 50, 50) 648 cr.fill() 649 650 - name: 2d.gradient.interpolate.overlap2 651 code: | 652 var g = ctx.createLinearGradient(0, 0, 100, 0); 653 var ps = [ 0, 1/10, 1/4, 1/3, 1/2, 3/4, 1 ]; 654 for (var p = 0; p < ps.length; ++p) 655 { 656 g.addColorStop(ps[p], '#0f0'); 657 for (var i = 0; i < 15; ++i) 658 g.addColorStop(ps[p], '#f00'); 659 g.addColorStop(ps[p], '#0f0'); 660 } 661 ctx.fillStyle = g; 662 ctx.fillRect(0, 0, 100, 50); 663 @assert pixel 1,25 == 0,255,0,255; 664 @assert pixel 30,25 == 0,255,0,255; 665 @assert pixel 40,25 == 0,255,0,255; 666 @assert pixel 60,25 == 0,255,0,255; 667 @assert pixel 80,25 == 0,255,0,255; 668 expected: green 669 670 - name: 2d.gradient.empty 671 code: | 672 ctx.fillStyle = '#0f0'; 673 ctx.fillRect(0, 0, 100, 50); 674 var g = ctx.createLinearGradient(0, 0, 0, 50); 675 ctx.fillStyle = g; 676 ctx.fillRect(0, 0, 100, 50); 677 @assert pixel 50,25 ==~ 0,255,0,255; 678 expected: green 679 680 - name: 2d.gradient.object.update 681 code: | 682 var g = ctx.createLinearGradient(-100, 0, 200, 0); 683 g.addColorStop(0, '#f00'); 684 g.addColorStop(1, '#f00'); 685 ctx.fillStyle = g; 686 ctx.fillRect(0, 0, 100, 50); 687 g.addColorStop(0.1, '#0f0'); 688 g.addColorStop(0.9, '#0f0'); 689 ctx.fillRect(0, 0, 100, 50); 690 @assert pixel 50,25 ==~ 0,255,0,255; 691 expected: green 692 693 - name: 2d.gradient.object.compare 694 code: | 695 var g1 = ctx.createLinearGradient(0, 0, 100, 0); 696 var g2 = ctx.createLinearGradient(0, 0, 100, 0); 697 @assert g1 !== g2; 698 ctx.fillStyle = g1; 699 @assert ctx.fillStyle === g1; 700 701 - name: 2d.gradient.object.crosscanvas 702 code: | 703 ctx.fillStyle = '#f00'; 704 ctx.fillRect(0, 0, 100, 50); 705 var g = {{ create_canvas }}.getContext('2d').createLinearGradient(0, 0, 100, 0); 706 g.addColorStop(0, '#0f0'); 707 g.addColorStop(1, '#0f0'); 708 ctx.fillStyle = g; 709 ctx.fillRect(0, 0, 100, 50); 710 @assert pixel 50,25 ==~ 0,255,0,255; 711 expected: green 712 append_variants_to_name: false 713 variants: 714 - HtmlCanvas: 715 canvas_types: ['HtmlCanvas'] 716 create_canvas: document.createElement('canvas') 717 OffscreenCanvas: 718 canvas_types: ['OffscreenCanvas', 'Worker'] 719 create_canvas: new OffscreenCanvas(100, 50) 720 721 - name: 2d.gradient.object.current 722 canvas_types: ['HtmlCanvas'] 723 code: | 724 canvas.setAttribute('style', 'color: #f00'); 725 726 ctx.fillStyle = '#f00'; 727 ctx.fillRect(0, 0, 100, 50); 728 729 var g = ctx.createLinearGradient(0, 0, 100, 0); 730 g.addColorStop(0, 'currentColor'); 731 g.addColorStop(1, 'currentColor'); 732 ctx.fillStyle = g; 733 ctx.fillRect(0, 0, 100, 50); 734 @assert pixel 50,25 ==~ 0,0,0,255; 735 expected: | 736 size 100 50 737 cr.set_source_rgb(0, 0, 0) 738 cr.rectangle(0, 0, 100, 50) 739 cr.fill() 740 741 - name: 2d.gradient.object.invalidoffset 742 code: | 743 var g = ctx.createLinearGradient(0, 0, 100, 0); 744 @assert throws INDEX_SIZE_ERR g.addColorStop(-1, '#000'); 745 @assert throws INDEX_SIZE_ERR g.addColorStop(2, '#000'); 746 @assert throws TypeError g.addColorStop(Infinity, '#000'); 747 @assert throws TypeError g.addColorStop(-Infinity, '#000'); 748 @assert throws TypeError g.addColorStop(NaN, '#000'); 749 750 - name: 2d.gradient.object.invalidcolor 751 code: | 752 var g = ctx.createLinearGradient(0, 0, 100, 0); 753 @assert throws SYNTAX_ERR g.addColorStop(0, ""); 754 @assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); 755 @assert throws SYNTAX_ERR g.addColorStop(0, 'null'); 756 @assert throws SYNTAX_ERR g.addColorStop(0, 'undefined'); 757 @assert throws SYNTAX_ERR g.addColorStop(0, null); 758 @assert throws SYNTAX_ERR g.addColorStop(0, undefined); 759 760 var g = ctx.createRadialGradient(0, 0, 0, 100, 0, 0); 761 @assert throws SYNTAX_ERR g.addColorStop(0, ""); 762 @assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); 763 @assert throws SYNTAX_ERR g.addColorStop(0, 'null'); 764 @assert throws SYNTAX_ERR g.addColorStop(0, 'undefined'); 765 @assert throws SYNTAX_ERR g.addColorStop(0, null); 766 @assert throws SYNTAX_ERR g.addColorStop(0, undefined); 767 768 769 - name: 2d.gradient.linear.nonfinite 770 desc: createLinearGradient() throws TypeError if arguments are not finite 771 notes: *bindings 772 code: | 773 @nonfinite @assert throws TypeError ctx.createLinearGradient(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>); 774 775 - name: 2d.gradient.linear.transform.1 776 desc: Linear gradient coordinates are relative to the coordinate space at the time 777 of filling 778 code: | 779 var g = ctx.createLinearGradient(0, 0, 200, 0); 780 g.addColorStop(0, '#f00'); 781 g.addColorStop(0.25, '#0f0'); 782 g.addColorStop(0.75, '#0f0'); 783 g.addColorStop(1, '#f00'); 784 ctx.fillStyle = g; 785 ctx.translate(-50, 0); 786 ctx.fillRect(50, 0, 100, 50); 787 @assert pixel 25,25 == 0,255,0,255; 788 @assert pixel 50,25 == 0,255,0,255; 789 @assert pixel 75,25 == 0,255,0,255; 790 expected: green 791 792 - name: 2d.gradient.linear.transform.2 793 desc: Linear gradient coordinates are relative to the coordinate space at the time 794 of filling 795 code: | 796 ctx.translate(100, 0); 797 var g = ctx.createLinearGradient(0, 0, 200, 0); 798 g.addColorStop(0, '#f00'); 799 g.addColorStop(0.25, '#0f0'); 800 g.addColorStop(0.75, '#0f0'); 801 g.addColorStop(1, '#f00'); 802 ctx.fillStyle = g; 803 ctx.translate(-150, 0); 804 ctx.fillRect(50, 0, 100, 50); 805 @assert pixel 25,25 == 0,255,0,255; 806 @assert pixel 50,25 == 0,255,0,255; 807 @assert pixel 75,25 == 0,255,0,255; 808 expected: green 809 810 - name: 2d.gradient.linear.transform.3 811 desc: Linear gradient transforms do not experience broken caching effects 812 code: | 813 var g = ctx.createLinearGradient(0, 0, 200, 0); 814 g.addColorStop(0, '#f00'); 815 g.addColorStop(0.25, '#0f0'); 816 g.addColorStop(0.75, '#0f0'); 817 g.addColorStop(1, '#f00'); 818 ctx.fillStyle = g; 819 ctx.fillRect(0, 0, 100, 50); 820 ctx.translate(-50, 0); 821 ctx.fillRect(50, 0, 100, 50); 822 @assert pixel 25,25 == 0,255,0,255; 823 @assert pixel 50,25 == 0,255,0,255; 824 @assert pixel 75,25 == 0,255,0,255; 825 expected: green 826 827 - name: 2d.gradient.radial.negative 828 desc: createRadialGradient() throws INDEX_SIZE_ERR if either radius is negative 829 code: | 830 @assert throws INDEX_SIZE_ERR ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1); 831 @assert throws INDEX_SIZE_ERR ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1); 832 @assert throws INDEX_SIZE_ERR ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1); 833 834 - name: 2d.gradient.radial.nonfinite 835 desc: createRadialGradient() throws TypeError if arguments are not finite 836 notes: *bindings 837 code: | 838 @nonfinite @assert throws TypeError ctx.createRadialGradient(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>); 839 840 - name: 2d.gradient.radial.inside1 841 code: | 842 ctx.fillStyle = '#f00'; 843 ctx.fillRect(0, 0, 100, 50); 844 845 var g = ctx.createRadialGradient(50, 25, 100, 50, 25, 200); 846 g.addColorStop(0, '#0f0'); 847 g.addColorStop(1, '#f00'); 848 ctx.fillStyle = g; 849 ctx.fillRect(0, 0, 100, 50); 850 851 @assert pixel 1,1 == 0,255,0,255; 852 @assert pixel 50,1 == 0,255,0,255; 853 @assert pixel 98,1 == 0,255,0,255; 854 @assert pixel 1,25 == 0,255,0,255; 855 @assert pixel 50,25 == 0,255,0,255; 856 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 857 @assert pixel 1,48 == 0,255,0,255; 858 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 859 @assert pixel 98,48 == 0,255,0,255; 860 expected: green 861 862 - name: 2d.gradient.radial.inside2 863 code: | 864 ctx.fillStyle = '#f00'; 865 ctx.fillRect(0, 0, 100, 50); 866 867 var g = ctx.createRadialGradient(50, 25, 200, 50, 25, 100); 868 g.addColorStop(0, '#f00'); 869 g.addColorStop(1, '#0f0'); 870 ctx.fillStyle = g; 871 ctx.fillRect(0, 0, 100, 50); 872 873 @assert pixel 1,1 == 0,255,0,255; 874 @assert pixel 50,1 == 0,255,0,255; 875 @assert pixel 98,1 == 0,255,0,255; 876 @assert pixel 1,25 == 0,255,0,255; 877 @assert pixel 50,25 == 0,255,0,255; 878 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 879 @assert pixel 1,48 == 0,255,0,255; 880 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 881 @assert pixel 98,48 == 0,255,0,255; 882 expected: green 883 884 - name: 2d.gradient.radial.inside3 885 code: | 886 ctx.fillStyle = '#f00'; 887 ctx.fillRect(0, 0, 100, 50); 888 889 var g = ctx.createRadialGradient(50, 25, 200, 50, 25, 100); 890 g.addColorStop(0, '#f00'); 891 g.addColorStop(0.993, '#f00'); 892 g.addColorStop(1, '#0f0'); 893 ctx.fillStyle = g; 894 ctx.fillRect(0, 0, 100, 50); 895 896 @assert pixel 1,1 == 0,255,0,255; 897 @assert pixel 50,1 == 0,255,0,255; 898 @assert pixel 98,1 == 0,255,0,255; 899 @assert pixel 1,25 == 0,255,0,255; 900 @assert pixel 50,25 == 0,255,0,255; 901 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 902 @assert pixel 1,48 == 0,255,0,255; 903 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 904 @assert pixel 98,48 == 0,255,0,255; 905 expected: green 906 907 - name: 2d.gradient.radial.outside1 908 code: | 909 ctx.fillStyle = '#f00'; 910 ctx.fillRect(0, 0, 100, 50); 911 912 var g = ctx.createRadialGradient(200, 25, 10, 200, 25, 20); 913 g.addColorStop(0, '#f00'); 914 g.addColorStop(1, '#0f0'); 915 ctx.fillStyle = g; 916 ctx.fillRect(0, 0, 100, 50); 917 918 @assert pixel 1,1 == 0,255,0,255; 919 @assert pixel 50,1 == 0,255,0,255; 920 @assert pixel 98,1 == 0,255,0,255; 921 @assert pixel 1,25 == 0,255,0,255; 922 @assert pixel 50,25 == 0,255,0,255; 923 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 924 @assert pixel 1,48 == 0,255,0,255; 925 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 926 @assert pixel 98,48 == 0,255,0,255; 927 expected: green 928 929 - name: 2d.gradient.radial.outside2 930 code: | 931 ctx.fillStyle = '#f00'; 932 ctx.fillRect(0, 0, 100, 50); 933 934 var g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10); 935 g.addColorStop(0, '#0f0'); 936 g.addColorStop(1, '#f00'); 937 ctx.fillStyle = g; 938 ctx.fillRect(0, 0, 100, 50); 939 940 @assert pixel 1,1 == 0,255,0,255; 941 @assert pixel 50,1 == 0,255,0,255; 942 @assert pixel 98,1 == 0,255,0,255; 943 @assert pixel 1,25 == 0,255,0,255; 944 @assert pixel 50,25 == 0,255,0,255; 945 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 946 @assert pixel 1,48 == 0,255,0,255; 947 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 948 @assert pixel 98,48 == 0,255,0,255; 949 expected: green 950 951 - name: 2d.gradient.radial.outside3 952 code: | 953 ctx.fillStyle = '#f00'; 954 ctx.fillRect(0, 0, 100, 50); 955 956 var g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10); 957 g.addColorStop(0, '#0f0'); 958 g.addColorStop(0.001, '#f00'); 959 g.addColorStop(1, '#f00'); 960 ctx.fillStyle = g; 961 ctx.fillRect(0, 0, 100, 50); 962 963 @assert pixel 1,1 == 0,255,0,255; 964 @assert pixel 50,1 == 0,255,0,255; 965 @assert pixel 98,1 == 0,255,0,255; 966 @assert pixel 1,25 == 0,255,0,255; 967 @assert pixel 50,25 == 0,255,0,255; 968 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 969 @assert pixel 1,48 == 0,255,0,255; 970 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 971 @assert pixel 98,48 == 0,255,0,255; 972 expected: green 973 974 - name: 2d.gradient.radial.touch1 975 code: | 976 ctx.fillStyle = '#0f0'; 977 ctx.fillRect(0, 0, 100, 50); 978 979 var g = ctx.createRadialGradient(150, 25, 50, 200, 25, 100); 980 g.addColorStop(0, '#f00'); 981 g.addColorStop(1, '#f00'); 982 ctx.fillStyle = g; 983 ctx.fillRect(0, 0, 100, 50); 984 985 @assert pixel 1,1 == 0,255,0,255; @moz-todo 986 @assert pixel 50,1 == 0,255,0,255; @moz-todo 987 @assert pixel 98,1 == 0,255,0,255; @moz-todo 988 @assert pixel 1,25 == 0,255,0,255; @moz-todo 989 @assert pixel 50,25 == 0,255,0,255; @moz-todo 990 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; @moz-todo 991 @assert pixel 1,48 == 0,255,0,255; @moz-todo 992 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; @moz-todo 993 @assert pixel 98,48 == 0,255,0,255; @moz-todo 994 expected: green 995 996 - name: 2d.gradient.radial.touch2 997 code: | 998 ctx.fillStyle = '#f00'; 999 ctx.fillRect(0, 0, 100, 50); 1000 1001 var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150); 1002 g.addColorStop(0, '#f00'); 1003 g.addColorStop(0.01, '#0f0'); 1004 g.addColorStop(0.99, '#0f0'); 1005 g.addColorStop(1, '#f00'); 1006 ctx.fillStyle = g; 1007 ctx.fillRect(0, 0, 100, 50); 1008 1009 @assert pixel 1,1 == 0,255,0,255; 1010 @assert pixel 50,1 == 0,255,0,255; 1011 @assert pixel 98,1 == 0,255,0,255; 1012 @assert pixel 1,25 == 0,255,0,255; 1013 @assert pixel 50,25 == 0,255,0,255; 1014 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 1015 @assert pixel 1,48 == 0,255,0,255; 1016 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 1017 @assert pixel 98,48 == 0,255,0,255; 1018 expected: green 1019 1020 - name: 2d.gradient.radial.touch3 1021 code: | 1022 ctx.fillStyle = '#0f0'; 1023 ctx.fillRect(0, 0, 100, 50); 1024 1025 var g = ctx.createRadialGradient(120, -15, 25, 140, -30, 50); 1026 g.addColorStop(0, '#f00'); 1027 g.addColorStop(1, '#f00'); 1028 ctx.fillStyle = g; 1029 ctx.fillRect(0, 0, 100, 50); 1030 1031 @assert pixel 1,1 == 0,255,0,255; @moz-todo 1032 @assert pixel 50,1 == 0,255,0,255; @moz-todo 1033 @assert pixel 98,1 == 0,255,0,255; @moz-todo 1034 @assert pixel 1,25 == 0,255,0,255; @moz-todo 1035 @assert pixel 50,25 == 0,255,0,255; @moz-todo 1036 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; @moz-todo 1037 @assert pixel 1,48 == 0,255,0,255; @moz-todo 1038 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; @moz-todo 1039 @assert pixel 98,48 == 0,255,0,255; @moz-todo 1040 expected: green 1041 1042 - name: 2d.gradient.radial.equal 1043 code: | 1044 ctx.fillStyle = '#0f0'; 1045 ctx.fillRect(0, 0, 100, 50); 1046 1047 var g = ctx.createRadialGradient(50, 25, 20, 50, 25, 20); 1048 g.addColorStop(0, '#f00'); 1049 g.addColorStop(1, '#f00'); 1050 ctx.fillStyle = g; 1051 ctx.fillRect(0, 0, 100, 50); 1052 1053 @assert pixel 1,1 == 0,255,0,255; @moz-todo 1054 @assert pixel 50,1 == 0,255,0,255; @moz-todo 1055 @assert pixel 98,1 == 0,255,0,255; @moz-todo 1056 @assert pixel 1,25 == 0,255,0,255; @moz-todo 1057 @assert pixel 50,25 == 0,255,0,255; @moz-todo 1058 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; @moz-todo 1059 @assert pixel 1,48 == 0,255,0,255; @moz-todo 1060 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; @moz-todo 1061 @assert pixel 98,48 == 0,255,0,255; @moz-todo 1062 expected: green 1063 1064 - name: 2d.gradient.radial.cone.behind 1065 code: | 1066 ctx.fillStyle = '#0f0'; 1067 ctx.fillRect(0, 0, 100, 50); 1068 1069 var g = ctx.createRadialGradient(120, 25, 10, 211, 25, 100); 1070 g.addColorStop(0, '#f00'); 1071 g.addColorStop(1, '#f00'); 1072 ctx.fillStyle = g; 1073 ctx.fillRect(0, 0, 100, 50); 1074 1075 @assert pixel 1,1 == 0,255,0,255; @moz-todo 1076 @assert pixel 50,1 == 0,255,0,255; @moz-todo 1077 @assert pixel 98,1 == 0,255,0,255; @moz-todo 1078 @assert pixel 1,25 == 0,255,0,255; @moz-todo 1079 @assert pixel 50,25 == 0,255,0,255; @moz-todo 1080 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; @moz-todo 1081 @assert pixel 1,48 == 0,255,0,255; @moz-todo 1082 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; @moz-todo 1083 @assert pixel 98,48 == 0,255,0,255; @moz-todo 1084 expected: green 1085 1086 - name: 2d.gradient.radial.cone.front 1087 code: | 1088 ctx.fillStyle = '#f00'; 1089 ctx.fillRect(0, 0, 100, 50); 1090 1091 var g = ctx.createRadialGradient(311, 25, 10, 210, 25, 100); 1092 g.addColorStop(0, '#f00'); 1093 g.addColorStop(1, '#0f0'); 1094 ctx.fillStyle = g; 1095 ctx.fillRect(0, 0, 100, 50); 1096 1097 @assert pixel 1,1 == 0,255,0,255; 1098 @assert pixel 50,1 == 0,255,0,255; 1099 @assert pixel 98,1 == 0,255,0,255; 1100 @assert pixel 1,25 == 0,255,0,255; 1101 @assert pixel 50,25 == 0,255,0,255; 1102 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 1103 @assert pixel 1,48 == 0,255,0,255; 1104 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 1105 @assert pixel 98,48 == 0,255,0,255; 1106 expected: green 1107 1108 - name: 2d.gradient.radial.cone.bottom 1109 code: | 1110 ctx.fillStyle = '#f00'; 1111 ctx.fillRect(0, 0, 100, 50); 1112 1113 var g = ctx.createRadialGradient(210, 25, 100, 230, 25, 101); 1114 g.addColorStop(0, '#0f0'); 1115 g.addColorStop(1, '#f00'); 1116 ctx.fillStyle = g; 1117 ctx.fillRect(0, 0, 100, 50); 1118 1119 @assert pixel 1,1 == 0,255,0,255; 1120 @assert pixel 50,1 == 0,255,0,255; 1121 @assert pixel 98,1 == 0,255,0,255; 1122 @assert pixel 1,25 == 0,255,0,255; 1123 @assert pixel 50,25 == 0,255,0,255; 1124 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 1125 @assert pixel 1,48 == 0,255,0,255; 1126 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 1127 @assert pixel 98,48 == 0,255,0,255; 1128 expected: green 1129 1130 - name: 2d.gradient.radial.cone.top 1131 code: | 1132 ctx.fillStyle = '#f00'; 1133 ctx.fillRect(0, 0, 100, 50); 1134 1135 var g = ctx.createRadialGradient(230, 25, 100, 100, 25, 101); 1136 g.addColorStop(0, '#f00'); 1137 g.addColorStop(1, '#0f0'); 1138 ctx.fillStyle = g; 1139 ctx.fillRect(0, 0, 100, 50); 1140 1141 @assert pixel 1,1 == 0,255,0,255; 1142 @assert pixel 50,1 == 0,255,0,255; 1143 @assert pixel 98,1 == 0,255,0,255; 1144 @assert pixel 1,25 == 0,255,0,255; 1145 @assert pixel 50,25 == 0,255,0,255; 1146 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 1147 @assert pixel 1,48 == 0,255,0,255; 1148 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 1149 @assert pixel 98,48 == 0,255,0,255; 1150 expected: green 1151 1152 - name: 2d.gradient.radial.cone.beside 1153 code: | 1154 ctx.fillStyle = '#0f0'; 1155 ctx.fillRect(0, 0, 100, 50); 1156 1157 var g = ctx.createRadialGradient(0, 100, 40, 100, 100, 50); 1158 g.addColorStop(0, '#f00'); 1159 g.addColorStop(1, '#f00'); 1160 ctx.fillStyle = g; 1161 ctx.fillRect(0, 0, 100, 50); 1162 1163 @assert pixel 1,1 == 0,255,0,255; @moz-todo 1164 @assert pixel 50,1 == 0,255,0,255; @moz-todo 1165 @assert pixel 98,1 == 0,255,0,255; @moz-todo 1166 @assert pixel 1,25 == 0,255,0,255; @moz-todo 1167 @assert pixel 50,25 == 0,255,0,255; @moz-todo 1168 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; @moz-todo 1169 @assert pixel 1,48 == 0,255,0,255; @moz-todo 1170 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; @moz-todo 1171 @assert pixel 98,48 == 0,255,0,255; @moz-todo 1172 expected: green 1173 1174 - name: 2d.gradient.radial.cone.cylinder 1175 code: | 1176 ctx.fillStyle = '#f00'; 1177 ctx.fillRect(0, 0, 100, 50); 1178 1179 var g = ctx.createRadialGradient(210, 25, 100, 230, 25, 100); 1180 g.addColorStop(0, '#0f0'); 1181 g.addColorStop(1, '#f00'); 1182 ctx.fillStyle = g; 1183 ctx.fillRect(0, 0, 100, 50); 1184 1185 @assert pixel 1,1 == 0,255,0,255; 1186 @assert pixel 50,1 == 0,255,0,255; 1187 @assert pixel 98,1 == 0,255,0,255; 1188 @assert pixel 1,25 == 0,255,0,255; 1189 @assert pixel 50,25 == 0,255,0,255; 1190 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 1191 @assert pixel 1,48 == 0,255,0,255; 1192 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 1193 @assert pixel 98,48 == 0,255,0,255; 1194 expected: green 1195 1196 - name: 2d.gradient.radial.cone.shape1 1197 code: | 1198 var tol = 1; // tolerance to avoid antialiasing artifacts 1199 1200 ctx.fillStyle = '#0f0'; 1201 ctx.fillRect(0, 0, 100, 50); 1202 1203 ctx.fillStyle = '#f00'; 1204 ctx.beginPath(); 1205 ctx.moveTo(30+tol, 40); 1206 ctx.lineTo(110, -20+tol); 1207 ctx.lineTo(110, 100-tol); 1208 ctx.fill(); 1209 1210 var g = ctx.createRadialGradient(30+10*5/2, 40, 10*3/2, 30+10*15/4, 40, 10*9/4); 1211 g.addColorStop(0, '#0f0'); 1212 g.addColorStop(1, '#0f0'); 1213 ctx.fillStyle = g; 1214 ctx.fillRect(0, 0, 100, 50); 1215 1216 @assert pixel 1,1 == 0,255,0,255; 1217 @assert pixel 50,1 == 0,255,0,255; 1218 @assert pixel 98,1 == 0,255,0,255; 1219 @assert pixel 1,25 == 0,255,0,255; 1220 @assert pixel 50,25 == 0,255,0,255; 1221 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 1222 @assert pixel 1,48 == 0,255,0,255; 1223 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 1224 @assert pixel 98,48 == 0,255,0,255; 1225 expected: green 1226 1227 - name: 2d.gradient.radial.cone.shape2 1228 code: | 1229 var tol = 1; // tolerance to avoid antialiasing artifacts 1230 1231 ctx.fillStyle = '#0f0'; 1232 ctx.fillRect(0, 0, 100, 50); 1233 1234 var g = ctx.createRadialGradient(30+10*5/2, 40, 10*3/2, 30+10*15/4, 40, 10*9/4); 1235 g.addColorStop(0, '#f00'); 1236 g.addColorStop(1, '#f00'); 1237 ctx.fillStyle = g; 1238 ctx.fillRect(0, 0, 100, 50); 1239 1240 ctx.fillStyle = '#0f0'; 1241 ctx.beginPath(); 1242 ctx.moveTo(30-tol, 40); 1243 ctx.lineTo(110, -20-tol); 1244 ctx.lineTo(110, 100+tol); 1245 ctx.fill(); 1246 1247 @assert pixel 1,1 == 0,255,0,255; @moz-todo 1248 @assert pixel 50,1 == 0,255,0,255; @moz-todo 1249 @assert pixel 98,1 == 0,255,0,255; 1250 @assert pixel 1,25 == 0,255,0,255; @moz-todo 1251 @assert pixel 50,25 == 0,255,0,255; 1252 @assert pixel 98,25 ==~ 0,255,0,255 +/- 1; 1253 @assert pixel 1,48 == 0,255,0,255; @moz-todo 1254 @assert pixel 50,48 ==~ 0,255,0,255 +/- 1; 1255 @assert pixel 98,48 == 0,255,0,255; 1256 expected: green 1257 1258 - name: 2d.gradient.radial.transform.1 1259 desc: Radial gradient coordinates are relative to the coordinate space at the time 1260 of filling 1261 code: | 1262 var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2); 1263 g.addColorStop(0, '#0f0'); 1264 g.addColorStop(0.5, '#0f0'); 1265 g.addColorStop(0.51, '#f00'); 1266 g.addColorStop(1, '#f00'); 1267 ctx.fillStyle = g; 1268 ctx.translate(50, 25); 1269 ctx.scale(10, 10); 1270 ctx.fillRect(-5, -2.5, 10, 5); 1271 @assert pixel 25,25 == 0,255,0,255; 1272 @assert pixel 50,25 == 0,255,0,255; 1273 @assert pixel 75,25 == 0,255,0,255; 1274 expected: green 1275 1276 - name: 2d.gradient.radial.transform.2 1277 desc: Radial gradient coordinates are relative to the coordinate space at the time 1278 of filling 1279 code: | 1280 ctx.translate(100, 0); 1281 var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2); 1282 g.addColorStop(0, '#0f0'); 1283 g.addColorStop(0.5, '#0f0'); 1284 g.addColorStop(0.51, '#f00'); 1285 g.addColorStop(1, '#f00'); 1286 ctx.fillStyle = g; 1287 ctx.translate(-50, 25); 1288 ctx.scale(10, 10); 1289 ctx.fillRect(-5, -2.5, 10, 5); 1290 @assert pixel 25,25 == 0,255,0,255; 1291 @assert pixel 50,25 == 0,255,0,255; 1292 @assert pixel 75,25 == 0,255,0,255; 1293 expected: green 1294 1295 - name: 2d.gradient.radial.transform.3 1296 desc: Radial gradient transforms do not experience broken caching effects 1297 code: | 1298 var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2); 1299 g.addColorStop(0, '#0f0'); 1300 g.addColorStop(0.5, '#0f0'); 1301 g.addColorStop(0.51, '#f00'); 1302 g.addColorStop(1, '#f00'); 1303 ctx.fillStyle = g; 1304 ctx.fillRect(0, 0, 100, 50); 1305 ctx.translate(50, 25); 1306 ctx.scale(10, 10); 1307 ctx.fillRect(-5, -2.5, 10, 5); 1308 @assert pixel 25,25 == 0,255,0,255; 1309 @assert pixel 50,25 == 0,255,0,255; 1310 @assert pixel 75,25 == 0,255,0,255; 1311 expected: green 1312 1313 - name: 2d.gradient.conic.positive.rotation 1314 desc: Conic gradient with positive rotation 1315 code: | 1316 const g = ctx.createConicGradient(3*Math.PI/2, 50, 25); 1317 // It's red in the upper right region and green on the lower left region 1318 g.addColorStop(0, "#f00"); 1319 g.addColorStop(0.25, "#0f0"); 1320 g.addColorStop(0.50, "#0f0"); 1321 g.addColorStop(0.75, "#f00"); 1322 ctx.fillStyle = g; 1323 ctx.fillRect(0, 0, 100, 50); 1324 @assert pixel 25,15 ==~ 255,0,0,255 +/- 3; 1325 @assert pixel 75,40 ==~ 0,255,0,255 +/- 3; 1326 expected: green 1327 1328 - name: 2d.gradient.conic.negative.rotation 1329 desc: Conic gradient with negative rotation 1330 code: | 1331 const g = ctx.createConicGradient(-Math.PI/2, 50, 25); 1332 // It's red in the upper right region and green on the lower left region 1333 g.addColorStop(0, "#f00"); 1334 g.addColorStop(0.25, "#0f0"); 1335 g.addColorStop(0.50, "#0f0"); 1336 g.addColorStop(0.75, "#f00"); 1337 ctx.fillStyle = g; 1338 ctx.fillRect(0, 0, 100, 50); 1339 @assert pixel 25,15 ==~ 255,0,0,255 +/- 3; 1340 @assert pixel 75,40 ==~ 0,255,0,255 +/- 3; 1341 expected: green 1342 1343 - name: 2d.gradient.conic.invalid.inputs 1344 desc: Conic gradient function with invalid inputs 1345 code: | 1346 @nonfinite @assert throws TypeError ctx.createConicGradient(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>); 1347 1348 const g = ctx.createConicGradient(0, 0, 25); 1349 @nonfinite @assert throws TypeError g.addColorStop(<Infinity -Infinity NaN>, <'#f00'>); 1350 @nonfinite @assert throws SYNTAX_ERR g.addColorStop(<0>, <Infinity -Infinity NaN>); 1351 1352 - name: 2d.pattern.basic.type 1353 images: 1354 - green.png 1355 code: | 1356 {% set root = 'self' if canvas_type == 'Worker' else 'window' %} 1357 @assert {{ root }}.CanvasPattern !== undefined; 1358 1359 {{ root }}.CanvasPattern.prototype.thisImplementsCanvasPattern = true; 1360 1361 {{ load_image }} 1362 var pattern = ctx.createPattern(img, 'no-repeat'); 1363 @assert pattern.thisImplementsCanvasPattern; 1364 variants: &load-image-variant-definition 1365 - HtmlCanvas: 1366 append_variants_to_name: false 1367 canvas_types: ['HtmlCanvas'] 1368 load_image: var img = document.getElementById('{{ (images or svgimages)[0] }}'); 1369 OffscreenCanvas: 1370 append_variants_to_name: false 1371 canvas_types: ['OffscreenCanvas', 'Worker'] 1372 test_type: promise 1373 load_image: |- 1374 var response = await fetch('/images/{{ (images or svgimages)[0] }}') 1375 var blob = await response.blob(); 1376 var img = await createImageBitmap(blob); 1377 1378 - name: 2d.pattern.basic.image 1379 images: 1380 - green.png 1381 code: | 1382 ctx.fillStyle = '#f00'; 1383 ctx.fillRect(0, 0, 100, 50); 1384 {{ load_image }} 1385 var pattern = ctx.createPattern(img, 'no-repeat'); 1386 ctx.fillStyle = pattern; 1387 ctx.fillRect(0, 0, 100, 50); 1388 1389 @assert pixel 1,1 == 0,255,0,255; 1390 @assert pixel 98,1 == 0,255,0,255; 1391 @assert pixel 1,48 == 0,255,0,255; 1392 @assert pixel 98,48 == 0,255,0,255; 1393 expected: green 1394 variants: *load-image-variant-definition 1395 1396 - name: 2d.pattern.basic.canvas 1397 code: | 1398 ctx.fillStyle = '#f00'; 1399 ctx.fillRect(0, 0, 100, 50); 1400 1401 {{ create_canvas2 }} 1402 var ctx2 = canvas2.getContext('2d'); 1403 ctx2.fillStyle = '#0f0'; 1404 ctx2.fillRect(0, 0, 100, 50); 1405 1406 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 1407 ctx.fillStyle = pattern; 1408 ctx.fillRect(0, 0, 100, 50); 1409 1410 @assert pixel 1,1 == 0,255,0,255; 1411 @assert pixel 50,1 == 0,255,0,255; 1412 @assert pixel 98,1 == 0,255,0,255; 1413 @assert pixel 1,25 == 0,255,0,255; 1414 @assert pixel 50,25 == 0,255,0,255; 1415 @assert pixel 98,25 == 0,255,0,255; 1416 @assert pixel 1,48 == 0,255,0,255; 1417 @assert pixel 50,48 == 0,255,0,255; 1418 @assert pixel 98,48 == 0,255,0,255; 1419 expected: green 1420 variants: &create-canvas2-variant-definition 1421 - HtmlCanvas: 1422 append_variants_to_name: false 1423 canvas_types: ['HtmlCanvas'] 1424 create_canvas2: |- 1425 var canvas2 = document.createElement('canvas'); 1426 canvas2.width = 100; 1427 canvas2.height = 50; 1428 OffscreenCanvas: 1429 append_variants_to_name: false 1430 canvas_types: ['OffscreenCanvas', 'Worker'] 1431 create_canvas2: |- 1432 var canvas2 = new OffscreenCanvas(100, 50); 1433 1434 - name: 2d.pattern.basic.zerocanvas 1435 code: | 1436 canvas.width = 0; 1437 canvas.height = 10; 1438 @assert canvas.width === 0; 1439 @assert canvas.height === 10; 1440 @assert throws INVALID_STATE_ERR ctx.createPattern(canvas, 'repeat'); 1441 1442 canvas.width = 10; 1443 canvas.height = 0; 1444 @assert canvas.width === 10; 1445 @assert canvas.height === 0; 1446 @assert throws INVALID_STATE_ERR ctx.createPattern(canvas, 'repeat'); 1447 1448 canvas.width = 0; 1449 canvas.height = 0; 1450 @assert canvas.width === 0; 1451 @assert canvas.height === 0; 1452 @assert throws INVALID_STATE_ERR ctx.createPattern(canvas, 'repeat'); 1453 1454 - name: 2d.pattern.basic.nocontext 1455 code: | 1456 {{ create_canvas2 }} 1457 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 1458 1459 ctx.fillStyle = '#0f0'; 1460 ctx.fillRect(0, 0, 100, 50); 1461 ctx.fillStyle = '#f00'; 1462 ctx.fillStyle = pattern; 1463 ctx.fillRect(0, 0, 100, 50); 1464 1465 @assert pixel 1,1 == 0,255,0,255; 1466 @assert pixel 98,1 == 0,255,0,255; 1467 @assert pixel 1,48 == 0,255,0,255; 1468 @assert pixel 98,48 == 0,255,0,255; 1469 expected: green 1470 variants: *create-canvas2-variant-definition 1471 1472 - name: 2d.pattern.transform.identity 1473 code: | 1474 {{ create_canvas2 }} 1475 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 1476 pattern.setTransform(new DOMMatrix()); 1477 1478 ctx.fillStyle = '#0f0'; 1479 ctx.fillRect(0, 0, 100, 50); 1480 ctx.fillStyle = '#f00'; 1481 ctx.fillStyle = pattern; 1482 ctx.fillRect(0, 0, 100, 50); 1483 1484 @assert pixel 1,1 == 0,255,0,255; 1485 @assert pixel 98,1 == 0,255,0,255; 1486 @assert pixel 1,48 == 0,255,0,255; 1487 @assert pixel 98,48 == 0,255,0,255; 1488 expected: green 1489 variants: *create-canvas2-variant-definition 1490 1491 - name: 2d.pattern.transform.infinity 1492 code: | 1493 {{ create_canvas2 }} 1494 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 1495 pattern.setTransform({a: Infinity}); 1496 1497 ctx.fillStyle = '#0f0'; 1498 ctx.fillRect(0, 0, 100, 50); 1499 ctx.fillStyle = '#f00'; 1500 ctx.fillStyle = pattern; 1501 ctx.fillRect(0, 0, 100, 50); 1502 1503 @assert pixel 1,1 == 0,255,0,255; 1504 @assert pixel 98,1 == 0,255,0,255; 1505 @assert pixel 1,48 == 0,255,0,255; 1506 @assert pixel 98,48 == 0,255,0,255; 1507 expected: green 1508 variants: *create-canvas2-variant-definition 1509 1510 - name: 2d.pattern.transform.invalid 1511 code: | 1512 {{ create_canvas2 }} 1513 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 1514 @assert throws TypeError pattern.setTransform({a: 1, m11: 2}); 1515 variants: *create-canvas2-variant-definition 1516 1517 - name: 2d.pattern.image.undefined 1518 notes: *bindings 1519 code: | 1520 @assert throws TypeError ctx.createPattern(undefined, 'repeat'); 1521 1522 - name: 2d.pattern.image.null 1523 notes: *bindings 1524 code: | 1525 @assert throws TypeError ctx.createPattern(null, 'repeat'); 1526 1527 - name: 2d.pattern.image.string 1528 notes: *bindings 1529 code: | 1530 @assert throws TypeError ctx.createPattern('../images/red.png', 'repeat'); 1531 1532 - name: 2d.pattern.image.incomplete.nosrc 1533 canvas_types: ['HtmlCanvas'] 1534 code: | 1535 var img = new Image(); 1536 @assert ctx.createPattern(img, 'repeat') === null; 1537 1538 - name: 2d.pattern.image.incomplete.immediate 1539 canvas_types: ['HtmlCanvas'] 1540 images: 1541 - red.png 1542 code: | 1543 var img = new Image(); 1544 img.src = '../images/red.png'; 1545 // This triggers the "update the image data" algorithm. 1546 // The image will not go to the "completely available" state 1547 // until a fetch task in the networking task source is processed, 1548 // so the image must not be fully decodable yet: 1549 @assert ctx.createPattern(img, 'repeat') === null; @moz-todo 1550 1551 - name: 2d.pattern.image.incomplete.reload 1552 canvas_types: ['HtmlCanvas'] 1553 images: 1554 - yellow.png 1555 - red.png 1556 code: | 1557 var img = document.getElementById('yellow.png'); 1558 img.src = '../images/red.png'; 1559 // This triggers the "update the image data" algorithm, 1560 // and resets the image to the "unavailable" state. 1561 // The image will not go to the "completely available" state 1562 // until a fetch task in the networking task source is processed, 1563 // so the image must not be fully decodable yet: 1564 @assert ctx.createPattern(img, 'repeat') === null; @moz-todo 1565 1566 - name: 2d.pattern.image.incomplete.emptysrc 1567 canvas_types: ['HtmlCanvas'] 1568 images: 1569 - red.png 1570 mozilla: {throws: !!null ''} 1571 code: | 1572 var img = document.getElementById('red.png'); 1573 img.src = ""; 1574 @assert ctx.createPattern(img, 'repeat') === null; 1575 1576 - name: 2d.pattern.image.incomplete.removedsrc 1577 canvas_types: ['HtmlCanvas'] 1578 images: 1579 - red.png 1580 mozilla: {throws: !!null ''} 1581 code: | 1582 var img = document.getElementById('red.png'); 1583 img.removeAttribute('src'); 1584 @assert ctx.createPattern(img, 'repeat') === null; 1585 1586 - name: 2d.pattern.image.broken 1587 canvas_types: ['HtmlCanvas'] 1588 images: 1589 - broken.png 1590 code: | 1591 var img = document.getElementById('broken.png'); 1592 @assert throws INVALID_STATE_ERR ctx.createPattern(img, 'repeat'); 1593 1594 - name: 2d.pattern.image.nonexistent 1595 canvas_types: ['HtmlCanvas'] 1596 images: 1597 - no-such-image-really.png 1598 code: | 1599 var img = document.getElementById('no-such-image-really.png'); 1600 @assert throws INVALID_STATE_ERR ctx.createPattern(img, 'repeat'); 1601 1602 - name: 2d.pattern.svgimage.nonexistent 1603 canvas_types: ['HtmlCanvas'] 1604 svgimages: 1605 - no-such-image-really.png 1606 code: | 1607 var img = document.getElementById('no-such-image-really.png'); 1608 @assert throws INVALID_STATE_ERR ctx.createPattern(img, 'repeat'); 1609 1610 - name: 2d.pattern.image.nonexistent-but-loading 1611 canvas_types: ['HtmlCanvas'] 1612 code: | 1613 var img = document.createElement("img"); 1614 img.src = "/images/no-such-image-really.png"; 1615 @assert ctx.createPattern(img, 'repeat') === null; 1616 var img = document.createElementNS("http://www.w3.org/2000/svg", "image"); 1617 img.src = "/images/no-such-image-really.png"; 1618 @assert ctx.createPattern(img, 'repeat') === null; 1619 1620 - name: 2d.pattern.image.nosrc 1621 canvas_types: ['HtmlCanvas'] 1622 code: | 1623 var img = document.createElement("img"); 1624 @assert ctx.createPattern(img, 'repeat') === null; 1625 var img = document.createElementNS("http://www.w3.org/2000/svg", "image"); 1626 @assert ctx.createPattern(img, 'repeat') === null; 1627 1628 - name: 2d.pattern.image.zerowidth 1629 canvas_types: ['HtmlCanvas'] 1630 images: 1631 - red-zerowidth.svg 1632 code: | 1633 var img = document.getElementById('red-zerowidth.svg'); 1634 @assert ctx.createPattern(img, 'repeat') === null; 1635 1636 - name: 2d.pattern.image.zeroheight 1637 canvas_types: ['HtmlCanvas'] 1638 images: 1639 - red-zeroheight.svg 1640 code: | 1641 var img = document.getElementById('red-zeroheight.svg'); 1642 @assert ctx.createPattern(img, 'repeat') === null; 1643 1644 - name: 2d.pattern.svgimage.zerowidth 1645 canvas_types: ['HtmlCanvas'] 1646 svgimages: 1647 - red-zerowidth.svg 1648 code: | 1649 var img = document.getElementById('red-zerowidth.svg'); 1650 @assert ctx.createPattern(img, 'repeat') === null; 1651 1652 - name: 2d.pattern.svgimage.zeroheight 1653 canvas_types: ['HtmlCanvas'] 1654 svgimages: 1655 - red-zeroheight.svg 1656 code: | 1657 var img = document.getElementById('red-zeroheight.svg'); 1658 @assert ctx.createPattern(img, 'repeat') === null; 1659 1660 - name: 2d.pattern.repeat.empty 1661 images: 1662 - green-1x1.png 1663 code: | 1664 ctx.fillStyle = '#f00'; 1665 ctx.fillRect(0, 0, 100, 50); 1666 {{ load_image }} 1667 var pattern = ctx.createPattern(img, ""); 1668 ctx.fillStyle = pattern; 1669 ctx.fillRect(0, 0, 200, 50); 1670 1671 @assert pixel 1,1 == 0,255,0,255; 1672 @assert pixel 98,1 == 0,255,0,255; 1673 @assert pixel 1,48 == 0,255,0,255; 1674 @assert pixel 98,48 == 0,255,0,255; 1675 expected: green 1676 variants: *load-image-variant-definition 1677 1678 - name: 2d.pattern.repeat.null 1679 code: | 1680 @assert ctx.createPattern(canvas, null) != null; 1681 1682 - name: 2d.pattern.repeat.undefined 1683 code: | 1684 @assert throws SYNTAX_ERR ctx.createPattern(canvas, undefined); 1685 1686 - name: 2d.pattern.repeat.unrecognised 1687 code: | 1688 @assert throws SYNTAX_ERR ctx.createPattern(canvas, "invalid"); 1689 1690 - name: 2d.pattern.repeat.unrecognisednull 1691 code: | 1692 @assert throws SYNTAX_ERR ctx.createPattern(canvas, "null"); 1693 1694 - name: 2d.pattern.repeat.case 1695 code: | 1696 @assert throws SYNTAX_ERR ctx.createPattern(canvas, "Repeat"); 1697 1698 - name: 2d.pattern.repeat.nullsuffix 1699 code: | 1700 @assert throws SYNTAX_ERR ctx.createPattern(canvas, "repeat\0"); 1701 1702 - name: 2d.pattern.modify.image1 1703 canvas_types: ['HtmlCanvas'] 1704 images: 1705 - green.png 1706 code: | 1707 var img = document.getElementById('green.png'); 1708 var pattern = ctx.createPattern(img, 'no-repeat'); 1709 deferTest(); 1710 img.onload = t.step_func_done(function () 1711 { 1712 ctx.fillStyle = pattern; 1713 ctx.fillRect(0, 0, 100, 50); 1714 1715 @assert pixel 1,1 == 0,255,0,255; 1716 @assert pixel 98,1 == 0,255,0,255; 1717 @assert pixel 1,48 == 0,255,0,255; 1718 @assert pixel 98,48 == 0,255,0,255; 1719 }); 1720 img.src = '/images/red.png'; 1721 expected: green 1722 1723 - name: 2d.pattern.modify.image2 1724 canvas_types: ['HtmlCanvas'] 1725 images: 1726 - green.png 1727 code: | 1728 var img = document.getElementById('green.png'); 1729 var pattern = ctx.createPattern(img, 'no-repeat'); 1730 ctx.fillStyle = pattern; 1731 ctx.fillRect(0, 0, 100, 50); 1732 ctx.fillStyle = '#00f'; 1733 ctx.fillRect(0, 0, 100, 50); 1734 deferTest(); 1735 img.onload = t.step_func_done(function () 1736 { 1737 ctx.fillStyle = pattern; 1738 ctx.fillRect(0, 0, 100, 50); 1739 1740 @assert pixel 1,1 == 0,255,0,255; 1741 @assert pixel 98,1 == 0,255,0,255; 1742 @assert pixel 1,48 == 0,255,0,255; 1743 @assert pixel 98,48 == 0,255,0,255; 1744 }); 1745 img.src = '/images/red.png'; 1746 expected: green 1747 1748 - name: 2d.pattern.modify.canvas1 1749 canvas_types: ['HtmlCanvas'] 1750 code: | 1751 {{ create_canvas2 }} 1752 var ctx2 = canvas2.getContext('2d'); 1753 ctx2.fillStyle = '#0f0'; 1754 ctx2.fillRect(0, 0, 100, 50); 1755 1756 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 1757 1758 ctx2.fillStyle = '#f00'; 1759 ctx2.fillRect(0, 0, 100, 50); 1760 1761 ctx.fillStyle = pattern; 1762 ctx.fillRect(0, 0, 100, 50); 1763 1764 @assert pixel 1,1 == 0,255,0,255; 1765 @assert pixel 98,1 == 0,255,0,255; 1766 @assert pixel 1,48 == 0,255,0,255; 1767 @assert pixel 98,48 == 0,255,0,255; 1768 expected: green 1769 variants: *create-canvas2-variant-definition 1770 1771 - name: 2d.pattern.modify.canvas2 1772 code: | 1773 {{ create_canvas2 }} 1774 var ctx2 = canvas2.getContext('2d'); 1775 ctx2.fillStyle = '#0f0'; 1776 ctx2.fillRect(0, 0, 100, 50); 1777 1778 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 1779 ctx.fillStyle = pattern; 1780 ctx.fillRect(0, 0, 100, 50); 1781 ctx.fillStyle = '#f00'; 1782 ctx.fillRect(0, 0, 100, 50); 1783 1784 ctx2.fillStyle = '#f00'; 1785 ctx2.fillRect(0, 0, 100, 50); 1786 1787 ctx.fillStyle = pattern; 1788 ctx.fillRect(0, 0, 100, 50); 1789 1790 @assert pixel 1,1 == 0,255,0,255; 1791 @assert pixel 98,1 == 0,255,0,255; 1792 @assert pixel 1,48 == 0,255,0,255; 1793 @assert pixel 98,48 == 0,255,0,255; 1794 expected: green 1795 variants: *create-canvas2-variant-definition 1796 1797 - name: 2d.pattern.crosscanvas 1798 images: 1799 - green.png 1800 code: | 1801 {{ load_image }} 1802 1803 var pattern = {{ create_canvas }}.getContext('2d').createPattern(img, 'no-repeat'); 1804 ctx.fillStyle = '#f00'; 1805 ctx.fillRect(0, 0, 100, 50); 1806 ctx.fillStyle = pattern; 1807 ctx.fillRect(0, 0, 100, 50); 1808 1809 @assert pixel 50,25 == 0,255,0,255; 1810 expected: green 1811 append_variants_to_name: false 1812 variants: 1813 - HtmlCanvas: 1814 canvas_types: ['HtmlCanvas'] 1815 load_image: var img = document.getElementById('{{ images[0] }}'); 1816 create_canvas: document.createElement('canvas') 1817 OffscreenCanvas: 1818 canvas_types: ['OffscreenCanvas', 'Worker'] 1819 test_type: promise 1820 load_image: |- 1821 var response = await fetch('/images/{{ images[0] }}') 1822 var blob = await response.blob(); 1823 var img = await createImageBitmap(blob); 1824 create_canvas: new OffscreenCanvas(100, 50) 1825 1826 - name: 2d.pattern.paint.norepeat.basic 1827 images: 1828 - green.png 1829 code: | 1830 ctx.fillStyle = '#f00'; 1831 ctx.fillRect(0, 0, 100, 50); 1832 1833 {{ load_image }} 1834 var pattern = ctx.createPattern(img, 'no-repeat'); 1835 ctx.fillStyle = pattern; 1836 ctx.fillRect(0, 0, 100, 50); 1837 1838 @assert pixel 1,1 == 0,255,0,255; 1839 @assert pixel 98,1 == 0,255,0,255; 1840 @assert pixel 1,48 == 0,255,0,255; 1841 @assert pixel 98,48 == 0,255,0,255; 1842 expected: green 1843 variants: *load-image-variant-definition 1844 1845 - name: 2d.pattern.paint.norepeat.outside 1846 images: 1847 - red.png 1848 code: | 1849 ctx.fillStyle = '#f00'; 1850 ctx.fillRect(0, 0, 100, 50); 1851 1852 {{ load_image }} 1853 var pattern = ctx.createPattern(img, 'no-repeat'); 1854 ctx.fillStyle = '#0f0'; 1855 ctx.fillRect(0, 0, 100, 50); 1856 1857 ctx.fillStyle = pattern; 1858 ctx.fillRect(0, -50, 100, 50); 1859 ctx.fillRect(-100, 0, 100, 50); 1860 ctx.fillRect(0, 50, 100, 50); 1861 ctx.fillRect(100, 0, 100, 50); 1862 1863 @assert pixel 1,1 == 0,255,0,255; 1864 @assert pixel 98,1 == 0,255,0,255; 1865 @assert pixel 1,48 == 0,255,0,255; 1866 @assert pixel 98,48 == 0,255,0,255; 1867 expected: green 1868 variants: *load-image-variant-definition 1869 1870 - name: 2d.pattern.paint.norepeat.outside_arc 1871 images: 1872 - red-16x16.png 1873 code: | 1874 ctx.fillStyle = '#f00'; 1875 ctx.fillRect(0, 0, 100, 50); 1876 {{ load_image }} 1877 var pattern = ctx.createPattern(img, 'no-repeat'); 1878 ctx.fillStyle = '#0f0'; 1879 ctx.fillRect(0, 0, 100, 50); 1880 ctx.fillStyle = pattern; 1881 ctx.beginPath(); 1882 ctx.arc(0, 0, 50, 0, Math.PI * 2); 1883 ctx.closePath(); 1884 ctx.fill(); 1885 ctx.fillStyle = '#0f0'; 1886 ctx.fillRect(0, 0, 16, 16); 1887 @assert pixel 1,1 == 0,255,0,255; 1888 @assert pixel 20,1 == 0,255,0,255; 1889 @assert pixel 1,20 == 0,255,0,255; 1890 @assert pixel 48,48 == 0,255,0,255; 1891 expected: green 1892 variants: *load-image-variant-definition 1893 1894 - name: 2d.pattern.paint.norepeat.coord1 1895 images: 1896 - green.png 1897 code: | 1898 ctx.fillStyle = '#0f0'; 1899 ctx.fillRect(0, 0, 50, 50); 1900 ctx.fillStyle = '#f00'; 1901 ctx.fillRect(50, 0, 50, 50); 1902 1903 {{ load_image }} 1904 var pattern = ctx.createPattern(img, 'no-repeat'); 1905 ctx.fillStyle = pattern; 1906 ctx.translate(50, 0); 1907 ctx.fillRect(-50, 0, 100, 50); 1908 1909 @assert pixel 1,1 == 0,255,0,255; 1910 @assert pixel 98,1 == 0,255,0,255; 1911 @assert pixel 1,48 == 0,255,0,255; 1912 @assert pixel 98,48 == 0,255,0,255; 1913 expected: green 1914 variants: *load-image-variant-definition 1915 1916 - name: 2d.pattern.paint.norepeat.coord2 1917 images: 1918 - green.png 1919 code: | 1920 {{ load_image }} 1921 var pattern = ctx.createPattern(img, 'no-repeat'); 1922 ctx.fillStyle = pattern; 1923 ctx.fillRect(0, 0, 50, 50); 1924 1925 ctx.fillStyle = '#f00'; 1926 ctx.fillRect(50, 0, 50, 50); 1927 1928 ctx.fillStyle = pattern; 1929 ctx.translate(50, 0); 1930 ctx.fillRect(-50, 0, 100, 50); 1931 1932 @assert pixel 1,1 == 0,255,0,255; 1933 @assert pixel 98,1 == 0,255,0,255; 1934 @assert pixel 1,48 == 0,255,0,255; 1935 @assert pixel 98,48 == 0,255,0,255; 1936 expected: green 1937 variants: *load-image-variant-definition 1938 1939 - name: 2d.pattern.paint.norepeat.coord3 1940 images: 1941 - red.png 1942 code: | 1943 ctx.fillStyle = '#0f0'; 1944 ctx.fillRect(0, 0, 100, 50); 1945 1946 {{ load_image }} 1947 var pattern = ctx.createPattern(img, 'no-repeat'); 1948 ctx.fillStyle = pattern; 1949 ctx.translate(50, 25); 1950 ctx.fillRect(-50, -25, 100, 50); 1951 1952 ctx.fillStyle = '#0f0'; 1953 ctx.fillRect(0, 0, 50, 25); 1954 1955 @assert pixel 1,1 == 0,255,0,255; 1956 @assert pixel 98,1 == 0,255,0,255; 1957 @assert pixel 1,48 == 0,255,0,255; 1958 @assert pixel 98,48 == 0,255,0,255; 1959 expected: green 1960 variants: *load-image-variant-definition 1961 1962 - name: 2d.pattern.paint.repeat.basic 1963 images: 1964 - green-16x16.png 1965 code: | 1966 ctx.fillStyle = '#f00'; 1967 ctx.fillRect(0, 0, 100, 50); 1968 1969 {{ load_image }} 1970 var pattern = ctx.createPattern(img, 'repeat'); 1971 ctx.fillStyle = pattern; 1972 ctx.fillRect(0, 0, 100, 50); 1973 1974 @assert pixel 1,1 == 0,255,0,255; 1975 @assert pixel 98,1 == 0,255,0,255; 1976 @assert pixel 1,48 == 0,255,0,255; 1977 @assert pixel 98,48 == 0,255,0,255; 1978 expected: green 1979 variants: *load-image-variant-definition 1980 1981 - name: 2d.pattern.paint.repeat.outside 1982 images: 1983 - green-16x16.png 1984 code: | 1985 ctx.fillStyle = '#f00'; 1986 ctx.fillRect(0, 0, 100, 50); 1987 1988 {{ load_image }} 1989 var pattern = ctx.createPattern(img, 'repeat'); 1990 ctx.fillStyle = pattern; 1991 ctx.translate(50, 25); 1992 ctx.fillRect(-50, -25, 100, 50); 1993 1994 @assert pixel 1,1 == 0,255,0,255; 1995 @assert pixel 98,1 == 0,255,0,255; 1996 @assert pixel 1,48 == 0,255,0,255; 1997 @assert pixel 98,48 == 0,255,0,255; 1998 expected: green 1999 variants: *load-image-variant-definition 2000 2001 - name: 2d.pattern.paint.repeat.coord1 2002 images: 2003 - rgrg-256x256.png 2004 code: | 2005 ctx.fillStyle = '#f00'; 2006 ctx.fillRect(0, 0, 100, 50); 2007 2008 {{ load_image }} 2009 var pattern = ctx.createPattern(img, 'repeat'); 2010 ctx.fillStyle = pattern; 2011 ctx.translate(-128, -78); 2012 ctx.fillRect(128, 78, 100, 50); 2013 2014 @assert pixel 1,1 == 0,255,0,255; 2015 @assert pixel 98,1 == 0,255,0,255; 2016 @assert pixel 1,48 == 0,255,0,255; 2017 @assert pixel 98,48 == 0,255,0,255; 2018 expected: green 2019 variants: *load-image-variant-definition 2020 2021 - name: 2d.pattern.paint.repeat.coord2 2022 images: 2023 - ggrr-256x256.png 2024 code: | 2025 {{ load_image }} 2026 var pattern = ctx.createPattern(img, 'repeat'); 2027 ctx.fillStyle = pattern; 2028 ctx.fillRect(0, 0, 100, 50); 2029 2030 @assert pixel 1,1 == 0,255,0,255; 2031 @assert pixel 98,1 == 0,255,0,255; 2032 @assert pixel 1,48 == 0,255,0,255; 2033 @assert pixel 98,48 == 0,255,0,255; 2034 expected: green 2035 variants: *load-image-variant-definition 2036 2037 - name: 2d.pattern.paint.repeat.coord3 2038 images: 2039 - rgrg-256x256.png 2040 code: | 2041 {{ load_image }} 2042 var pattern = ctx.createPattern(img, 'repeat'); 2043 ctx.fillStyle = pattern; 2044 ctx.fillRect(0, 0, 100, 50); 2045 2046 ctx.translate(-128, -78); 2047 ctx.fillRect(128, 78, 100, 50); 2048 2049 @assert pixel 1,1 == 0,255,0,255; 2050 @assert pixel 98,1 == 0,255,0,255; 2051 @assert pixel 1,48 == 0,255,0,255; 2052 @assert pixel 98,48 == 0,255,0,255; 2053 expected: green 2054 variants: *load-image-variant-definition 2055 2056 - name: 2d.pattern.paint.repeatx.basic 2057 images: 2058 - green-16x16.png 2059 code: | 2060 ctx.fillStyle = '#0f0'; 2061 ctx.fillRect(0, 0, 100, 50); 2062 ctx.fillStyle = '#f00'; 2063 ctx.fillRect(0, 0, 100, 16); 2064 2065 {{ load_image }} 2066 var pattern = ctx.createPattern(img, 'repeat-x'); 2067 ctx.fillStyle = pattern; 2068 ctx.fillRect(0, 0, 100, 50); 2069 2070 @assert pixel 1,1 == 0,255,0,255; 2071 @assert pixel 98,1 == 0,255,0,255; 2072 @assert pixel 1,48 == 0,255,0,255; 2073 @assert pixel 98,48 == 0,255,0,255; 2074 expected: green 2075 variants: *load-image-variant-definition 2076 2077 - name: 2d.pattern.paint.repeatx.outside 2078 images: 2079 - red-16x16.png 2080 code: | 2081 ctx.fillStyle = '#0f0'; 2082 ctx.fillRect(0, 0, 100, 50); 2083 2084 {{ load_image }} 2085 var pattern = ctx.createPattern(img, 'repeat-x'); 2086 ctx.fillStyle = pattern; 2087 ctx.fillRect(0, 0, 100, 50); 2088 2089 ctx.fillStyle = '#0f0'; 2090 ctx.fillRect(0, 0, 100, 16); 2091 2092 @assert pixel 1,1 == 0,255,0,255; 2093 @assert pixel 98,1 == 0,255,0,255; 2094 @assert pixel 1,48 == 0,255,0,255; 2095 @assert pixel 98,48 == 0,255,0,255; 2096 expected: green 2097 variants: *load-image-variant-definition 2098 2099 - name: 2d.pattern.paint.repeatx.coord1 2100 images: 2101 - red-16x16.png 2102 code: | 2103 ctx.fillStyle = '#0f0'; 2104 ctx.fillRect(0, 0, 100, 50); 2105 2106 {{ load_image }} 2107 var pattern = ctx.createPattern(img, 'repeat-x'); 2108 ctx.fillStyle = pattern; 2109 ctx.translate(0, 16); 2110 ctx.fillRect(0, -16, 100, 50); 2111 2112 ctx.fillStyle = '#0f0'; 2113 ctx.fillRect(0, 0, 100, 16); 2114 2115 @assert pixel 1,1 == 0,255,0,255; 2116 @assert pixel 98,1 == 0,255,0,255; 2117 @assert pixel 1,25 == 0,255,0,255; 2118 @assert pixel 98,25 == 0,255,0,255; 2119 @assert pixel 1,48 == 0,255,0,255; 2120 @assert pixel 98,48 == 0,255,0,255; 2121 expected: green 2122 variants: *load-image-variant-definition 2123 2124 - name: 2d.pattern.paint.repeaty.basic 2125 images: 2126 - green-16x16.png 2127 code: | 2128 ctx.fillStyle = '#0f0'; 2129 ctx.fillRect(0, 0, 100, 50); 2130 ctx.fillStyle = '#f00'; 2131 ctx.fillRect(0, 0, 16, 50); 2132 2133 {{ load_image }} 2134 var pattern = ctx.createPattern(img, 'repeat-y'); 2135 ctx.fillStyle = pattern; 2136 ctx.fillRect(0, 0, 100, 50); 2137 2138 @assert pixel 1,1 == 0,255,0,255; 2139 @assert pixel 98,1 == 0,255,0,255; 2140 @assert pixel 1,48 == 0,255,0,255; 2141 @assert pixel 98,48 == 0,255,0,255; 2142 expected: green 2143 variants: *load-image-variant-definition 2144 2145 - name: 2d.pattern.paint.repeaty.outside 2146 images: 2147 - red-16x16.png 2148 code: | 2149 ctx.fillStyle = '#0f0'; 2150 ctx.fillRect(0, 0, 100, 50); 2151 2152 {{ load_image }} 2153 var pattern = ctx.createPattern(img, 'repeat-y'); 2154 ctx.fillStyle = pattern; 2155 ctx.fillRect(0, 0, 100, 50); 2156 2157 ctx.fillStyle = '#0f0'; 2158 ctx.fillRect(0, 0, 16, 50); 2159 2160 @assert pixel 1,1 == 0,255,0,255; 2161 @assert pixel 98,1 == 0,255,0,255; 2162 @assert pixel 1,48 == 0,255,0,255; 2163 @assert pixel 98,48 == 0,255,0,255; 2164 expected: green 2165 variants: *load-image-variant-definition 2166 2167 - name: 2d.pattern.paint.repeaty.coord1 2168 images: 2169 - red-16x16.png 2170 code: | 2171 ctx.fillStyle = '#0f0'; 2172 ctx.fillRect(0, 0, 100, 50); 2173 2174 {{ load_image }} 2175 var pattern = ctx.createPattern(img, 'repeat-y'); 2176 ctx.fillStyle = pattern; 2177 ctx.translate(48, 0); 2178 ctx.fillRect(-48, 0, 100, 50); 2179 2180 ctx.fillStyle = '#0f0'; 2181 ctx.fillRect(0, 0, 16, 50); 2182 2183 @assert pixel 1,1 == 0,255,0,255; 2184 @assert pixel 50,1 == 0,255,0,255; 2185 @assert pixel 98,1 == 0,255,0,255; 2186 @assert pixel 1,48 == 0,255,0,255; 2187 @assert pixel 50,48 == 0,255,0,255; 2188 @assert pixel 98,48 == 0,255,0,255; 2189 expected: green 2190 variants: *load-image-variant-definition 2191 2192 - name: 2d.pattern.paint.orientation.image 2193 desc: Image patterns do not get flipped when painted 2194 images: 2195 - rrgg-256x256.png 2196 code: | 2197 ctx.fillStyle = '#f00'; 2198 ctx.fillRect(0, 0, 100, 50); 2199 2200 {{ load_image }} 2201 var pattern = ctx.createPattern(img, 'no-repeat'); 2202 ctx.fillStyle = pattern; 2203 ctx.save(); 2204 ctx.translate(0, -103); 2205 ctx.fillRect(0, 103, 100, 50); 2206 ctx.restore(); 2207 2208 ctx.fillStyle = '#0f0'; 2209 ctx.fillRect(0, 0, 100, 25); 2210 2211 @assert pixel 1,1 == 0,255,0,255; 2212 @assert pixel 98,1 == 0,255,0,255; 2213 @assert pixel 1,48 == 0,255,0,255; 2214 @assert pixel 98,48 == 0,255,0,255; 2215 expected: green 2216 variants: *load-image-variant-definition 2217 2218 - name: 2d.pattern.paint.orientation.canvas 2219 desc: Canvas patterns do not get flipped when painted 2220 code: | 2221 ctx.fillStyle = '#f00'; 2222 ctx.fillRect(0, 0, 100, 50); 2223 2224 {{ create_canvas2 }} 2225 var ctx2 = canvas2.getContext('2d'); 2226 ctx2.fillStyle = '#f00'; 2227 ctx2.fillRect(0, 0, 100, 25); 2228 ctx2.fillStyle = '#0f0'; 2229 ctx2.fillRect(0, 25, 100, 25); 2230 2231 var pattern = ctx.createPattern(canvas2, 'no-repeat'); 2232 ctx.fillStyle = pattern; 2233 ctx.fillRect(0, 0, 100, 50); 2234 ctx.fillStyle = '#0f0'; 2235 ctx.fillRect(0, 0, 100, 25); 2236 2237 @assert pixel 1,1 == 0,255,0,255; 2238 @assert pixel 98,1 == 0,255,0,255; 2239 @assert pixel 1,48 == 0,255,0,255; 2240 @assert pixel 98,48 == 0,255,0,255; 2241 expected: green 2242 variants: *create-canvas2-variant-definition 2243 2244 - name: 2d.pattern.animated.gif 2245 desc: createPattern() of an animated GIF draws the first frame 2246 canvas_types: ['HtmlCanvas'] 2247 images: 2248 - anim-gr.gif 2249 code: | 2250 deferTest(); 2251 step_timeout(function () { 2252 var pattern = ctx.createPattern(document.getElementById('anim-gr.gif'), 'repeat'); 2253 ctx.fillStyle = pattern; 2254 ctx.fillRect(0, 0, 50, 50); 2255 step_timeout(t.step_func_done(function () { 2256 ctx.fillRect(50, 0, 50, 50); 2257 @assert pixel 25,25 ==~ 0,255,0,255; 2258 @assert pixel 75,25 ==~ 0,255,0,255; 2259 }), 250); 2260 }, 250); 2261 expected: green 2262 2263 - name: 2d.fillStyle.CSSRGB 2264 desc: CSSRGB works as color input 2265 canvas_types: ['HtmlCanvas', 'OffscreenCanvas'] 2266 code: | 2267 ctx.fillStyle = new CSSRGB(1, 0, 1); 2268 @assert ctx.fillStyle === '#ff00ff'; 2269 ctx.fillRect(0, 0, 100, 50); 2270 @assert pixel 50,25 == 255,0,255,255; 2271 2272 const color = new CSSRGB(0, CSS.percent(50), 0); 2273 ctx.fillStyle = color; 2274 @assert ctx.fillStyle === '#008000'; 2275 ctx.fillRect(0, 0, 100, 50); 2276 @assert pixel 50,25 == 0,128,0,255; 2277 color.g = 0; 2278 ctx.fillStyle = color; 2279 @assert ctx.fillStyle === '#000000'; 2280 ctx.fillRect(0, 0, 100, 50); 2281 @assert pixel 50,25 == 0,0,0,255; 2282 2283 color.alpha = 0; 2284 ctx.fillStyle = color; 2285 @assert ctx.fillStyle === 'rgba(0, 0, 0, 0)'; 2286 ctx.reset(); 2287 color.alpha = 0.5; 2288 ctx.fillStyle = color; 2289 ctx.fillRect(0, 0, 100, 50); 2290 @assert pixel 50,25 == 0,0,0,128; 2291 2292 color.alpha = 1; 2293 color.g = 1; 2294 ctx.fillStyle = color; 2295 ctx.fillRect(0, 0, 100, 50); 2296 expected: green 2297 2298 - name: 2d.fillStyle.CSSHSL 2299 desc: CSSHSL works as color input 2300 canvas_types: ['HtmlCanvas', 'OffscreenCanvas'] 2301 code: | 2302 ctx.fillStyle = new CSSHSL(CSS.deg(180), 0.5, 0.5); 2303 ctx.fillRect(0, 0, 100, 50); 2304 @assert pixel 50,25 ==~ 64,191,191,255 +/- 3; 2305 2306 const color = new CSSHSL(CSS.deg(180), 1, 1); 2307 ctx.fillStyle = color; 2308 @assert ctx.fillStyle === '#ffffff'; 2309 ctx.fillRect(0, 0, 100, 50); 2310 @assert pixel 50,25 == 255,255,255,255; 2311 color.l = 0.5; 2312 ctx.fillStyle = color; 2313 @assert ctx.fillStyle === '#00ffff'; 2314 ctx.fillRect(0, 0, 100, 50); 2315 @assert pixel 50,25 == 0,255,255,255; 2316 2317 color.h = CSS.deg(120); 2318 color.s = 1; 2319 color.l = 0.5; 2320 ctx.fillStyle = color; 2321 ctx.fillRect(0, 0, 100, 50); 2322 expected: green 2323 2324 - name: 2d.fillStyle.colormix 2325 desc: color-mix works as color input 2326 canvas_types: ['HtmlCanvas', 'OffscreenCanvas', 'Worker'] 2327 code: | 2328 ctx.fillStyle = "color-mix(in srgb, red, blue)"; 2329 @assert ctx.fillStyle === 'color(srgb 0.5 0 0.5)'; 2330 ctx.fillStyle = "color-mix(in srgb, red, color(srgb 1 0 0))"; 2331 @assert ctx.fillStyle === 'color(srgb 1 0 0)'; 2332 2333 - name: 2d.fillStyle.colormix.currentcolor 2334 desc: color-mix works as color input with currentcolor 2335 canvas_types: ['HtmlCanvas'] 2336 code: | 2337 canvas.setAttribute('style', 'color: magenta'); 2338 ctx.fillStyle = "color-mix(in srgb, black, currentcolor)"; 2339 @assert ctx.fillStyle === 'color(srgb 0.5 0 0.5)'; 2340 ctx.strokeStyle = "color-mix(in srgb, black, currentcolor)"; 2341 @assert ctx.strokeStyle === 'color(srgb 0.5 0 0.5)'; 2342 2343 - name: 2d.strokeStyle.colormix 2344 desc: color-mix works as color input 2345 canvas_types: ['HtmlCanvas', 'OffscreenCanvas'] 2346 code: | 2347 ctx.strokeStyle = "color-mix(in srgb, red, blue)"; 2348 @assert ctx.strokeStyle === 'color(srgb 0.5 0 0.5)'; 2349 ctx.strokeStyle = "color-mix(in srgb, red, color(srgb 1 0 0))"; 2350 @assert ctx.strokeStyle === 'color(srgb 1 0 0)'; 2351 2352 - name: 2d.gradient.colormix 2353 desc: color-mix works as CanvasGradient color input 2354 canvas_types: ['HtmlCanvas'] 2355 code: | 2356 var g = ctx.createLinearGradient(0, 0, 100, 0); 2357 g.addColorStop(0, '#f00'); 2358 g.addColorStop(1, 'color-mix(in srgb, #0f0, #00f)'); 2359 ctx.fillStyle = g; 2360 ctx.fillRect(0, 0, 100, 50); 2361 @assert pixel 25,25 ==~ 212,81,61,255 +/- 3; 2362 @assert pixel 50,25 ==~ 167,106,88,255 +/- 3; 2363 @assert pixel 75,25 ==~ 113,120,109,255 +/- 3; 2364 2365 - name: 2d.fillStyle.relativecolor 2366 desc: Relative color works as color input 2367 canvas_types: ['HtmlCanvas', 'OffscreenCanvas', 'Worker'] 2368 code: | 2369 ctx.fillStyle = "rgb(from red g r b)"; 2370 @assert ctx.fillStyle === 'color(srgb 0 1 0)'; 2371 ctx.fillStyle = "color(from color(srgb 0.25 0.5 0.75 / 0.5) srgb r g b / alpha)"; 2372 @assert ctx.fillStyle === 'color(srgb 0.25 0.5 0.75 / 0.5)'; 2373 2374 - name: 2d.fillStyle.relativecolor.currentcolor 2375 desc: Relative color works as color input with currentcolor 2376 canvas_types: ['HtmlCanvas'] 2377 code: | 2378 canvas.setAttribute('style', 'color: magenta'); 2379 ctx.fillStyle = "rgb(from currentcolor g r b)"; 2380 @assert ctx.fillStyle === 'color(srgb 0 1 1)'; 2381 ctx.strokeStyle = "rgb(from currentcolor g r b)"; 2382 @assert ctx.strokeStyle === 'color(srgb 0 1 1)'; 2383 2384 - name: 2d.strokeStyle.relativecolor 2385 desc: Relative color works as color input 2386 canvas_types: ['HtmlCanvas', 'OffscreenCanvas', 'Worker'] 2387 code: | 2388 ctx.strokeStyle = "rgb(from red g r b)"; 2389 @assert ctx.strokeStyle === 'color(srgb 0 1 0)'; 2390 ctx.strokeStyle = "color(from color(srgb 0.25 0.5 0.75 / 0.5) srgb r g b / alpha)"; 2391 @assert ctx.strokeStyle === 'color(srgb 0.25 0.5 0.75 / 0.5)'; 2392 2393 - name: 2d.gradient.relativecolor 2394 desc: Relative color works as CanvasGradient color input 2395 canvas_types: ['HtmlCanvas', 'OffscreenCanvas', 'Worker'] 2396 code: | 2397 var g = ctx.createLinearGradient(0, 0, 100, 0); 2398 g.addColorStop(0, '#f00'); 2399 g.addColorStop(1, 'rgb(from red g r b)'); 2400 ctx.fillStyle = g; 2401 ctx.fillRect(0, 0, 100, 50); 2402 @assert pixel 25,25 ==~ 236,116,0,255 +/- 3; 2403 @assert pixel 50,25 ==~ 208,170,0,255 +/- 3; 2404 @assert pixel 75,25 ==~ 159,214,0,255 +/- 3; 2405 2406 - name: 2d.gradient.colorInterpolationMethod 2407 desc: CSS color spaces work as a CanvasGradient color interpolation methods 2408 fuzzy: maxDifference=0-1; totalPixels=0-60000 2409 code: | 2410 var g = ctx.createLinearGradient(0, 0, 100, 0); 2411 g.addColorStop(0, 'color(srgb 1 0 0)'); 2412 g.addColorStop(1, 'color(srgb 0 1 0)'); 2413 g.colorInterpolationMethod = '{{ variant_name }}'; 2414 ctx.fillStyle = g; 2415 ctx.fillRect(0, 0, 100, 50); 2416 html_reference: | 2417 <style> 2418 #swatch-{{ variant_name }} { 2419 width: 100%; 2420 height: 100%; 2421 background: linear-gradient(to right in {{ variant_name }}, 2422 color(srgb 1 0 0), color(srgb 0 1 0)); 2423 } 2424 </style> 2425 <div id="swatch-{{ variant_name }}"></div> 2426 variants_layout: [single_file] 2427 grid_width: 5 2428 variants: 2429 - srgb: 2430 hsl: 2431 hwb: 2432 srgb-linear: 2433 display-p3-linear: 2434 display-p3: 2435 a98-rgb: 2436 prophoto-rgb: 2437 rec2020: 2438 lab: 2439 oklab: 2440 lch: 2441 oklch: 2442 xyz: 2443 xyz-d50: 2444 xyz-d65: 2445 2446 - name: 2d.gradient.hueInterpolationMethod 2447 desc: CSS hue interpolation methods work for CanvasGradients 2448 fuzzy: maxDifference=0-1; totalPixels=0-60000 2449 code: | 2450 // Generate two gradients, one from red to green, the other from red to blue. 2451 // In the first instance "shorter" is equivalent to "increasing". 2452 // In the second, "shorter" is equivalent to "decreasing". 2453 2454 var g = ctx.createLinearGradient(0, 0, 100, 0); 2455 g.addColorStop(0, 'color(srgb 1 0 0)'); 2456 g.addColorStop(1, 'color(srgb 0 1 0)'); 2457 g.colorInterpolationMethod = '{{ variant_names[1] }}'; 2458 g.hueInterpolationMethod = '{{ variant_names[0] }}'; 2459 ctx.fillStyle = g; 2460 ctx.fillRect(0, 0, 100, 25); 2461 2462 var g2 = ctx.createLinearGradient(0, 0, 100, 0); 2463 g2.addColorStop(0, 'color(srgb 1 0 0)'); 2464 g2.addColorStop(1, 'color(srgb 0 0 1)'); 2465 g2.colorInterpolationMethod = '{{ variant_names[1] }}'; 2466 g2.hueInterpolationMethod = '{{ variant_names[0] }}'; 2467 ctx.fillStyle = g2; 2468 ctx.fillRect(0, 25, 100, 25); 2469 html_reference: | 2470 <style> 2471 .swatch { 2472 width: 100%; 2473 height: 50%; 2474 } 2475 </style> 2476 <div class="swatch" style="background: 2477 linear-gradient(to right in {{ variant_names[1] }} {{ variant_names[0] }} 2478 hue, color(srgb 1 0 0), color(srgb 0 1 0)); 2479 "></div> 2480 <div class="swatch" style="background: 2481 linear-gradient(to right in {{ variant_names[1] }} {{ variant_names[0] }} 2482 hue, color(srgb 1 0 0), color(srgb 0 0 1)); 2483 "></div> 2484 variants_layout: [single_file, single_file] 2485 variants: 2486 # Hue interpolation methods 2487 - shorter: 2488 longer: 2489 increasing: 2490 decreasing: 2491 # Polar color interpolation spaces 2492 - hsl: 2493 hwb: 2494 lch: 2495 oklch: