diff options
Diffstat (limited to 'devtools/client/inspector/fonts/reducers')
4 files changed, 223 insertions, 0 deletions
diff --git a/devtools/client/inspector/fonts/reducers/font-editor.js b/devtools/client/inspector/fonts/reducers/font-editor.js new file mode 100644 index 0000000000..b40fff4ba1 --- /dev/null +++ b/devtools/client/inspector/fonts/reducers/font-editor.js @@ -0,0 +1,157 @@ +/* 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 { + getStr, +} = require("resource://devtools/client/inspector/fonts/utils/l10n.js"); +const { + parseFontVariationAxes, +} = require("resource://devtools/client/inspector/fonts/utils/font-utils.js"); + +const { + APPLY_FONT_VARIATION_INSTANCE, + RESET_EDITOR, + SET_FONT_EDITOR_DISABLED, + UPDATE_AXIS_VALUE, + UPDATE_EDITOR_STATE, + UPDATE_PROPERTY_VALUE, + UPDATE_WARNING_MESSAGE, +} = require("resource://devtools/client/inspector/fonts/actions/index.js"); + +const CUSTOM_INSTANCE_NAME = getStr("fontinspector.customInstanceName"); + +const INITIAL_STATE = { + // Variable font axes. + axes: {}, + // Copy of the most recent axes values. Used to revert from a named instance. + customInstanceValues: [], + // When true, prevent users from interacting with inputs in the font editor. + disabled: false, + // Fonts used on the selected element. + fonts: [], + // Current selected font variation instance. + instance: { + name: CUSTOM_INSTANCE_NAME, + values: [], + }, + // CSS font properties defined on the selected rule. + properties: {}, + // Unique identifier for the selected element. + id: "", + // Warning message with the reason why the font editor cannot be shown. + warning: getStr("fontinspector.noFontsUsedOnCurrentElement"), +}; + +const reducers = { + // Update font editor with the axes and values defined by a font variation instance. + [APPLY_FONT_VARIATION_INSTANCE](state, { name, values }) { + const newState = { ...state }; + newState.instance.name = name; + newState.instance.values = values; + + if (Array.isArray(values) && values.length) { + newState.axes = values.reduce((acc, value) => { + acc[value.axis] = value.value; + return acc; + }, {}); + } + + return newState; + }, + + [RESET_EDITOR](state) { + return { ...INITIAL_STATE }; + }, + + [UPDATE_AXIS_VALUE](state, { axis, value }) { + const newState = { ...state }; + newState.axes[axis] = value; + + // Cache the latest axes and their values to restore them when switching back from + // a named font variation instance to the custom font variation instance. + newState.customInstanceValues = Object.keys(state.axes).map(axisName => { + return { axis: [axisName], value: state.axes[axisName] }; + }); + + // As soon as an axis value is manually updated, mark the custom font variation + // instance as selected. + newState.instance.name = CUSTOM_INSTANCE_NAME; + + return newState; + }, + + [SET_FONT_EDITOR_DISABLED](state, { disabled }) { + return { ...state, disabled }; + }, + + [UPDATE_EDITOR_STATE](state, { fonts, properties, id }) { + const axes = parseFontVariationAxes(properties["font-variation-settings"]); + + // If not defined in font-variation-settings, setup "wght" axis with the value of + // "font-weight" if it is numeric and not a keyword. + const weight = properties["font-weight"]; + if ( + axes.wght === undefined && + parseFloat(weight).toString() === weight.toString() + ) { + axes.wght = parseFloat(weight); + } + + // If not defined in font-variation-settings, setup "wdth" axis with the percentage + // number from the value of "font-stretch" if it is not a keyword. + const stretch = properties["font-stretch"]; + // Match the number part from values like: 10%, 10.55%, 0.2% + // If there's a match, the number is the second item in the match array. + const match = stretch.trim().match(/^(\d+(.\d+)?)%$/); + if (axes.wdth === undefined && match && match[1]) { + axes.wdth = parseFloat(match[1]); + } + + // If not defined in font-variation-settings, setup "slnt" axis with the negative + // of the "font-style: oblique" angle, if any. + const style = properties["font-style"]; + const obliqueMatch = style.trim().match(/^oblique(?:\s*(\d+(.\d+)?)deg)?$/); + if (axes.slnt === undefined && obliqueMatch) { + if (obliqueMatch[1]) { + // Negate the angle because CSS and OpenType measure in opposite directions. + axes.slnt = -parseFloat(obliqueMatch[1]); + } else { + // Lack of an <angle> for "font-style: oblique" represents "14deg". + axes.slnt = -14; + } + } + + // If not defined in font-variation-settings, setup "ital" axis with 0 for + // "font-style: normal" or 1 for "font-style: italic". + if (axes.ital === undefined) { + if (style === "normal") { + axes.ital = 0; + } else if (style === "italic") { + axes.ital = 1; + } + } + + return { ...state, axes, fonts, properties, id }; + }, + + [UPDATE_PROPERTY_VALUE](state, { property, value }) { + const newState = { ...state }; + newState.properties[property] = value; + return newState; + }, + + [UPDATE_WARNING_MESSAGE](state, { warning }) { + return { ...state, warning }; + }, +}; + +module.exports = function (state = INITIAL_STATE, action) { + const reducer = reducers[action.type]; + if (!reducer) { + return state; + } + return reducer(state, action); +}; diff --git a/devtools/client/inspector/fonts/reducers/font-options.js b/devtools/client/inspector/fonts/reducers/font-options.js new file mode 100644 index 0000000000..9df8625e56 --- /dev/null +++ b/devtools/client/inspector/fonts/reducers/font-options.js @@ -0,0 +1,27 @@ +/* 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 { + UPDATE_PREVIEW_TEXT, +} = require("resource://devtools/client/inspector/fonts/actions/index.js"); + +const INITIAL_FONT_OPTIONS = { + previewText: "", +}; + +const reducers = { + [UPDATE_PREVIEW_TEXT](fontOptions, { previewText }) { + return Object.assign({}, fontOptions, { previewText }); + }, +}; + +module.exports = function (fontOptions = INITIAL_FONT_OPTIONS, action) { + const reducer = reducers[action.type]; + if (!reducer) { + return fontOptions; + } + return reducer(fontOptions, action); +}; diff --git a/devtools/client/inspector/fonts/reducers/fonts.js b/devtools/client/inspector/fonts/reducers/fonts.js new file mode 100644 index 0000000000..92a6ef87c1 --- /dev/null +++ b/devtools/client/inspector/fonts/reducers/fonts.js @@ -0,0 +1,28 @@ +/* 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 { + UPDATE_FONTS, +} = require("resource://devtools/client/inspector/fonts/actions/index.js"); + +const INITIAL_FONT_DATA = { + // All fonts on the current page. + allFonts: [], +}; + +const reducers = { + [UPDATE_FONTS](_, { allFonts }) { + return { allFonts }; + }, +}; + +module.exports = function (fontData = INITIAL_FONT_DATA, action) { + const reducer = reducers[action.type]; + if (!reducer) { + return fontData; + } + return reducer(fontData, action); +}; diff --git a/devtools/client/inspector/fonts/reducers/moz.build b/devtools/client/inspector/fonts/reducers/moz.build new file mode 100644 index 0000000000..13d1c7cf34 --- /dev/null +++ b/devtools/client/inspector/fonts/reducers/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + "font-editor.js", + "font-options.js", + "fonts.js", +) |