Chromium Code Reviews| Index: ui/accessibility/extensions/colorenhancer/src/cvd.js |
| diff --git a/ui/accessibility/extensions/colorenhancer/src/cvd.js b/ui/accessibility/extensions/colorenhancer/src/cvd.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8ba5eb213799e70d3b87b3620fa2a5b8b0114ff5 |
| --- /dev/null |
| +++ b/ui/accessibility/extensions/colorenhancer/src/cvd.js |
| @@ -0,0 +1,339 @@ |
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| + |
| +// ======= Global state ======= |
| + |
| +var storedDelta = 0; |
| +var storedSeverity = 0; |
| +var storedType = "type_a"; |
| +var storedSimulate = false; |
| +var curFilter = 0; |
| + |
| + |
| +// ======= 3x3 matrix ops ======= |
| + |
| +var identityMatrix3x3 = [ |
| + [1, 0, 0], |
| + [0, 1, 0], |
| + [0, 0, 1] |
| +]; |
| + |
| + |
|
kevers
2015/03/09 13:56:59
Should have jsdoc for all functions.
Peter Wen
2015/03/09 21:35:56
Added some and others left as TODOs.
|
| +function add3x3(m1, m2) { |
| + var result = []; |
| + for (var i = 0; i < 3; i++) { |
| + result[i] = []; |
| + for (var j = 0; j < 3; j++) { |
| + result[i].push(m1[i][j] + m2[i][j]); |
| + } |
| + } |
| + return result; |
| +} |
| + |
| + |
| +function sub3x3(m1, m2) { |
| + var result = []; |
| + for (var i = 0; i < 3; i++) { |
| + result[i] = []; |
| + for (var j = 0; j < 3; j++) { |
| + result[i].push(m1[i][j] - m2[i][j]); |
| + } |
| + } |
| + return result; |
| +} |
| + |
| + |
| +function mul3x3(m1, m2) { |
| + var result = []; |
| + for (var i = 0; i < 3; i++) { |
| + result[i] = []; |
| + for (var j = 0; j < 3; j++) { |
| + var sum = 0; |
| + for (var k = 0; k < 3; k++) { |
| + sum += m1[i][k] * m2[k][j]; |
| + } |
| + result[i].push(sum); |
| + } |
| + } |
| + return result; |
| +} |
| + |
| + |
| +function mul3x3Scalar(m, k) { |
| + var result = []; |
| + for (var i = 0; i < 3; i++) { |
| + result[i] = []; |
| + for (var j = 0; j < 3; j++) { |
| + result[i].push(k * m[i][j]); |
| + } |
| + } |
| + return result; |
| +} |
| + |
| + |
| +// ======= CVD parameters ======= |
| + |
| +var cvdSimulationParams = { |
|
dmazzoni
2015/03/09 15:40:40
Could you provide any docs on how these were compu
kevers
2015/03/09 15:56:55
Peter, these values were generated by doing a poly
mustaq
2015/03/09 16:35:18
Since we had decided earlier to use severity=1 w/o
kevers
2015/03/09 18:41:48
Thought we decided that we (eventually) wouldn't s
Peter Wen
2015/03/09 21:35:57
Done.
|
| + type_a /*protanomaly*/: [ |
|
kevers
2015/03/09 13:56:59
jsdoc @emum {string}
Also style for enumeration sh
Peter Wen
2015/03/09 21:35:57
Done.
|
| + [0.4720, -1.2946, 0.9857], |
| + [-0.6128, 1.6326, 0.0187], |
| + [0.1407, -0.3380, -0.0044], |
| + [-0.1420, 0.2488, 0.0044], |
| + [0.1872, -0.3908, 0.9942], |
| + [-0.0451, 0.1420, 0.0013], |
| + [0.0222, -0.0253, -0.0004], |
| + [-0.0290, -0.0201, 0.0006], |
| + [0.0068, 0.0454, 0.9990] |
| + ], |
| + type_b /*deuteranomaly*/: [ |
| + [0.5442, -1.1454, 0.9818], |
| + [-0.7091, 1.5287, 0.0238], |
| + [0.1650, -0.3833, -0.0055], |
| + [-0.1664, 0.4368, 0.0056], |
| + [0.2178, -0.5327, 0.9927], |
| + [-0.0514, 0.0958, 0.0017], |
| + [0.0180, -0.0288, -0.0006], |
| + [-0.0232, -0.0649, 0.0007], |
| + [0.0052, 0.0360, 0.9998] |
| + ], |
| + type_c /*tritanomaly*/: [ |
| + [0.4275, -0.0181, 0.9307], |
| + [-0.2454, 0.0013, 0.0827], |
| + [-0.1821, 0.0168, -0.0134], |
| + [-0.1280, 0.0047, 0.0202], |
| + [0.0233, -0.0398, 0.9728], |
| + [0.1048, 0.0352, 0.0070], |
| + [-0.0156, 0.0061, 0.0071], |
| + [0.3841, 0.2947, 0.0151], |
| + [-0.3685, -0.3008, 0.9778] |
| + ] |
| +}; |
| + |
| + |
| +var cvdCorrectionMatrices = { |
|
kevers
2015/03/09 13:56:59
Dead code. Please remove.
Peter Wen
2015/03/09 21:35:57
Done.
|
| + type_a /*protanomaly*/: [ |
| + [0.0, 0.0, 0.0], |
| + [0.7, 1.0, 0.0], |
| + [0.7, 0.0, 1.0] |
| + ], |
| + type_b /*deuteranomaly*/: [ |
| + [1.0, 0.7, 0.0], |
| + [0.0, 0.0, 0.0], |
| + [0.0, 0.7, 1.0] |
| + ], |
| + type_c /*tritanomaly*/: [ |
| + [1.0, 0.0, 0.7], |
| + [0.0, 1.0, 0.7], |
| + [0.0, 0.0, 0.0] |
| + ] |
| +}; |
| + |
| + |
| +// TODO(mustaq): A common matrix for all types? E.g. Kevin's experiment |
| +// suggested: Mx[1][0] = 0.7+0.3*delta and Mx[2][0] = 0.7-0.3*delta |
| +var cvdCorrectionParams = { |
|
kevers
2015/03/09 13:56:59
See comments above on enumerations.
Peter Wen
2015/03/09 21:35:56
Done.
|
| + type_a /*protanomaly*/: { |
| + addendum: [ |
| + [-1.0, 0.0, 0.0], |
| + [0.5, 1.0, 0.0], |
| + [1.5, 0.0, 1.0] |
| + ], |
| + delta_factor: [ |
| + [0.0, 0.0, 0.0], |
| + [1.0, 0.0, 0.0], |
| + [-1.0, 0.0, 0.0] |
| + ] |
| + }, |
| + type_b /*deuteranomaly*/: { |
| + addendum: [ |
| + [1.0, 0.5, 0.0], |
| + [0.5, -1.0, 0.0], |
| + [1.5, 1.5, 1.0] |
| + ], |
| + delta_factor: [ |
| + [0.0, 1.0, 0.0], |
| + [0.0, 0.0, 0.0], |
| + [0.0, -1.0, 0.0] |
| + ] |
| + }, |
| + type_c /*tritanomaly*/: { |
| + addendum: [ |
| + [1.0, 0.0, 1.5], |
| + [0.0, 1.0, 0.5], |
| + [0.0, 0.0, -1.0] |
| + ], |
| + delta_factor: [ |
| + [0.0, 0.0, -1.0], |
| + [0.0, 0.0, 1.0], |
| + [0.0, 0.0, 0.0] |
| + ] |
| + } |
| +}; |
| + |
| + |
| +// ======= CVD matrix builders ======= |
| + |
| +function getCvdSimulationMatrix(cvdType, severity) { |
| + var cvdSimulationParam = cvdSimulationParams[cvdType]; |
| + var severity2 = severity * severity; |
| + var matrix = []; |
| + for (var i = 0; i < 3; i++) { |
| + var row = []; |
| + for (var j = 0; j < 3; j++) { |
| + var paramRow = i*3+j; |
| + var val = cvdSimulationParam[paramRow][0] * severity2 |
| + + cvdSimulationParam[paramRow][1] * severity |
| + + cvdSimulationParam[paramRow][2]; |
| + row.push(val); |
| + } |
| + matrix.push(row); |
| + } |
| + return matrix; |
| +} |
| + |
| + |
| +function getCvdCorrectionMatrix(cvdType, delta) { |
| + cvdCorrectionParam = cvdCorrectionParams[cvdType]; |
| + // TODO(mustaq): Perhaps nuke full-matrix operations after experiment. |
| + return add3x3(cvdCorrectionParam["addendum"], |
| + mul3x3Scalar(cvdCorrectionParam["delta_factor"], delta)); |
| +} |
| + |
| + |
| +function getCvdMatrixAsString(cvdType, severity, delta, simulate) { |
| + var effectiveMatrix = getCvdSimulationMatrix(cvdType, severity); |
| + |
| + if (!simulate) { |
| + var cvdCorrectionMatrix = getCvdCorrectionMatrix(cvdType, delta); |
| + var tmpProduct = mul3x3(cvdCorrectionMatrix, effectiveMatrix); |
| + |
| + effectiveMatrix = sub3x3( |
| + add3x3(identityMatrix3x3, cvdCorrectionMatrix), |
| + tmpProduct); |
| + } |
| + |
| + var outputRows = []; |
| + for (var i = 0; i < 3; i++) { |
| + outputRows.push(effectiveMatrix[i].join(" ") + " 0 0"); |
| + } |
| + // Add the alpha row |
| + outputRows.push("0 0 0 1 0"); |
| + return outputRows.join(" "); |
| +} |
| + |
| + |
| +// ======= Page linker ======= |
| + |
| +var svgDefaultMatrix = |
| + "1 0 0 0 0 " + |
| + "0 1 0 0 0 " + |
| + "0 0 1 0 0 " + |
| + "0 0 0 1 0"; |
| + |
| +var svgContent = |
| + '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">' + |
| + ' <defs>' + |
| + ' <filter id="cvd_extension_0">' + |
| + ' <feColorMatrix id="cvd_filter_matrix_0" type="matrix" values="' + |
| + svgDefaultMatrix + '"/>' + |
| + ' </filter>' + |
| + ' <filter id="cvd_extension_1">' + |
| + ' <feColorMatrix id="cvd_filter_matrix_1" type="matrix" values="' + |
| + svgDefaultMatrix + '"/>' + |
| + ' </filter>' + |
| + ' </defs>' + |
| + '</svg>'; |
| + |
| + |
| +function addSvgIfMissing() { |
| + var wrap = document.getElementById("cvd_extension_svg_filter"); |
| + if (!wrap) { |
| + wrap = document.createElement("span"); |
| + wrap.id = "cvd_extension_svg_filter"; |
| + wrap.setAttribute("hidden", ""); |
| + wrap.innerHTML = svgContent; |
| + document.body.appendChild(wrap); |
| + } |
| +} |
| + |
| + |
| +function update() { |
| + if (!document.body) { |
| + document.addEventListener("DOMContentLoaded", update); |
| + return; |
| + } |
| + addSvgIfMissing(); |
| + var next = 1 - curFilter; |
| + |
| + console.log( |
|
kevers
2015/03/09 13:56:59
Please change console.log calls to DebugPrint and
Peter Wen
2015/03/09 21:35:57
Do you mean to create a debugPrint global function
kevers
2015/03/10 14:07:51
Added a note to clarify in reviewer comment on pop
|
| + "Setting matrix#" + next + " to " + |
| + getCvdMatrixAsString( |
| + storedType, storedSeverity, storedDelta, storedSimulate)); |
| + |
| + var matrix = document.getElementById("cvd_filter_matrix_" + next); |
| + matrix.setAttribute( |
| + "values", getCvdMatrixAsString( |
| + storedType, storedSeverity, storedDelta, storedSimulate)); |
| + |
| + var html = document.documentElement; |
| + html.classList.remove("filter" + curFilter); |
| + html.offsetTop; |
| + html.classList.add("filter" + next); |
| + |
| + curFilter = next; |
| + |
| + window.scrollBy(0, 1); |
|
kevers
2015/03/09 13:56:59
This looks like a strange hack. Why is it needed?
dmazzoni
2015/03/09 15:40:40
Yeah, if the filters don't update without this hac
Peter Wen
2015/03/09 21:35:57
Added TODO to investigate.
|
| + window.scrollBy(0, -1); |
| +} |
| + |
| + |
| +function onExtensionMessage(request) { |
| + console.log(request); |
| + var changed = false; |
| + |
| + if (request["delta"] !== undefined) { |
| + var delta = request.delta; |
| + if (storedDelta != delta) { |
| + storedDelta = delta; |
| + changed = true; |
| + } |
| + } |
| + |
| + if (request["severity"] !== undefined) { |
| + var severity = request.severity; |
| + if (storedSeverity != severity) { |
| + storedSeverity = severity; |
| + changed = true; |
| + } |
| + } |
| + |
| + if (request["type"] !== undefined) { |
| + var type = request.type; |
| + if (storedType != type) { |
| + storedType = type; |
| + changed = true; |
| + } |
| + } |
| + |
| + if (request["simulate"] !== undefined) { |
| + var simulate = request.simulate; |
| + if (storedSimulate != simulate) { |
| + storedSimulate = simulate; |
| + changed = true; |
| + } |
| + } |
| + |
| + if (changed) |
| + update(); |
| +} |
| + |
| + |
| +function init() { |
| + chrome.extension.onRequest.addListener(onExtensionMessage); |
| + chrome.extension.sendRequest({"init": true}, onExtensionMessage); |
| +} |
| + |
| + |
| +init(); |