OLD | NEW |
1 <html> | 1 <html> |
2 <head> | 2 <head> |
3 <title>A canvas globalCompositeOperation test with alpha blending</title> | 3 <title>A canvas globalCompositeOperation test with alpha compositing on text
</title> |
4 <!-- This test was inspired by http://canvex.lazyilluminati.com/misc/composi
tex.html --> | 4 <!-- This test was inspired by http://canvex.lazyilluminati.com/misc/composi
tex.html --> |
5 <script type="application/x-javascript"> | 5 <script type="application/x-javascript"> |
6 if (window.testRunner) { | 6 if (window.testRunner) { |
7 testRunner.dumpAsText(); | 7 testRunner.dumpAsText(); |
8 testRunner.waitUntilDone(); | 8 testRunner.waitUntilDone(); |
9 } | 9 } |
10 | 10 |
11 var compositeTypes = [ | 11 var compositeTypes = [ |
12 'source-over','source-in','source-out','source-atop', | 12 'source-over','source-in','source-out','source-atop', |
13 'destination-over','destination-in','destination-out','destination-ato
p', | 13 'destination-over','destination-in','destination-out','destination-ato
p', |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 trCanvasElement.appendChild(tdElement); | 306 trCanvasElement.appendChild(tdElement); |
307 | 307 |
308 // Create div element for pass/fail messages. | 308 // Create div element for pass/fail messages. |
309 var messageElement = document.createElement("div"); | 309 var messageElement = document.createElement("div"); |
310 tdElement = document.createElement("td"); | 310 tdElement = document.createElement("td"); |
311 tdElement.setAttribute("colspan", "2"); | 311 tdElement.setAttribute("colspan", "2"); |
312 tdElement.appendChild(messageElement); | 312 tdElement.appendChild(messageElement); |
313 trMessageElement.appendChild(tdElement); | 313 trMessageElement.appendChild(tdElement); |
314 | 314 |
315 var ctx = expectedCanvasElement.getContext("2d"); | 315 var ctx = expectedCanvasElement.getContext("2d"); |
316 ctx.lineWidth = 10; | 316 ctx.lineWidth = 3; |
317 // Draw expected image. | 317 // Draw expected image. |
318 ctx.globalCompositeOperation = "copy"; | 318 ctx.globalCompositeOperation = "copy"; |
319 ctx.fillStyle = getRGBAString(expectedColor.destination); | 319 ctx.fillStyle = getRGBAString(expectedColor.destination); |
320 ctx.strokeStyle = getRGBAString(expectedColor.destination); | 320 ctx.strokeStyle = getRGBAString(expectedColor.destination); |
321 drawPolicy.drawDestination(ctx); | 321 drawPolicy.drawDestination(ctx); |
322 ctx.fillStyle = getRGBAString(expectedColor.source); | 322 ctx.fillStyle = getRGBAString(expectedColor.source); |
323 ctx.strokeStyle = getRGBAString(expectedColor.source); | 323 ctx.strokeStyle = getRGBAString(expectedColor.source); |
324 drawPolicy.drawSource(ctx); | 324 drawPolicy.drawSource(ctx); |
325 ctx.fillStyle = getRGBAString(expectedColor.composition); | 325 ctx.fillStyle = getRGBAString(expectedColor.composition); |
326 ctx.strokeStyle = getRGBAString(expectedColor.composition); | 326 ctx.strokeStyle = getRGBAString(expectedColor.composition); |
327 drawPolicy.drawComposition(ctx); | 327 drawPolicy.drawComposition(ctx); |
328 | 328 |
329 ctx = actualCanvasElement.getContext("2d"); | 329 ctx = actualCanvasElement.getContext("2d"); |
330 ctx.lineWidth = 10; | 330 ctx.lineWidth = 3; |
331 | 331 |
332 // Draw destination rectangle. | 332 // Draw destination rectangle. |
333 ctx.globalCompositeOperation = "copy"; | 333 ctx.globalCompositeOperation = "copy"; |
334 ctx.fillStyle = getRGBAString(inputColor.destination); | 334 ctx.fillStyle = getRGBAString(inputColor.destination); |
335 ctx.strokeStyle = getRGBAString(inputColor.destination); | 335 ctx.strokeStyle = getRGBAString(inputColor.destination); |
336 drawPolicy.drawDestination(ctx); | 336 drawPolicy.drawDestination(ctx); |
337 | 337 |
338 // Draw source rectangle. | 338 // Draw source rectangle. |
339 ctx.globalCompositeOperation = type; | 339 ctx.globalCompositeOperation = type; |
340 ctx.fillStyle = getRGBAString(inputColor.source); | 340 ctx.fillStyle = getRGBAString(inputColor.source); |
341 ctx.strokeStyle = getRGBAString(inputColor.source); | 341 ctx.strokeStyle = getRGBAString(inputColor.source); |
342 drawPolicy.drawSource(ctx); | 342 drawPolicy.drawSource(ctx); |
343 | 343 |
344 // Let's check if the results are expected or not. | 344 // Let's check if the results are expected or not. |
345 var errorSuffix = ", composite type: " + type + ", source: " +
inputColor.source + ", destination: " + inputColor.destination + "<br>"; | 345 var errorSuffix = ", composite type: " + type + ", source: " +
inputColor.source + ", destination: " + inputColor.destination + "<br>"; |
346 | 346 |
347 var results = ""; | 347 var results = ""; |
348 // Note that (0, 0) may be affected by anti-alias. | 348 // Note that (2, 3) may be affected by anti-alias. |
349 var img = ctx.getImageData(1, 1, 1, 1).data; | 349 var img = ctx.getImageData(3, 4, 1, 1).data; |
350 var actualColor = [img[0], img[1], img[2], img[3]]; | 350 var actualColor = [img[0], img[1], img[2], img[3]]; |
351 if (isDifferentColor(actualColor, expectedColor.source)) { | 351 if (isDifferentColor(actualColor, expectedColor.source)) { |
352 results += "Unexpected source! expected: " + expectedColor
.source + " actual: " + actualColor + errorSuffix; | 352 results += "Unexpected source! expected: " + expectedColor
.source + " actual: " + actualColor + errorSuffix; |
353 } | 353 } |
354 // Note that (24, 24) may be affected by anti-alias. | 354 // Note that (24, 24) may be affected by anti-alias. |
355 img = ctx.getImageData(23, 23, 1, 1).data; | 355 img = ctx.getImageData(23, 23, 1, 1).data; |
356 actualColor = [img[0], img[1], img[2], img[3]]; | 356 actualColor = [img[0], img[1], img[2], img[3]]; |
357 if (isDifferentColor(actualColor, expectedColor.destination))
{ | 357 if (isDifferentColor(actualColor, expectedColor.destination))
{ |
358 results += "Unexpected destination! expected: " + expected
Color.destination + " actual: " + actualColor + errorSuffix; | 358 results += "Unexpected destination! expected: " + expected
Color.destination + " actual: " + actualColor + errorSuffix; |
359 } | 359 } |
360 img = ctx.getImageData(12, 12, 1, 1).data; | 360 img = ctx.getImageData(11, 12, 1, 1).data; |
361 actualColor = [img[0], img[1], img[2], img[3]]; | 361 actualColor = [img[0], img[1], img[2], img[3]]; |
362 if (isDifferentColor(actualColor, expectedColor.composition))
{ | 362 if (isDifferentColor(actualColor, expectedColor.composition))
{ |
363 results += "Unexpected composition! expected: " + expected
Color.composition + " actual: " + actualColor + errorSuffix; | 363 results += "Unexpected composition! expected: " + expected
Color.composition + " actual: " + actualColor + errorSuffix; |
364 } | 364 } |
365 | 365 |
366 if (results == "") { | 366 if (results == "") { |
367 messageElement.style.backgroundColor = "green"; | 367 messageElement.style.backgroundColor = "green"; |
368 messageElement.innerHTML = results = "PASS"; | 368 messageElement.innerHTML = results = "PASS"; |
369 } else { | 369 } else { |
370 messageElement.style.backgroundColor = "red"; | 370 messageElement.style.backgroundColor = "red"; |
371 messageElement.innerHTML = results; | 371 messageElement.innerHTML = results; |
372 } | 372 } |
373 | 373 |
374 // Dump colors into text area for debugging purpose. | 374 // Dump colors into text area for debugging purpose. |
375 var debugText = document.getElementById("debug"); | 375 var debugText = document.getElementById("debug"); |
376 img = ctx.getImageData(0, 0, 1, 1).data; | 376 img = ctx.getImageData(0, 0, 1, 1).data; |
377 debugText.value += img[0] + "," + img[1] + "," + img[2] + ","
+ img[3] + "\n"; | 377 debugText.value += img[0] + "," + img[1] + "," + img[2] + ","
+ img[3] + "\n"; |
378 img = ctx.getImageData(12, 12, 1, 1).data; | 378 img = ctx.getImageData(12, 12, 1, 1).data; |
379 debugText.value += img[0] + "," + img[1] + "," + img[2] + ","
+ img[3] + "\n"; | 379 debugText.value += img[0] + "," + img[1] + "," + img[2] + ","
+ img[3] + "\n"; |
380 img = ctx.getImageData(24, 24, 1, 1).data; | 380 img = ctx.getImageData(24, 24, 1, 1).data; |
381 debugText.value += img[0] + "," + img[1] + "," + img[2] + ","
+ img[3] + "\n"; | 381 debugText.value += img[0] + "," + img[1] + "," + img[2] + ","
+ img[3] + "\n"; |
382 } | 382 } |
383 } | 383 } |
384 } | 384 } |
385 | 385 |
386 var useStrokeRect = { | 386 var useFillText = { |
387 drawSource: function(ctx) { | 387 drawSource: function(ctx) { |
388 ctx.strokeRect(5, 5, 10, 10); | 388 ctx.font="bold 20px arial"; |
| 389 ctx.fillText("B", 0, 18); |
389 }, | 390 }, |
390 | 391 |
391 drawDestination: function(ctx) { | 392 drawDestination: function(ctx) { |
392 ctx.fillRect(5, 5, 20, 20); | 393 ctx.fillRect(5, 5, 20, 20); |
393 }, | 394 }, |
394 | 395 |
395 drawComposition: function(ctx) { | 396 drawComposition: function(ctx) { |
396 ctx.fillRect(5, 5, 15, 15); | 397 ctx.fillRect(5, 5, 15, 15); |
397 }, | 398 }, |
398 | 399 |
399 name: "stroke rect" | 400 name: "fill text" |
400 }; | 401 }; |
401 | 402 |
402 var usePathAndStroke = { | 403 var useStrokeText = { |
403 drawSource: function(ctx) { | 404 drawSource: function(ctx) { |
404 ctx.beginPath(); | 405 ctx.font="bold 20px arial"; |
405 ctx.moveTo(5, 5); | 406 ctx.strokeText("B", 0, 18); |
406 ctx.lineTo(15, 5); | |
407 ctx.lineTo(15, 15); | |
408 ctx.lineTo(5, 15); | |
409 ctx.closePath(); | |
410 ctx.stroke(); | |
411 }, | 407 }, |
412 | 408 |
413 drawDestination: function(ctx) { | 409 drawDestination: function(ctx) { |
414 ctx.fillRect(5, 5, 20, 20); | 410 ctx.fillRect(5, 5, 20, 20); |
415 }, | 411 }, |
416 | 412 |
417 drawComposition: function(ctx) { | 413 drawComposition: function(ctx) { |
418 ctx.fillRect(5, 5, 15, 15); | 414 ctx.fillRect(5, 5, 15, 15); |
419 }, | 415 }, |
420 | 416 |
421 name: "path and stroke" | 417 name: "stroke text" |
422 }; | 418 }; |
423 | 419 |
424 function draw() | 420 function draw() |
425 { | 421 { |
426 drawTable(useStrokeRect); | 422 drawTable(useFillText); |
427 drawTable(usePathAndStroke); | 423 drawTable(useStrokeText); |
428 if (window.testRunner) | 424 if (window.testRunner) |
429 testRunner.notifyDone(); | 425 testRunner.notifyDone(); |
430 } | 426 } |
431 </script> | 427 </script> |
432 <style type="text/css"> | 428 <style type="text/css"> |
433 body { margin: 20px; font-family: arial,verdana,helvetica; background: #ff
f;} | 429 body { margin: 20px; font-family: arial,verdana,helvetica; background: #ff
f;} |
434 h1 { font-size: 140%; font-weight:normal; color: #036; border-bottom: 1px
solid #ccc; } | 430 h1 { font-size: 140%; font-weight:normal; color: #036; border-bottom: 1px
solid #ccc; } |
435 canvas { border: 2px solid #000; margin-bottom: 5px; } | 431 canvas { border: 2px solid #000; margin-bottom: 5px; } |
436 table { background: #00f; } | 432 table { background: #00f; } |
437 th { font-size: 70%; padding: 0; } | 433 th { font-size: 70%; padding: 0; } |
438 td { font-size: 70%; padding: 0; } | 434 td { font-size: 70%; padding: 0; } |
439 pre { float:left; display:block; background: rgb(238,238,238); border: 1px
dashed #666; padding: 15px 20px; margin: 0 0 10px 0; } | 435 pre { float:left; display:block; background: rgb(238,238,238); border: 1px
dashed #666; padding: 15px 20px; margin: 0 0 10px 0; } |
440 </style> | 436 </style> |
441 </head> | 437 </head> |
442 <body onload="draw();"> | 438 <body onload="draw();"> |
443 <p>This test exercises a bunch of alpha composition checks with stroking. Th
e top-left rectangles are the source images and bottom-right rectangles are the
destination images.</p> | 439 <p>This test exercises a bunch of alpha composition operations on text. The
top-left rectangles are the source images and bottom-right rectangles are the de
stination images.</p> |
444 <div id="results"> | 440 <div id="results"> |
445 </div> | 441 </div> |
446 <textarea id="debug"></textarea> | 442 <textarea id="debug"></textarea> |
447 </body> | 443 </body> |
448 </html> | 444 </html> |
OLD | NEW |