forked from mirrors/gecko-dev
MozReview-Commit-ID: 6cLDkoCt0al --HG-- extra : rebase_source : 26e95a9320998085675a1f14bfa4442f4bbc38dc
94 lines
3 KiB
JavaScript
94 lines
3 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";
|
|
|
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
|
|
const WATERFALL_BACKGROUND_TICKS_MULTIPLE = 5; // ms
|
|
const WATERFALL_BACKGROUND_TICKS_SCALES = 3;
|
|
const WATERFALL_BACKGROUND_TICKS_SPACING_MIN = 10; // px
|
|
const WATERFALL_BACKGROUND_TICKS_COLOR_RGB = [128, 136, 144];
|
|
const WATERFALL_BACKGROUND_TICKS_OPACITY_MIN = 32; // byte
|
|
const WATERFALL_BACKGROUND_TICKS_OPACITY_ADD = 32; // byte
|
|
|
|
const FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS = 100;
|
|
|
|
/**
|
|
* Creates the background displayed on the marker's waterfall.
|
|
*/
|
|
function drawWaterfallBackground(doc, dataScale, waterfallWidth) {
|
|
let canvas = doc.createElementNS(HTML_NS, "canvas");
|
|
let ctx = canvas.getContext("2d");
|
|
|
|
// Nuke the context.
|
|
let canvasWidth = canvas.width = waterfallWidth;
|
|
// Awww yeah, 1px, repeats on Y axis.
|
|
let canvasHeight = canvas.height = 1;
|
|
|
|
// Start over.
|
|
let imageData = ctx.createImageData(canvasWidth, canvasHeight);
|
|
let pixelArray = imageData.data;
|
|
|
|
let buf = new ArrayBuffer(pixelArray.length);
|
|
let view8bit = new Uint8ClampedArray(buf);
|
|
let view32bit = new Uint32Array(buf);
|
|
|
|
// Build new millisecond tick lines...
|
|
let [r, g, b] = WATERFALL_BACKGROUND_TICKS_COLOR_RGB;
|
|
let alphaComponent = WATERFALL_BACKGROUND_TICKS_OPACITY_MIN;
|
|
let tickInterval = findOptimalTickInterval({
|
|
ticksMultiple: WATERFALL_BACKGROUND_TICKS_MULTIPLE,
|
|
ticksSpacingMin: WATERFALL_BACKGROUND_TICKS_SPACING_MIN,
|
|
dataScale: dataScale
|
|
});
|
|
|
|
// Insert one pixel for each division on each scale.
|
|
for (let i = 1; i <= WATERFALL_BACKGROUND_TICKS_SCALES; i++) {
|
|
let increment = tickInterval * Math.pow(2, i);
|
|
for (let x = 0; x < canvasWidth; x += increment) {
|
|
let position = x | 0;
|
|
view32bit[position] = (alphaComponent << 24) | (b << 16) | (g << 8) | r;
|
|
}
|
|
alphaComponent += WATERFALL_BACKGROUND_TICKS_OPACITY_ADD;
|
|
}
|
|
|
|
// Flush the image data and cache the waterfall background.
|
|
pixelArray.set(view8bit);
|
|
ctx.putImageData(imageData, 0, 0);
|
|
doc.mozSetImageElement("waterfall-background", canvas);
|
|
|
|
return canvas;
|
|
}
|
|
|
|
/**
|
|
* Finds the optimal tick interval between time markers in this timeline.
|
|
*
|
|
* @param number ticksMultiple
|
|
* @param number ticksSpacingMin
|
|
* @param number dataScale
|
|
* @return number
|
|
*/
|
|
function findOptimalTickInterval({ ticksMultiple, ticksSpacingMin, dataScale }) {
|
|
let timingStep = ticksMultiple;
|
|
let maxIters = FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS;
|
|
let numIters = 0;
|
|
|
|
if (dataScale > ticksSpacingMin) {
|
|
return dataScale;
|
|
}
|
|
|
|
while (true) {
|
|
let scaledStep = dataScale * timingStep;
|
|
if (++numIters > maxIters) {
|
|
return scaledStep;
|
|
}
|
|
if (scaledStep < ticksSpacingMin) {
|
|
timingStep <<= 1;
|
|
continue;
|
|
}
|
|
return scaledStep;
|
|
}
|
|
}
|
|
|
|
exports.TickUtils = { findOptimalTickInterval, drawWaterfallBackground };
|