gecko-dev/devtools/server/actors/replay/graphics.js

94 строки
3.2 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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/. */
// This module defines the routines used when updating the graphics shown by a
// middleman process tab. Middleman processes have their own window/document
// which are connected to the compositor in the UI process in the usual way.
// We need to update the contents of the document to draw the raw graphics data
// provided by the child process.
"use strict";
ChromeUtils.import("resource://gre/modules/Services.jsm");
const CC = Components.Constructor;
// Create a sandbox with the resources we need. require() doesn't work here.
const sandbox = Cu.Sandbox(CC("@mozilla.org/systemprincipal;1", "nsIPrincipal")());
Cu.evalInSandbox(
"Components.utils.import('resource://gre/modules/jsdebugger.jsm');" +
"addDebuggerToGlobal(this);",
sandbox
);
// Windows in the middleman process are initially set up as about:blank pages.
// This method fills them in with a canvas filling the tab.
function setupContents(window) {
// The middlemanCanvas element fills the tab's contents.
const canvas = window.middlemanCanvas = window.document.createElement("canvas");
canvas.style.position = "absolute";
window.document.body.style.margin = "0px";
window.document.body.prepend(canvas);
}
function getCanvas(window) {
if (!window.middlemanCanvas) {
setupContents(window);
}
return window.middlemanCanvas;
}
function updateWindowCanvas(window, buffer, width, height, hadFailure) {
// Make sure the window has a canvas filling the screen.
const canvas = getCanvas(window);
canvas.width = width;
canvas.height = height;
// If there is a scale for this window, then the graphics will already have
// been scaled in the child process. To avoid scaling the graphics twice,
// transform the canvas to undo the scaling.
const scale = window.devicePixelRatio;
if (scale != 1) {
canvas.style.transform =
`scale(${ 1 / scale }) translate(-${ width / scale }px, -${ height / scale }px)`;
}
const cx = canvas.getContext("2d");
const graphicsData = new Uint8Array(buffer);
const imageData = cx.getImageData(0, 0, width, height);
imageData.data.set(graphicsData);
cx.putImageData(imageData, 0, 0);
// Indicate to the user when repainting failed and we are showing old painted
// graphics instead of the most up-to-date graphics.
if (hadFailure) {
cx.fillStyle = "red";
cx.font = "48px serif";
cx.fillText("PAINT FAILURE", 10, 50);
}
}
// Entry point for when we have some new graphics data from the child process
// to draw.
// eslint-disable-next-line no-unused-vars
function UpdateCanvas(buffer, width, height, hadFailure) {
try {
// Paint to all windows we can find. Hopefully there is only one.
for (const window of Services.ww.getWindowEnumerator()) {
updateWindowCanvas(window, buffer, width, height, hadFailure);
}
} catch (e) {
dump("Middleman Graphics UpdateCanvas Exception: " + e + "\n");
}
}
// eslint-disable-next-line no-unused-vars
var EXPORTED_SYMBOLS = [
"UpdateCanvas",
];