summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/accessibility/worker.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/actors/accessibility/worker.js')
-rw-r--r--devtools/server/actors/accessibility/worker.js105
1 files changed, 105 insertions, 0 deletions
diff --git a/devtools/server/actors/accessibility/worker.js b/devtools/server/actors/accessibility/worker.js
new file mode 100644
index 0000000000..67fed4d22b
--- /dev/null
+++ b/devtools/server/actors/accessibility/worker.js
@@ -0,0 +1,105 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+/* eslint-env worker */
+
+/**
+ * Import `createTask` to communicate with `devtools/shared/worker`.
+ */
+importScripts("resource://gre/modules/workers/require.js");
+const { createTask } = require("resource://devtools/shared/worker/helper.js");
+
+/**
+ * @see LineGraphWidget.prototype.setDataFromTimestamps in Graphs.js
+ * @param number id
+ * @param array timestamps
+ * @param number interval
+ * @param number duration
+ */
+createTask(self, "getBgRGBA", ({ dataTextBuf, dataBackgroundBuf }) =>
+ getBgRGBA(dataTextBuf, dataBackgroundBuf)
+);
+
+/**
+ * Calculates the luminance of a rgba tuple based on the formula given in
+ * https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ *
+ * @param {Array} rgba An array with [r,g,b,a] values.
+ * @return {Number} The calculated luminance.
+ */
+function calculateLuminance(rgba) {
+ for (let i = 0; i < 3; i++) {
+ rgba[i] /= 255;
+ rgba[i] =
+ rgba[i] < 0.03928
+ ? rgba[i] / 12.92
+ : Math.pow((rgba[i] + 0.055) / 1.055, 2.4);
+ }
+ return 0.2126 * rgba[0] + 0.7152 * rgba[1] + 0.0722 * rgba[2];
+}
+
+/**
+ * Get RGBA or a range of RGBAs for the background pixels under the text. If luminance is
+ * uniform, only return one value of RGBA, otherwise return values that correspond to the
+ * min and max luminances.
+ * @param {ImageData} dataTextBuf
+ * pixel data for the accessible object with text visible.
+ * @param {ImageData} dataBackgroundBuf
+ * pixel data for the accessible object with transparent text.
+ * @return {Object}
+ * RGBA or a range of RGBAs with min and max values.
+ */
+function getBgRGBA(dataTextBuf, dataBackgroundBuf) {
+ let min = [0, 0, 0, 1];
+ let max = [255, 255, 255, 1];
+ let minLuminance = 1;
+ let maxLuminance = 0;
+ const luminances = {};
+ const dataText = new Uint8ClampedArray(dataTextBuf);
+ const dataBackground = new Uint8ClampedArray(dataBackgroundBuf);
+
+ let foundDistinctColor = false;
+ for (let i = 0; i < dataText.length; i = i + 4) {
+ const tR = dataText[i];
+ const bgR = dataBackground[i];
+ const tG = dataText[i + 1];
+ const bgG = dataBackground[i + 1];
+ const tB = dataText[i + 2];
+ const bgB = dataBackground[i + 2];
+
+ // Ignore pixels that are the same where pixels that are different between the two
+ // images are assumed to belong to the text within the node.
+ if (tR === bgR && tG === bgG && tB === bgB) {
+ continue;
+ }
+
+ foundDistinctColor = true;
+
+ const bgColor = `rgb(${bgR}, ${bgG}, ${bgB})`;
+ let luminance = luminances[bgColor];
+
+ if (!luminance) {
+ // Calculate luminance for the RGB value and store it to only measure once.
+ luminance = calculateLuminance([bgR, bgG, bgB]);
+ luminances[bgColor] = luminance;
+ }
+
+ if (minLuminance >= luminance) {
+ minLuminance = luminance;
+ min = [bgR, bgG, bgB, 1];
+ }
+
+ if (maxLuminance <= luminance) {
+ maxLuminance = luminance;
+ max = [bgR, bgG, bgB, 1];
+ }
+ }
+
+ if (!foundDistinctColor) {
+ return null;
+ }
+
+ return minLuminance === maxLuminance ? { value: max } : { min, max };
+}