mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 987797 - Font preview tooltip does not preview web fonts. r=bgrins
This commit is contained in:
parent
846faa287d
commit
5acb30cc53
@ -37,7 +37,6 @@ const SPECTRUM_FRAME = "chrome://browser/content/devtools/spectrum-frame.xhtml";
|
||||
const ESCAPE_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE;
|
||||
const RETURN_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_RETURN;
|
||||
const POPUP_EVENTS = ["shown", "hidden", "showing", "hiding"];
|
||||
const FONT_FAMILY_PREVIEW_TEXT = "(ABCabc123&@%)";
|
||||
|
||||
/**
|
||||
* Tooltip widget.
|
||||
@ -636,7 +635,9 @@ Tooltip.prototype = {
|
||||
* it was resized, if if was resized before this function was called.
|
||||
* If not provided, will be measured on the loaded image.
|
||||
* - maxDim : if the image should be resized before being shown, pass
|
||||
* a number here
|
||||
* a number here.
|
||||
* - hideDimensionLabel : if the dimension label should be appended
|
||||
* after the image.
|
||||
*/
|
||||
setImageContent: function(imageUrl, options={}) {
|
||||
if (!imageUrl) {
|
||||
@ -656,25 +657,28 @@ Tooltip.prototype = {
|
||||
}
|
||||
vbox.appendChild(image);
|
||||
|
||||
// Dimension label
|
||||
let label = this.doc.createElement("label");
|
||||
label.classList.add("devtools-tooltip-caption");
|
||||
label.classList.add("theme-comment");
|
||||
if (options.naturalWidth && options.naturalHeight) {
|
||||
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
|
||||
options.naturalHeight);
|
||||
} else {
|
||||
// If no dimensions were provided, load the image to get them
|
||||
label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
|
||||
let imgObj = new this.doc.defaultView.Image();
|
||||
imgObj.src = imageUrl;
|
||||
imgObj.onload = () => {
|
||||
imgObj.onload = null;
|
||||
label.textContent = this._getImageDimensionLabel(imgObj.naturalWidth,
|
||||
imgObj.naturalHeight);
|
||||
if (!options.hideDimensionLabel) {
|
||||
let label = this.doc.createElement("label");
|
||||
label.classList.add("devtools-tooltip-caption");
|
||||
label.classList.add("theme-comment");
|
||||
|
||||
if (options.naturalWidth && options.naturalHeight) {
|
||||
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
|
||||
options.naturalHeight);
|
||||
} else {
|
||||
// If no dimensions were provided, load the image to get them
|
||||
label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
|
||||
let imgObj = new this.doc.defaultView.Image();
|
||||
imgObj.src = imageUrl;
|
||||
imgObj.onload = () => {
|
||||
imgObj.onload = null;
|
||||
label.textContent = this._getImageDimensionLabel(imgObj.naturalWidth,
|
||||
imgObj.naturalHeight);
|
||||
}
|
||||
}
|
||||
|
||||
vbox.appendChild(label);
|
||||
}
|
||||
vbox.appendChild(label);
|
||||
|
||||
this.content = vbox;
|
||||
},
|
||||
@ -777,26 +781,30 @@ Tooltip.prototype = {
|
||||
* This is based on Lea Verou's Dablet. See https://github.com/LeaVerou/dabblet
|
||||
* for more info.
|
||||
* @param {String} font The font family value.
|
||||
* @param {object} nodeFront
|
||||
* The NodeActor that will used to retrieve the dataURL for the font
|
||||
* family tooltip contents.
|
||||
* @return A promise that resolves when the font tooltip content is ready, or
|
||||
* rejects if no font is provided
|
||||
*/
|
||||
setFontFamilyContent: function(font) {
|
||||
if (!font) {
|
||||
return;
|
||||
setFontFamilyContent: Task.async(function*(font, nodeFront) {
|
||||
if (!font || !nodeFront) {
|
||||
throw "Missing font";
|
||||
}
|
||||
|
||||
// Main container
|
||||
let vbox = this.doc.createElement("vbox");
|
||||
vbox.setAttribute("flex", "1");
|
||||
if (typeof nodeFront.getFontFamilyDataURL === "function") {
|
||||
font = font.replace(/"/g, "'");
|
||||
font = font.replace("!important", "");
|
||||
font = font.trim();
|
||||
|
||||
// Display the font family previewer
|
||||
let previewer = this.doc.createElement("description");
|
||||
previewer.setAttribute("flex", "1");
|
||||
previewer.style.fontFamily = font;
|
||||
previewer.classList.add("devtools-tooltip-font-previewer-text");
|
||||
previewer.textContent = FONT_FAMILY_PREVIEW_TEXT;
|
||||
vbox.appendChild(previewer);
|
||||
let fillStyle = (Services.prefs.getCharPref("devtools.theme") === "light") ?
|
||||
"black" : "white";
|
||||
|
||||
this.content = vbox;
|
||||
}
|
||||
let {data, size} = yield nodeFront.getFontFamilyDataURL(font, fillStyle);
|
||||
let str = yield data.string();
|
||||
this.setImageContent(str, { hideDimensionLabel: true, maxDim: size });
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -545,8 +545,12 @@ CssHtmlTree.prototype = {
|
||||
|
||||
// Test for font family
|
||||
if (propName.textContent === "font-family") {
|
||||
this.tooltip.setFontFamilyContent(propValue.textContent);
|
||||
return true;
|
||||
let prop = propValue.textContent.toLowerCase();
|
||||
|
||||
if (prop !== "inherit" && prop !== "unset" && prop !== "initial") {
|
||||
return this.tooltip.setFontFamilyContent(propValue.textContent,
|
||||
inspector.selection.nodeFront);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1212,8 +1212,12 @@ CssRuleView.prototype = {
|
||||
return this.previewTooltip.setRelativeImageContent(uri, this.inspector.inspector, dim);
|
||||
}
|
||||
if (tooltipType === "font") {
|
||||
this.previewTooltip.setFontFamilyContent(target.textContent);
|
||||
return true;
|
||||
let prop = target.textContent.toLowerCase();
|
||||
|
||||
if (prop !== "inherit" && prop !== "unset" && prop !== "initial") {
|
||||
return this.previewTooltip.setFontFamilyContent(target.textContent,
|
||||
this.inspector.selection.nodeFront);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -29,15 +29,15 @@ let test = asyncTest(function*() {
|
||||
info("Selecting the test node");
|
||||
yield selectNode("#testElement", inspector);
|
||||
|
||||
yield testRuleView(view);
|
||||
yield testRuleView(view, inspector.selection.nodeFront);
|
||||
|
||||
info("Opening the computed view");
|
||||
let {toolbox, inspector, view} = yield openComputedView();
|
||||
|
||||
yield testComputedView(view);
|
||||
yield testComputedView(view, inspector.selection.nodeFront);
|
||||
});
|
||||
|
||||
function* testRuleView(ruleView) {
|
||||
function* testRuleView(ruleView, nodeFront) {
|
||||
info("Testing font-family tooltips in the rule view");
|
||||
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
@ -52,11 +52,15 @@ function* testRuleView(ruleView) {
|
||||
// And verify that the tooltip gets shown on this property
|
||||
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
|
||||
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
||||
function* testComputedView(computedView) {
|
||||
function* testComputedView(computedView, nodeFront) {
|
||||
info("Testing font-family tooltips in the computed view");
|
||||
|
||||
let panel = computedView.tooltip.panel;
|
||||
@ -64,6 +68,10 @@ function* testComputedView(computedView) {
|
||||
|
||||
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
|
||||
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
@ -27,15 +27,15 @@ let test = asyncTest(function*() {
|
||||
info("Selecting the test node");
|
||||
yield selectNode("#testElement", inspector);
|
||||
|
||||
yield testRuleView(view);
|
||||
yield testRuleView(view, inspector.selection.nodeFront);
|
||||
|
||||
info("Opening the computed view");
|
||||
let {toolbox, inspector, view} = yield openComputedView();
|
||||
|
||||
yield testComputedView(view);
|
||||
yield testComputedView(view, inspector.selection.nodeFront);
|
||||
});
|
||||
|
||||
function* testRuleView(ruleView) {
|
||||
function* testRuleView(ruleView, nodeFront) {
|
||||
info("Testing font-family tooltips in the rule view");
|
||||
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
@ -55,11 +55,15 @@ function* testRuleView(ruleView) {
|
||||
// And verify that the tooltip gets shown on this property
|
||||
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
|
||||
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
||||
function* testComputedView(computedView) {
|
||||
function* testComputedView(computedView, nodeFront) {
|
||||
info("Testing font-family tooltips in the computed view");
|
||||
|
||||
let panel = computedView.tooltip.panel;
|
||||
@ -67,6 +71,10 @@ function* testComputedView(computedView) {
|
||||
|
||||
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
|
||||
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
|
||||
let dataURL = yield getFontFamilyDataURL(valueSpan.textContent, nodeFront);
|
||||
is(images[0].getAttribute("src"), dataURL, "Tooltip contains the correct data-uri image");
|
||||
}
|
||||
|
@ -468,6 +468,22 @@ function hasSideBarTab(inspector, id) {
|
||||
return !!inspector.sidebar.getWindowForTab(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataURL for the font family tooltip.
|
||||
* @param {String} font The font family value.
|
||||
* @param {object} nodeFront
|
||||
* The NodeActor that will used to retrieve the dataURL for the
|
||||
* font family tooltip contents.
|
||||
*/
|
||||
let getFontFamilyDataURL = Task.async(function*(font, nodeFront) {
|
||||
let fillStyle = (Services.prefs.getCharPref("devtools.theme") === "light") ?
|
||||
"black" : "white";
|
||||
|
||||
let {data} = yield nodeFront.getFontFamilyDataURL(font, fillStyle);
|
||||
let dataURL = yield data.string();
|
||||
return dataURL;
|
||||
});
|
||||
|
||||
/* *********************************************
|
||||
* RULE-VIEW
|
||||
* *********************************************
|
||||
|
@ -184,14 +184,6 @@
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
|
||||
/* Tooltip: Font Family Previewer Text */
|
||||
.devtools-tooltip-font-previewer-text {
|
||||
max-width: 400px;
|
||||
line-height: 1.5;
|
||||
font-size: 150%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Tooltip: Alert Icon */
|
||||
|
||||
.devtools-tooltip-alert-icon {
|
||||
|
@ -349,10 +349,6 @@ div.CodeMirror span.eval-text {
|
||||
border-bottom: 1px solid #434850;
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .devtools-tooltip-font-previewer-text {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .devtools-tooltip-simple-text:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
@ -358,10 +358,6 @@ div.CodeMirror span.eval-text {
|
||||
border-bottom: 1px solid #d9e1e8;
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .devtools-tooltip-font-previewer-text {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.theme-tooltip-panel .devtools-tooltip-simple-text:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ const {Class} = require("sdk/core/heritage");
|
||||
const {PageStyleActor} = require("devtools/server/actors/styles");
|
||||
const {HighlighterActor} = require("devtools/server/actors/highlighter");
|
||||
|
||||
const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
|
||||
const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
|
||||
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
@ -351,6 +353,42 @@ var NodeActor = exports.NodeActor = protocol.ActorClass({
|
||||
modifications: Arg(0, "array:json")
|
||||
},
|
||||
response: {}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Given the font and fill style, get the image data of a canvas with the
|
||||
* preview text and font.
|
||||
* Returns an imageData object with the actual data being a LongStringActor
|
||||
* and the width of the text as a string.
|
||||
* The image data is transmitted as a base64 encoded png data-uri.
|
||||
*/
|
||||
getFontFamilyDataURL: method(function(font, fillStyle="black") {
|
||||
let doc = this.rawNode.ownerDocument;
|
||||
let canvas = doc.createElementNS(XHTML_NS, "canvas");
|
||||
let ctx = canvas.getContext("2d");
|
||||
let fontValue = FONT_FAMILY_PREVIEW_TEXT_SIZE + "px " + font + ", serif";
|
||||
|
||||
// Get the correct preview text measurements and set the canvas dimensions
|
||||
ctx.font = fontValue;
|
||||
let textWidth = ctx.measureText(FONT_FAMILY_PREVIEW_TEXT).width;
|
||||
canvas.width = textWidth * 2;
|
||||
canvas.height = FONT_FAMILY_PREVIEW_TEXT_SIZE * 3;
|
||||
|
||||
ctx.font = fontValue;
|
||||
ctx.fillStyle = fillStyle;
|
||||
|
||||
// Align the text to be vertically center in the tooltip and
|
||||
// oversample the canvas for better text quality
|
||||
ctx.textBaseline = "top";
|
||||
ctx.scale(2, 2);
|
||||
ctx.fillText(FONT_FAMILY_PREVIEW_TEXT, 0, Math.round(FONT_FAMILY_PREVIEW_TEXT_SIZE / 3));
|
||||
|
||||
let dataURL = canvas.toDataURL("image/png");
|
||||
|
||||
return { data: LongStringActor(this.conn, dataURL), size: textWidth };
|
||||
}, {
|
||||
request: {font: Arg(0, "string"), fillStyle: Arg(1, "nullable:string")},
|
||||
response: RetVal("imageData")
|
||||
})
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user