1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 // ======= Global state =======
9 var storedSeverity = 0;
10 var storedType = 'PROTANOMALY';
11 var storedSimulate = false;
15 // ======= 3x3 matrix ops =======
17 var identityMatrix3x3 = [
27 function add3x3(m1, m2) {
29 for (var i = 0; i < 3; i++) {
31 for (var j = 0; j < 3; j++) {
32 result[i].push(m1[i][j] + m2[i][j]);
42 function sub3x3(m1, m2) {
44 for (var i = 0; i < 3; i++) {
46 for (var j = 0; j < 3; j++) {
47 result[i].push(m1[i][j] - m2[i][j]);
57 function mul3x3(m1, m2) {
59 for (var i = 0; i < 3; i++) {
61 for (var j = 0; j < 3; j++) {
63 for (var k = 0; k < 3; k++) {
64 sum += m1[i][k] * m2[k][j];
76 function mul3x3Scalar(m, k) {
78 for (var i = 0; i < 3; i++) {
80 for (var j = 0; j < 3; j++) {
81 result[i].push(k * m[i][j]);
88 // ======= CVD parameters =======
90 * Parameters for simulating color vision deficiency.
92 * http://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html
93 * Original Research Paper:
94 * http://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/Machado_Oliveira_Fernandes_CVD_Vis2009_final.pdf
98 var cvdSimulationParams = {
100 [0.4720, -1.2946, 0.9857],
101 [-0.6128, 1.6326, 0.0187],
102 [0.1407, -0.3380, -0.0044],
103 [-0.1420, 0.2488, 0.0044],
104 [0.1872, -0.3908, 0.9942],
105 [-0.0451, 0.1420, 0.0013],
106 [0.0222, -0.0253, -0.0004],
107 [-0.0290, -0.0201, 0.0006],
108 [0.0068, 0.0454, 0.9990]
111 [0.5442, -1.1454, 0.9818],
112 [-0.7091, 1.5287, 0.0238],
113 [0.1650, -0.3833, -0.0055],
114 [-0.1664, 0.4368, 0.0056],
115 [0.2178, -0.5327, 0.9927],
116 [-0.0514, 0.0958, 0.0017],
117 [0.0180, -0.0288, -0.0006],
118 [-0.0232, -0.0649, 0.0007],
119 [0.0052, 0.0360, 0.9998]
122 [0.4275, -0.0181, 0.9307],
123 [-0.2454, 0.0013, 0.0827],
124 [-0.1821, 0.0168, -0.0134],
125 [-0.1280, 0.0047, 0.0202],
126 [0.0233, -0.0398, 0.9728],
127 [0.1048, 0.0352, 0.0070],
128 [-0.0156, 0.0061, 0.0071],
129 [0.3841, 0.2947, 0.0151],
130 [-0.3685, -0.3008, 0.9778]
135 // TODO(mustaq): A common matrix for all types? E.g. Kevin's experiment
136 // suggested: Mx[1][0] = 0.7+0.3*delta and Mx[2][0] = 0.7-0.3*delta
138 * TODO(mustaq): JsDoc
142 var cvdCorrectionParams = {
182 // ======= CVD matrix builders =======
185 * TODO(mustaq): JsDoc
187 function getCvdSimulationMatrix(cvdType, severity) {
188 var cvdSimulationParam = cvdSimulationParams[cvdType];
189 var severity2 = severity * severity;
191 for (var i = 0; i < 3; i++) {
193 for (var j = 0; j < 3; j++) {
194 var paramRow = i*3+j;
195 var val = cvdSimulationParam[paramRow][0] * severity2
196 + cvdSimulationParam[paramRow][1] * severity
197 + cvdSimulationParam[paramRow][2];
207 * TODO(mustaq): JsDoc
209 function getCvdCorrectionMatrix(cvdType, delta) {
210 cvdCorrectionParam = cvdCorrectionParams[cvdType];
211 // TODO(mustaq): Perhaps nuke full-matrix operations after experiment.
212 return add3x3(cvdCorrectionParam['addendum'],
213 mul3x3Scalar(cvdCorrectionParam['delta_factor'], delta));
218 * TODO(mustaq): JsDoc
220 function getCvdMatrixAsString(cvdType, severity, delta, simulate) {
221 var effectiveMatrix = getCvdSimulationMatrix(cvdType, severity);
224 var cvdCorrectionMatrix = getCvdCorrectionMatrix(cvdType, delta);
225 var tmpProduct = mul3x3(cvdCorrectionMatrix, effectiveMatrix);
227 effectiveMatrix = sub3x3(
228 add3x3(identityMatrix3x3, cvdCorrectionMatrix),
233 for (var i = 0; i < 3; i++) {
234 outputRows.push(effectiveMatrix[i].join(' ') + ' 0 0');
237 outputRows.push('0 0 0 1 0');
238 return outputRows.join(' ');
242 // ======= Page linker =======
244 var svgDefaultMatrix =
251 '<svg xmlns='http://www.w3.org/2000/svg' version='1.1'>' +
253 ' <filter id='cvd_extension_0'>' +
254 ' <feColorMatrix id='cvd_filter_matrix_0' type='matrix' values='' +
255 svgDefaultMatrix + ''/>' +
257 ' <filter id='cvd_extension_1'>' +
258 ' <feColorMatrix id='cvd_filter_matrix_1' type='matrix' values='' +
259 svgDefaultMatrix + ''/>' +
265 * Checks for svg filter matrix presence and append to DOM if not present.
267 function addSvgIfMissing() {
268 var wrap = document.getElementById('cvd_extension_svg_filter');
270 wrap = document.createElement('span');
271 wrap.id = 'cvd_extension_svg_filter';
272 wrap.setAttribute('hidden', '');
273 wrap.innerHTML = svgContent;
274 document.body.appendChild(wrap);
280 * Update matrix when config values change.
283 if (!document.body) {
284 document.addEventListener('DOMContentLoaded', update);
288 var next = 1 - curFilter;
291 'Setting matrix#' + next + ' to ' +
292 getCvdMatrixAsString(
293 storedType, storedSeverity, storedDelta, storedSimulate));
295 var matrix = document.getElementById('cvd_filter_matrix_' + next);
297 'values', getCvdMatrixAsString(
298 storedType, storedSeverity, storedDelta, storedSimulate));
300 var html = document.documentElement;
301 html.classList.remove('filter' + curFilter);
303 html.classList.add('filter' + next);
307 // TODO(wnwen): Figure out whether this hack is still necessary.
308 window.scrollBy(0, 1);
309 window.scrollBy(0, -1);
314 * Process request from background page.
316 function onExtensionMessage(request) {
319 if (request['delta'] !== undefined) {
320 var delta = request.delta;
321 if (storedDelta != delta) {
327 if (request['severity'] !== undefined) {
328 var severity = request.severity;
329 if (storedSeverity != severity) {
330 storedSeverity = severity;
335 if (request['type'] !== undefined) {
336 var type = request.type;
337 if (storedType != type) {
343 if (request['simulate'] !== undefined) {
344 var simulate = request.simulate;
345 if (storedSimulate != simulate) {
346 storedSimulate = simulate;
357 * Prepare to process background messages and let it know to send initial
360 (function initialize() {
361 chrome.extension.onRequest.addListener(onExtensionMessage);
362 chrome.extension.sendRequest({'init': true}, onExtensionMessage);