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(); |