1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/* 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 };
}
|