<!doctype html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body>
<script>
description("Series of tests to ensure correct results on applying different blend modes.");
if (window.internals)
  internals.settings.setCanvasUsesAcceleratedDrawing(false);

var tmpimg = document.createElement('canvas');
tmpimg.width = 200;
tmpimg.height = 200;
ctx = tmpimg.getContext('2d');

// Create the image for blending test with images.
var img = document.createElement('canvas');
img.width = 200;
img.height = 200;
var imgCtx = img.getContext('2d');
imgCtx.fillStyle = "red";
imgCtx.fillRect(0,0,100,100);
imgCtx.fillStyle = "yellow";
imgCtx.fillRect(100,0,100,100);
imgCtx.fillStyle = "green";
imgCtx.fillRect(100,100,100,100);
imgCtx.fillStyle = "blue";
imgCtx.fillRect(0,100,100,100);


// Create expected results.
var blendModes =
// [blendMode, expectations solid on solid, expectations solid on alpha, expectations alpha on solid, expectations alpha on alpha]
[
  ['source-over',
     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
     [[171, 0, 84, 191],[171, 171, 84, 191],[0, 85, 84, 191],[0, 0, 255, 191]]
  ],
  ['normal',
     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
     [[171, 0, 84, 191],[171, 171, 84, 191],[0, 85, 84, 191],[0, 0, 255, 191]]
  ],
  ['multiply',
     [[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 255, 255]],
     [[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
     [[128, 0, 0, 255],[128, 128, 0, 255],[0, 64, 0, 255],[0, 0, 255, 255]],
     [[85, 0, 84, 191],[85, 85, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
  ],
  ['screen',
     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 255, 255]],
     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 255, 255]],
     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 255, 255]],
     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 255, 191]]
  ],
  ['overlay',
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
     [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
  ],
  ['darken',
     [[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 255, 255]],
     [[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
     [[128, 0, 0, 255],[128, 128, 0, 255],[0, 64, 0, 255],[0, 0, 255, 255]],
     [[85, 0, 84, 191],[85, 85, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
  ],
  ['lighten',
     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 255, 255]],
     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 255, 255]],
     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 255, 255]],
     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 255, 191]]
  ],
  ['color-dodge',
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
     [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
  ],
  ['color-burn',
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
     [[85, 0, 170, 191],[85, 85, 170, 191],[0, 0, 170, 191],[0, 0, 255, 191]]

  ],
  ['hard-light',
     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 1, 0, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 65, 0, 255],[0, 0, 255, 255]],
     [[171, 0, 84, 191],[171, 171, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
  ],
  ['soft-light',
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
     [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
  ],
  ['difference',
     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 0, 255]],
     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 127, 255]],
     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 128, 255]],
     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 171, 191]]
  ],
  ['exclusion',
     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 0, 255]],
     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 127, 255]],
     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 128, 255]],
     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 171, 191]]
  ],
  ['hue',
     [[93, 0, 0, 255],[31, 31, 0, 255],[0, 46, 0, 255],[0, 0, 255, 255]],
     [[49, 0, 127, 255],[16, 16, 127, 255],[0, 25, 127, 255],[0, 0, 255, 255]],
     [[175, 0, 0, 255],[144, 144, 0, 255],[0, 88, 0, 255],[0, 0, 255, 255]],
     [[116, 0, 84, 191],[96, 96, 84, 191],[0, 58, 84, 191],[0, 0, 255, 191]]
  ],
  ['saturation',
     [[0, 0, 255, 255],[0, 0, 255, 255],[14, 14, 142, 255],[0, 0, 255, 255]],
     [[0, 0, 255, 255],[0, 0, 255, 255],[7, 7, 198, 255],[0, 0, 255, 255]],
     [[128, 0, 127, 255],[128, 128, 127, 255],[7, 71, 70, 255],[0, 0, 255, 255]],
     [[85, 0, 167, 191],[85, 85, 167, 191],[0, 48, 130, 191],[0, 0, 255, 191]]
  ],
  ['color',
     [[93, 0, 0, 255],[31, 31, 0, 255],[0, 47, 0, 255],[0, 0, 255, 255]],
     [[49, 0, 127, 255],[16, 16, 127, 255],[0, 24, 127, 255],[0, 0, 255, 255]],
     [[175, 0, 0, 255],[144, 144, 0, 255],[0, 88, 0, 255],[0, 0, 255, 255]],
     [[116, 0, 84, 191],[96, 96, 84, 191],[0, 58, 84, 191],[0, 0, 255, 191]]
  ],
  ['luminosity',
     [[55, 55, 255, 255],[224, 224, 255, 255],[54, 54, 255, 255],[0, 0, 255, 255]],
     [[28, 28, 255, 255],[112, 112, 255, 255],[27, 27, 255, 255],[0, 0, 255, 255]],
     [[155, 27, 127, 255],[239, 239, 127, 255],[26, 90, 127, 255],[0, 0, 255, 255]],
     [[104, 19, 167, 191],[158, 158, 167, 191],[16, 58, 167, 191],[0, 0, 255, 191]]
  ]];

