Bug 1441622 - Expose the OpenType Font Variations data to the fonts redux store. r=pbro
authorGabriel Luong <gabriel.luong@gmail.com>
Thu, 01 Mar 2018 15:25:10 -0500
changeset 461135 2e915e01f05d02c2e39161733615af6f16982f29
parent 461134 01d017ee38c0491e353ead6d274e16d658a719f4
child 461136 cf67ac6f58d0fc08af06d9bd6f0247e9288e0568
child 461150 2667f0b010c959940d7a12b4311d54a6abd74ac5
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1441622
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1441622 - Expose the OpenType Font Variations data to the fonts redux store. r=pbro
devtools/client/inspector/fonts/fonts.js
devtools/client/inspector/fonts/types.js
devtools/server/actors/styles.js
devtools/shared/fronts/styles.js
devtools/shared/specs/styles.js
--- a/devtools/client/inspector/fonts/fonts.js
+++ b/devtools/client/inspector/fonts/fonts.js
@@ -1,23 +1,21 @@
 /* -*- indent-tabs-mode: nil; 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/. */
 
 "use strict";
 
+const { gDevTools } = require("devtools/client/framework/devtools");
 const { getColor } = require("devtools/client/shared/theme");
-
 const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
-const { gDevTools } = require("devtools/client/framework/devtools");
-
 const FontsApp = createFactory(require("./components/FontsApp"));
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 const INSPECTOR_L10N =
   new LocalizationHelper("devtools/client/locales/inspector.properties");
 
 const { updateFonts } = require("./actions/fonts");
 const { updatePreviewText } = require("./actions/font-options");
@@ -188,16 +186,21 @@ class FontInspector {
     }
 
     let options = {
       includePreviews: true,
       previewText,
       previewFillStyle: getColor("body-color")
     };
 
