mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +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 ESCAPE_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE;
|
||||||
const RETURN_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_RETURN;
|
const RETURN_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_RETURN;
|
||||||
const POPUP_EVENTS = ["shown", "hidden", "showing", "hiding"];
|
const POPUP_EVENTS = ["shown", "hidden", "showing", "hiding"];
|
||||||
const FONT_FAMILY_PREVIEW_TEXT = "(ABCabc123&@%)";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tooltip widget.
|
* Tooltip widget.
|
||||||
@ -636,7 +635,9 @@ Tooltip.prototype = {
|
|||||||
* it was resized, if if was resized before this function was called.
|
* it was resized, if if was resized before this function was called.
|
||||||
* If not provided, will be measured on the loaded image.
|
* If not provided, will be measured on the loaded image.
|
||||||
* - maxDim : if the image should be resized before being shown, pass
|
* - 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={}) {
|
setImageContent: function(imageUrl, options={}) {
|
||||||
if (!imageUrl) {
|
if (!imageUrl) {
|
||||||
@ -656,10 +657,11 @@ Tooltip.prototype = {
|
|||||||
}
|
}
|
||||||
vbox.appendChild(image);
|
vbox.appendChild(image);
|
||||||
|
|
||||||
// Dimension label
|
if (!options.hideDimensionLabel) {
|
||||||
let label = this.doc.createElement("label");
|
let label = this.doc.createElement("label");
|
||||||
label.classList.add("devtools-tooltip-caption");
|
label.classList.add("devtools-tooltip-caption");
|
||||||
label.classList.add("theme-comment");
|
label.classList.add("theme-comment");
|
||||||
|
|
||||||
if (options.naturalWidth && options.naturalHeight) {
|
if (options.naturalWidth && options.naturalHeight) {
|
||||||
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
|
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
|
||||||
options.naturalHeight);
|
options.naturalHeight);
|
||||||
@ -674,7 +676,9 @@ Tooltip.prototype = {
|
|||||||
imgObj.naturalHeight);
|
imgObj.naturalHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vbox.appendChild(label);
|
vbox.appendChild(label);
|
||||||
|
}
|
||||||
|
|
||||||
this.content = vbox;
|
this.content = vbox;
|
||||||
},
|
},
|
||||||
@ -777,26 +781,30 @@ Tooltip.prototype = {
|
|||||||
* This is based on Lea Verou's Dablet. See https://github.com/LeaVerou/dabblet
|
* This is based on Lea Verou's Dablet. See https://github.com/LeaVerou/dabblet
|
||||||
* for more info.
|
* for more info.
|
||||||
* @param {String} font The font family value.
|
* @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) {
|
setFontFamilyContent: Task.async(function*(font, nodeFront) {
|
||||||
if (!font) {
|
if (!font || !nodeFront) {
|
||||||
return;
|
throw "Missing font";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main container
|
if (typeof nodeFront.getFontFamilyDataURL === "function") {
|
||||||
let vbox = this.doc.createElement("vbox");
|
font = font.replace(/"/g, "'");
|
||||||
vbox.setAttribute("flex", "1");
|
font = font.replace("!important", "");
|
||||||
|
font = font.trim();
|
||||||
|
|
||||||
// Display the font family previewer
|
let fillStyle = (Services.prefs.getCharPref("devtools.theme") === "light") ?
|
||||||
let previewer = this.doc.createElement("description");
|
"black" : "white";
|
||||||
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);
|
|
||||||
|
|
||||||
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
|
// Test for font family
|
||||||
if (propName.textContent === "font-family") {
|
if (propName.textContent === "font-family") {
|
||||||
this.tooltip.setFontFamilyContent(propValue.textContent);
|
let prop = propValue.textContent.toLowerCase();
|
||||||
return true;
|
|
||||||
|
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);
|
return this.previewTooltip.setRelativeImageContent(uri, this.inspector.inspector, dim);
|
||||||
}
|
}
|
||||||
if (tooltipType === "font") {
|
if (tooltipType === "font") {
|
||||||
this.previewTooltip.setFontFamilyContent(target.textContent);
|
let prop = target.textContent.toLowerCase();
|
||||||
return true;
|
|
||||||
|
if (prop !== "inherit" && prop !== "unset" && prop !== "initial") {
|
||||||
|
return this.previewTooltip.setFontFamilyContent(target.textContent,
|
||||||
|
this.inspector.selection.nodeFront);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -29,15 +29,15 @@ let test = asyncTest(function*() {
|
|||||||
info("Selecting the test node");
|
info("Selecting the test node");
|
||||||
yield selectNode("#testElement", inspector);
|
yield selectNode("#testElement", inspector);
|
||||||
|
|
||||||
yield testRuleView(view);
|
yield testRuleView(view, inspector.selection.nodeFront);
|
||||||
|
|
||||||
info("Opening the computed view");
|
info("Opening the computed view");
|
||||||
let {toolbox, inspector, view} = yield openComputedView();
|
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");
|
info("Testing font-family tooltips in the rule view");
|
||||||
|
|
||||||
let panel = ruleView.previewTooltip.panel;
|
let panel = ruleView.previewTooltip.panel;
|
||||||
@ -52,11 +52,15 @@ function* testRuleView(ruleView) {
|
|||||||
// And verify that the tooltip gets shown on this property
|
// And verify that the tooltip gets shown on this property
|
||||||
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
|
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
|
||||||
|
|
||||||
let description = panel.getElementsByTagName("description")[0];
|
let images = panel.getElementsByTagName("image");
|
||||||
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
|
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");
|
info("Testing font-family tooltips in the computed view");
|
||||||
|
|
||||||
let panel = computedView.tooltip.panel;
|
let panel = computedView.tooltip.panel;
|
||||||
@ -64,6 +68,10 @@ function* testComputedView(computedView) {
|
|||||||
|
|
||||||
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
|
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
|
||||||
|
|
||||||
let description = panel.getElementsByTagName("description")[0];
|
let images = panel.getElementsByTagName("image");
|
||||||
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
|
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");
|
info("Selecting the test node");
|
||||||
yield selectNode("#testElement", inspector);
|
yield selectNode("#testElement", inspector);
|
||||||
|
|
||||||
yield testRuleView(view);
|
yield testRuleView(view, inspector.selection.nodeFront);
|
||||||
|
|
||||||
info("Opening the computed view");
|
info("Opening the computed view");
|
||||||
let {toolbox, inspector, view} = yield openComputedView();
|
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");
|
info("Testing font-family tooltips in the rule view");
|
||||||
|
|
||||||
let panel = ruleView.previewTooltip.panel;
|
let panel = ruleView.previewTooltip.panel;
|
||||||
@ -55,11 +55,15 @@ function* testRuleView(ruleView) {
|
|||||||
// And verify that the tooltip gets shown on this property
|
// And verify that the tooltip gets shown on this property
|
||||||
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
|
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
|
||||||
|
|
||||||
let description = panel.getElementsByTagName("description")[0];
|
let images = panel.getElementsByTagName("image");
|
||||||
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
|
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");
|
info("Testing font-family tooltips in the computed view");
|
||||||
|
|
||||||
let panel = computedView.tooltip.panel;
|
let panel = computedView.tooltip.panel;
|
||||||
@ -67,6 +71,10 @@ function* testComputedView(computedView) {
|
|||||||
|
|
||||||
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
|
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
|
||||||
|
|
||||||
let description = panel.getElementsByTagName("description")[0];
|
let images = panel.getElementsByTagName("image");
|
||||||
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
|
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);
|
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
|
* RULE-VIEW
|
||||||
* *********************************************
|
* *********************************************
|
||||||
|
@ -184,14 +184,6 @@
|
|||||||
margin-bottom: -4px;
|
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 */
|
/* Tooltip: Alert Icon */
|
||||||
|
|
||||||
.devtools-tooltip-alert-icon {
|
.devtools-tooltip-alert-icon {
|
||||||
|
@ -349,10 +349,6 @@ div.CodeMirror span.eval-text {
|
|||||||
border-bottom: 1px solid #434850;
|
border-bottom: 1px solid #434850;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-tooltip-panel .devtools-tooltip-font-previewer-text {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-tooltip-panel .devtools-tooltip-simple-text:last-child {
|
.theme-tooltip-panel .devtools-tooltip-simple-text:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -358,10 +358,6 @@ div.CodeMirror span.eval-text {
|
|||||||
border-bottom: 1px solid #d9e1e8;
|
border-bottom: 1px solid #d9e1e8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-tooltip-panel .devtools-tooltip-font-previewer-text {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-tooltip-panel .devtools-tooltip-simple-text:last-child {
|
.theme-tooltip-panel .devtools-tooltip-simple-text:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,8 @@ const {Class} = require("sdk/core/heritage");
|
|||||||
const {PageStyleActor} = require("devtools/server/actors/styles");
|
const {PageStyleActor} = require("devtools/server/actors/styles");
|
||||||
const {HighlighterActor} = require("devtools/server/actors/highlighter");
|
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 PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||||
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
||||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
@ -351,6 +353,42 @@ var NodeActor = exports.NodeActor = protocol.ActorClass({
|
|||||||
modifications: Arg(0, "array:json")
|
modifications: Arg(0, "array:json")
|
||||||
},
|
},
|
||||||
response: {}
|
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