// [Scenario, alpha on background, alpha on foreground]
var testScenario = [
  ['solid on solid', 1, 1],
  ['solid on alpha', 1, 0.5],
  ['alpha on solid', 0.5, 1],
  ['alpha on alpha', 0.5, 0.5]
];

testPoints = [{x: 50, y: 50}, {x: 150, y: 50}, {x: 150, y: 150}, {x: 50, y: 150}];

function pixelDataAtPoint(i, blend)
{
  return ctx.getImageData(testPoints[i].x, testPoints[i].y , 1, 1).data;
}

function checkBlendModeResult(blendMode, testScenario, expectedColors, sigma) {
  debug(testScenario);
  for (var i = 0; i < testPoints.length; i++) {
    var resultColor = "pixelDataAtPoint(" + i + ")";
    shouldBeCloseTo(resultColor +"[0]", expectedColors[i][0], sigma);
    shouldBeCloseTo(resultColor +"[1]", expectedColors[i][1], sigma);
    shouldBeCloseTo(resultColor +"[2]", expectedColors[i][2], sigma);
    shouldBeCloseTo(resultColor +"[3]", expectedColors[i][3], sigma);
    }
}

// Execute test.
function prepareTestScenario(sigma) {
  // Check each blend mode individually.
  for (var i = 0; i < blendModes.length; i++) {
    debug('Testing blend mode "' + blendModes[i][0] + '"');
    for (var j = 0; j < testScenario.length; j++) {
      ctx.globalCompositeOperation = 'clear';
      ctx.fillRect(0,0,200,200);
      ctx.globalCompositeOperation = 'source-over';
      ctx.save();
      
      // Draw backdrop.
      ctx.fillStyle = 'rgba(0, 0, 255, ' + testScenario[j][1] + ')';
      ctx.fillRect(0,0,200,200);
      
      // Apply blend mode.
      ctx.globalCompositeOperation = blendModes[i][0];
      ctx.globalAlpha = testScenario[j][2];
      ctx.fillStyle = "red";
      ctx.fillRect(0,0,100,100);
      ctx.fillStyle = "yellow";
      ctx.fillRect(100,0,100,100);
      ctx.fillStyle = "green";
      ctx.fillRect(100,100,100,100);
      ctx.fillStyle = "blue";
      ctx.fillRect(0,100,100,100);
      ctx.restore();
      
      checkBlendModeResult(blendModes[i][0], testScenario[j][0], blendModes[i][j+1], sigma);
      ctx.restore();                                  
      }
    debug('');
  }
}

// Run test and allow variation of results.
prepareTestScenario(5);
</script>
<script src="../../resources/js-test-post.js"></script>
</body>