summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/highlighters/fonts.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/actors/highlighters/fonts.js')
-rw-r--r--devtools/server/actors/highlighters/fonts.js122
1 files changed, 122 insertions, 0 deletions
diff --git a/devtools/server/actors/highlighters/fonts.js b/devtools/server/actors/highlighters/fonts.js
new file mode 100644
index 0000000000..3106e1b1fa
--- /dev/null
+++ b/devtools/server/actors/highlighters/fonts.js
@@ -0,0 +1,122 @@
+/* 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 InspectorUtils = require("InspectorUtils");
+loader.lazyRequireGetter(
+ this,
+ "loadSheet",
+ "devtools/shared/layout/utils",
+ true
+);
+loader.lazyRequireGetter(
+ this,
+ "removeSheet",
+ "devtools/shared/layout/utils",
+ true
+);
+
+// How many text runs are we highlighting at a time. There may be many text runs, and we
+// want to prevent performance problems.
+const MAX_TEXT_RANGES = 100;
+
+// This stylesheet is inserted into the page to customize the color of the selected text
+// runs.
+// Note that this color is defined as --highlighter-content-color in the highlighters.css
+// file, and corresponds to the box-model content color. We want to give it an opacity of
+// 0.6 here.
+const STYLESHEET_URI =
+ "data:text/css," +
+ encodeURIComponent(
+ "::selection{background-color:hsl(197,71%,73%,.6)!important;}"
+ );
+
+/**
+ * This highlighter highlights runs of text in the page that have been rendered given a
+ * certain font. The highlighting is done with window selection ranges, so no extra
+ * markup is being inserted into the content page.
+ */
+class FontsHighlighter {
+ constructor(highlighterEnv) {
+ this.env = highlighterEnv;
+ }
+
+ destroy() {
+ this.hide();
+ this.env = this.currentNode = null;
+ }
+
+ get currentNodeDocument() {
+ if (!this.currentNode) {
+ return this.env.document;
+ }
+
+ if (this.currentNode.nodeType === this.currentNode.DOCUMENT_NODE) {
+ return this.currentNode;
+ }
+
+ return this.currentNode.ownerDocument;
+ }
+
+ /**
+ * Show the highlighter for a given node.
+ * @param {DOMNode} node The node in which we want to search for text runs.
+ * @param {Object} options A bunch of options that can be set:
+ * - {String} name The actual font name to look for in the node.
+ * - {String} CSSFamilyName The CSS font-family name given to this font.
+ */
+ show(node, options) {
+ this.currentNode = node;
+ const doc = this.currentNodeDocument;
+
+ // Get all of the fonts used to render content inside the node.
+ const searchRange = doc.createRange();
+ searchRange.selectNodeContents(node);
+
+ const fonts = InspectorUtils.getUsedFontFaces(searchRange, MAX_TEXT_RANGES);
+
+ // Find the ones we want, based on the provided option.
+ const matchingFonts = fonts.filter(
+ f => f.CSSFamilyName === options.CSSFamilyName && f.name === options.name
+ );
+ if (!matchingFonts.length) {
+ return;
+ }
+
+ // Load the stylesheet that will customize the color of the highlighter (using a
+ // ::selection rule).
+ loadSheet(this.env.window, STYLESHEET_URI);
+
+ // Create a multi-selection in the page to highlight the text runs.
+ const selection = doc.defaultView.getSelection();
+ selection.removeAllRanges();
+
+ for (const matchingFont of matchingFonts) {
+ for (const range of matchingFont.ranges) {
+ selection.addRange(range);
+ }
+ }
+ }
+
+ hide() {
+ // No node was highlighted before, don't need to continue any further.
+ if (!this.currentNode) {
+ return;
+ }
+
+ try {
+ removeSheet(this.env.window, STYLESHEET_URI);
+ } catch (e) {
+ // Silently fail here as we might not have inserted the stylesheet at all.
+ }
+
+ // Simply remove all current ranges in the seletion.
+ const doc = this.currentNodeDocument;
+ const selection = doc.defaultView.getSelection();
+ selection.removeAllRanges();
+ }
+}
+
+exports.FontsHighlighter = FontsHighlighter;