103 lines
3.2 KiB
JavaScript
103 lines
3.2 KiB
JavaScript
/* 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";
|
|
|
|
/**
|
|
* 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 };
|
|
}
|