+    // Add the includeVariations argument into the option to get font variation data.
+    if (this.pageStyle.supportsFontVariations) {
+      options.includeVariations = true;
+    }
+
     fonts = await this.getFontsForNode(node, options);
     otherFonts = await this.getFontsNotInNode(fonts, options);
 
     if (!fonts.length && !otherFonts.length) {
       // No fonts to display. Clear the previously shown fonts.
       if (this.store) {
         this.store.dispatch(updateFonts(fonts, otherFonts));
       }
--- a/devtools/client/inspector/fonts/types.js
+++ b/devtools/client/inspector/fonts/types.js
@@ -2,16 +2,55 @@
  * 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 PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 /**
+ * A font variation axis.
+ */
+const fontVariationAxis = exports.fontVariationAxis = {
+  // The OpenType tag name of the variation axis
+  tag: PropTypes.string,
+
+  // The axis name of the variation axis
+  name: PropTypes.string,
+
+  // The minimum value of the variation axis
+  minValue: PropTypes.number,
+
+  // The maximum value of the variation axis
+  maxValue: PropTypes.number,
+
+  // The default value of the variation axis
+  defaultValue: PropTypes.number,
+};
+
+const fontVariationInstanceValue = exports.fontVariationInstanceValue = {
+  // The axis name of the variation axis
+  axis: PropTypes.string,
+
+  // The value of the variation axis
+  value: PropTypes.number,
+};
+
+/**
+ * A font variation instance.
+ */
+const fontVariationInstance = exports.fontVariationInstance = {
+  // The variation instance name of the font
+  axis: PropTypes.string,
+
+  // The font variation values for the variation instance of the font
+  values: PropTypes.arrayOf(PropTypes.shape(fontVariationInstanceValue)),
+};
+
+/**
  * A single font.
  */
 const font = exports.font = {
   // The format of the font
   format: PropTypes.string,
 
   // The name of the font
   name: PropTypes.string,
@@ -22,25 +61,31 @@ const font = exports.font = {
   // Object containing the CSS rule for the font
   rule: PropTypes.object,
 
   // The text of the CSS rule
   ruleText: PropTypes.string,
 
   // The URI of the font file
   URI: PropTypes.string,
+
+  // The variation axes of the font
+  variationAxes: PropTypes.arrayOf(PropTypes.shape(fontVariationAxis)),
+
+  // The variation instances of the font
+  variationInstances: PropTypes.arrayOf(PropTypes.shape(fontVariationInstance))
 };
 
 exports.fontOptions = {
   // The current preview text
   previewText: PropTypes.string,
 };
 
 /**
- * Font data
+ * Font data.
  */
 exports.fontData = {
   // The fonts used in the current element.
   fonts: PropTypes.arrayOf(PropTypes.shape(font)),
 
   // Fonts used elsewhere.
   otherFonts: PropTypes.arrayOf(PropTypes.shape(font)),
 };
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -1,15 +1,16 @@
 /* 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 {Ci} = require("chrome");
+const Services = require("Services");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const InspectorUtils = require("InspectorUtils");
 
 // This will also add the "stylesheet" actor type for protocol.js to recognize
 
 const {pageStyleSpec, styleRuleSpec, ELEMENT_STYLE} = require("devtools/shared/specs/styles");
 
@@ -24,16 +25,19 @@ loader.lazyRequireGetter(this, "parseNam
 loader.lazyRequireGetter(this, "UPDATE_PRESERVING_RULES",
   "devtools/server/actors/stylesheets", true);
 loader.lazyRequireGetter(this, "UPDATE_GENERAL",
   "devtools/server/actors/stylesheets", true);
 
 loader.lazyGetter(this, "PSEUDO_ELEMENTS", () => {
   return InspectorUtils.getCSSPseudoElementNames();
 });
+loader.lazyGetter(this, "FONT_VARIATIONS_ENABLED", () => {
+  return Services.prefs.getBoolPref("layout.css.font-variations.enabled");
+});
 
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 const FONT_PREVIEW_TEXT = "Abc";
 const FONT_PREVIEW_FONT_SIZE = 40;
 const FONT_PREVIEW_FILLSTYLE = "black";
 const NORMAL_FONT_WEIGHT = 400;
 const BOLD_FONT_WEIGHT = 700;
 // Offset (in px) to avoid cutting off text edges of italic fonts.
@@ -110,17 +114,20 @@ var PageStyleActor = protocol.ActorClass
       actor: this.actorID,
       traits: {
         // Whether the actor has had bug 1103993 fixed, which means that the
         // getApplied method calls cssLogic.highlight(node) to recreate the
         // style cache. Clients requesting getApplied from actors that have not
         // been fixed must make sure cssLogic.highlight(node) was called before.
         getAppliedCreatesStyleCache: true,
         // Whether addNewRule accepts the editAuthored argument.
-        authoredStyles: true
+        authoredStyles: true,
+        // Whether getAllUsedFontFaces/getUsedFontFaces accepts the includeVariations
+        // argument.
+        fontVariations: FONT_VARIATIONS_ENABLED,
       }
     };
   },
 
   /**
    * Called when a style sheet is updated.
    */
   _styleApplied: function (kind, styleSheet) {
@@ -315,16 +322,22 @@ var PageStyleActor = protocol.ActorClass
         };
         let { dataURL, size } = getFontPreviewData(font.CSSFamilyName,
                                                    contentDocument, opts);
         fontFace.preview = {
           data: LongStringActor(this.conn, dataURL),
           size: size
         };
       }
+
+      if (options.includeVariations && FONT_VARIATIONS_ENABLED) {
+        fontFace.variationAxes = font.getVariationAxes();
+        fontFace.variationInstances = font.getVariationInstances();
+      }
+
       fontsArray.push(fontFace);
     }
 
     // @font-face fonts at the top, then alphabetically, then by weight
     fontsArray.sort(function (a, b) {
       return a.weight > b.weight ? 1 : -1;
     });
     fontsArray.sort(function (a, b) {
--- a/devtools/shared/fronts/styles.js
+++ b/devtools/shared/fronts/styles.js
@@ -42,16 +42,20 @@ const PageStyleFront = FrontClassWithSpe
   get walker() {
     return this.inspector.walker;
   },
 
   get supportsAuthoredStyles() {
     return this._form.traits && this._form.traits.authoredStyles;
   },
 
+  get supportsFontVariations() {
+    return this._form.traits && this._form.traits.fontVariations;
+  },
+
   getMatchedSelectors: custom(function (node, property, options) {
     return this._getMatchedSelectors(node, property, options).then(ret => {
       return ret.matched;
     });
   }, {
     impl: "_getMatchedSelectors"
   }),
 
--- a/devtools/shared/specs/styles.js
+++ b/devtools/shared/specs/styles.js
@@ -53,26 +53,46 @@ types.addDictType("modifiedStylesReturn"
   ruleProps: RetVal("nullable:appliedStylesReturn")
 });
 
 types.addDictType("fontpreview", {
   data: "nullable:longstring",
   size: "json"
 });
 
+types.addDictType("fontvariationaxis", {
+  tag: "string",
+  name: "string",
+  minValue: "number",
+  maxValue: "number",
+  defaultValue: "number"
+});
+
+types.addDictType("fontvariationinstancevalue", {
+  axis: "string",
+  value: "number"
+});
+
+types.addDictType("fontvariationinstance", {
+  name: "string",
+  values: "array:fontvariationinstancevalue"
+});
+
 types.addDictType("fontface", {
   name: "string",
   CSSFamilyName: "string",
   rule: "nullable:domstylerule",
   srcIndex: "number",
   URI: "string",
   format: "string",
   preview: "nullable:fontpreview",
   localName: "string",
-  metadata: "string"
+  metadata: "string",
+  variationAxes: "array:fontvariationaxis",
+  variationInstances: "array:fontvariationinstance"
 });
 
 const pageStyleSpec = generateActorSpec({
   typeName: "pagestyle",
 
   events: {
     "stylesheet-updated": {
       type: "styleSheetUpdated",
@@ -90,28 +110,30 @@ const pageStyleSpec = generateActorSpec(
       },
       response: {
         computed: RetVal("json")
       }
     },
     getAllUsedFontFaces: {
       request: {
         includePreviews: Option(0, "boolean"),
+        includeVariations: Option(1, "boolean"),
         previewText: Option(0, "string"),
         previewFontSize: Option(0, "string"),
         previewFillStyle: Option(0, "string")
       },
       response: {
         fontFaces: RetVal("array:fontface")
       }
     },
     getUsedFontFaces: {
       request: {
         node: Arg(0, "domnode"),
         includePreviews: Option(1, "boolean"),
+        includeVariations: Option(1, "boolean"),
         previewText: Option(1, "string"),
         previewFontSize: Option(1, "string"),
         previewFillStyle: Option(1, "string")
       },
       response: {
         fontFaces: RetVal("array:fontface")
       }
     },