Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / fast / canvas / canvas-blending-helpers.js
blobff34874b1d39ec80384ce9bd15b9048772431a4c
1 var blendModes = ["source-over", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn",
2 "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"];
4 // Helper functions for separate blend mode
6 var separateBlendmodes = ["normal", "multiply", "screen", "overlay",
7 "darken", "lighten", "colorDodge","colorBurn",
8 "hardLight", "softLight", "difference", "exclusion"];
10 var separateBlendFunctions = {
11 normal: function(b, s) {
12 return s;
14 multiply: function(b, s) {
15 return b * s;
17 screen: function(b, s) {
18 return b + s - b * s;
20 overlay: function(b, s) {
21 return separateBlendFunctions.hardLight(b, s);
23 darken: function(b, s) {
24 return Math.min(b, s);
26 lighten: function(b, s) {
27 return Math.max(b, s);
29 colorDodge: function(b, s) {
30 if(b == 1)
31 return 1;
32 return Math.min(1, s / (1 - b));
34 colorBurn: function(b, s) {
35 if(s == 0)
36 return 0;
37 return 1 - Math.min(1, (1 - b) / s);
39 hardLight: function(b, s) {
40 if(s <= 0.5)
41 return separateBlendFunctions.multiply(s, 2 * b);
43 return separateBlendFunctions.screen(s, 2 * b - 1);
45 softLight: function(b, s) {
46 var c = 0;
47 if(b <= 0.25)
48 c = ((16 * b - 12) * b + 4) * b;
49 else
50 c = Math.sqrt(b);
52 if(s <= 0.5)
53 return b - (1 - 2 * s) * b * (1 - b);
55 return b + (2 * s - 1) * (c - b);
57 difference: function(b, s) {
58 return Math.abs(b - s);
60 exclusion: function(b, s) {
61 return s + b - 2 * b * s;
65 function applyBlendMode(b, s, blendFunc) {
66 var resultedColor = [0, 0, 0, 255];
67 for (var i = 0; i < 3; ++i)
68 resultedColor[i] = 255 * (s[3] * (1 - b[3]) * s[i] + b[3] * s[3] * blendFunc(b[i], s[i]) + (1 - s[3]) * b[3] * b[i]);
69 return resultedColor;
73 // Helper functions for nonseparate blend modes
75 var nonSeparateBlendModes = ["hue", "saturation", "color", "luminosity"];
77 function luminosity(c) {
78 return 0.3 * c[0] + 0.59 * c[1] + 0.11 * c[2];
81 function clipColor(c) {
82 var l = luminosity(c);
83 var n = Math.min(c[0], c[1], c[2]);
84 var x = Math.max(c[0], c[1], c[2]);
86 if (n < 0) {
87 c[0] = l + (((c[0] - l) * l) / (l - n));
88 c[1] = l + (((c[1] - l) * l) / (l - n));
89 c[2] = l + (((c[1] - l) * l) / (l - n));
92 if (x > 1) {
93 c[0] = l + (((c[0] - l) * (1 - l)) / (x - l));
94 c[1] = l + (((c[1] - l) * (1 - l)) / (x - l));
95 c[2] = l + (((c[2] - l) * (1 - l)) / (x - l));
98 return c;
101 function setLuminosity(c, l) {
102 var d = l - luminosity(c);
103 c[0] += d;
104 c[1] += d;
105 c[2] += d;
106 return clipColor(c);
109 function saturation(c) {
110 return Math.max(c[0], c[1], c[2]) - Math.min(c[0], c[1], c[2]);
113 function setSaturation(c, s) {
114 var max = Math.max(c[0], c[1], c[2]);
115 var min = Math.min(c[0], c[1], c[2]);
116 var index_max = -1;
117 var index_min = -1;
119 for (var i = 0; i < 3; ++i) {
120 if (c[i] == min && index_min == -1) {
121 index_min = i;
122 continue;
124 if (c[i] == max && index_max == -1)
125 index_max = i;
127 var index_mid = 3 - index_max - index_min;
128 var mid = c[index_mid];
131 if (max > min) {
132 mid = (((mid - min) * s) / (max - min));
133 max = s;
134 } else {
135 mid = 0;
136 max = 0;
138 min = 0;
140 var newColor = [0, 0, 0];
142 newColor[index_min] = min;
143 newColor[index_mid] = mid;
144 newColor[index_max] = max;
146 return newColor;
149 var nonSeparateBlendFunctions = {
150 hue: function(b, s) {
151 var bCopy = [b[0], b[1], b[2]];
152 var sCopy = [s[0], s[1], s[2]];
153 return setLuminosity(setSaturation(sCopy, saturation(bCopy)), luminosity(bCopy));
155 saturation: function(b, s) {
156 var bCopy = [b[0], b[1], b[2]];
157 var sCopy = [s[0], s[1], s[2]];
158 return setLuminosity(setSaturation(bCopy, saturation(sCopy)), luminosity(bCopy));
160 color: function(b, s) {
161 var bCopy = [b[0], b[1], b[2]];
162 var sCopy = [s[0], s[1], s[2]];
163 return setLuminosity(sCopy, luminosity(bCopy));
165 luminosity: function(b, s) {
166 var bCopy = [b[0], b[1], b[2]];
167 var sCopy = [s[0], s[1], s[2]];
168 return setLuminosity(bCopy, luminosity(sCopy));
172 // Helper functions for drawing in canvas tests
174 function drawColorInContext(color, context) {
175 context.fillStyle = color;
176 context.fillRect(0, 0, 10, 10);
179 function drawBackdropColorInContext(context) {
180 drawColorInContext("rgba(129, 255, 129, 1)", context);
183 function drawSourceColorInContext(context) {
184 drawColorInContext("rgba(255, 129, 129, 1)", context);
187 function fillPathWithColorInContext(color, context) {
188 context.fillStyle = color;
189 context.lineTo(0, 10);
190 context.lineTo(10, 10);
191 context.lineTo(10, 0);
192 context.lineTo(0, 0);
193 context.fill();
196 function fillPathWithBackdropInContext(context) {
197 fillPathWithColorInContext("rgba(129, 255, 129, 1)", context);
200 function fillPathWithSourceInContext(context) {
201 fillPathWithColorInContext("rgba(255, 129, 129, 1)", context);
204 function applyTransformsToContext(context) {
205 context.translate(1, 1);
206 context.rotate(Math.PI / 2);
207 context.scale(2, 2);
210 function drawBackdropColorWithShadowInContext(context) {
211 context.save();
212 context.shadowOffsetX = 2;
213 context.shadowOffsetY = 2;
214 context.shadowColor = 'rgba(192, 192, 192, 1)';
215 drawBackdropColorInContext(context);
216 context.restore();
219 function drawSourceColorRectOverShadow(context) {
220 context.fillStyle = "rgba(255, 129, 129, 1)";
221 context.fillRect(0, 0, 12, 12);
224 function drawColorImageInContext(color, context, callback) {
225 var cvs = document.createElement("canvas");
226 var ctx = cvs.getContext("2d");
227 drawColorInContext(color, ctx);
228 var imageURL = cvs.toDataURL();
230 var backdropImage = new Image();
231 backdropImage.onload = function() {
232 context.drawImage(this, 0, 0);
233 callback();
235 backdropImage.src = imageURL;
238 function drawBackdropColorImageInContext(context, callback) {
239 drawColorImageInContext("rgba(129, 255, 129, 1)", context, callback);
242 function drawSourceColorImageInContext(context, callback) {
243 drawColorImageInContext("rgba(255, 129, 129, 1)", context, callback);
246 function drawColorPatternInContext(color, context, callback) {
247 var cvs = document.createElement("canvas");
248 var ctx = cvs.getContext("2d");
249 drawColorInContext(color, ctx);
250 var imageURL = cvs.toDataURL();
252 var backdropImage = new Image();
253 backdropImage.onload = function() {
254 var pattern = context.createPattern(backdropImage, 'repeat');
255 context.rect(0, 0, 10, 10);
256 context.fillStyle = pattern;
257 context.fill();
258 callback();
260 backdropImage.src = imageURL;
263 function drawBackdropColorPatternInContext(context, callback) {
264 drawColorPatternInContext("rgba(129, 255, 129, 1)", context, callback);
267 function drawSourceColorPatternInContext(context, callback) {
268 drawColorPatternInContext("rgba(255, 129, 129, 1)", context, callback);
271 function drawGradientInContext(color1, context) {
272 var grad = context.createLinearGradient(0, 0, 10, 10);
273 grad.addColorStop(0, color1);
274 grad.addColorStop(1, color1);
275 context.fillStyle = grad;
276 context.fillRect(0, 0, 10, 10);
279 function drawBackdropColorGradientInContext(context) {
280 drawGradientInContext("rgba(129, 255, 129, 1)", context);
283 function drawSourceColorGradientInContext(context) {
284 drawGradientInContext("rgba(255, 129, 129, 1)", context);
287 function blendColors(backdrop, source, blendModeIndex) {
288 if (blendModeIndex < separateBlendmodes.length)
289 return separateBlendColors(backdrop, source, blendModeIndex);
290 return nonSeparateBlendColors(backdrop, source, blendModeIndex - separateBlendmodes.length);
293 function separateBlendColors(backdrop, source, blendModeIndex) {
294 return applyBlendMode(backdrop, source, separateBlendFunctions[separateBlendmodes[blendModeIndex]]);
297 function nonSeparateBlendColors(backdrop, source, blendModeIndex) {
298 var expectedColor = nonSeparateBlendFunctions[nonSeparateBlendModes[blendModeIndex]](backdrop, source);
299 for (var i = 0; i < 3; ++i)
300 expectedColor[i] = source[3] * (1 - backdrop[3]) * source[i] + source[3] * backdrop[3] * expectedColor[i] + (1 - source[3]) * backdrop[3] * backdrop[i];
301 return [Math.round(255 * expectedColor[0]), Math.round(255 * expectedColor[1]), Math.round(255 * expectedColor[2]), 255];