From d4aa6a7253327ff000a962e10a06505f6fde66dd Mon Sep 17 00:00:00 2001 From: Erik Demaine Date: Sun, 15 Jan 2017 19:05:21 -0500 Subject: [PATCH] Fix all AMS mathord symbols (#618) * Fix all AMS mathord symbols * Fix \imath, \jmath, \pounds support * Fix \mathit support * Fix Greek capitals * Default font to main (fix Unicode support) * Now using correct \maltese * Correct mathit documentation * var -> const * Add trailing commas * Remove greekCapitals (no longer needed) --- src/buildCommon.js | 101 ++++++++++-------- test/screenshotter/images/Symbols1-chrome.png | Bin 6420 -> 6470 bytes .../screenshotter/images/Symbols1-firefox.png | Bin 5519 -> 5569 bytes 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/buildCommon.js b/src/buildCommon.js index 47e02c9..4777342 100644 --- a/src/buildCommon.js +++ b/src/buildCommon.js @@ -9,27 +9,28 @@ const fontMetrics = require("./fontMetrics"); const symbols = require("./symbols"); const utils = require("./utils"); -const greekCapitals = [ - "\\Gamma", - "\\Delta", - "\\Theta", - "\\Lambda", - "\\Xi", - "\\Pi", - "\\Sigma", - "\\Upsilon", - "\\Phi", - "\\Psi", - "\\Omega", -]; - // The following have to be loaded from Main-Italic font, using class mainit const mainitLetters = [ - "\u0131", // dotless i, \imath - "\u0237", // dotless j, \jmath - "\u00a3", // \pounds + "\\imath", // dotless i + "\\jmath", // dotless j + "\\pounds", // pounds symbol ]; +/** + * Looks up the given symbol in fontMetrics, after applying any symbol + * replacements defined in symbol.js + */ +const lookupSymbol = function(value, fontFamily, mode) { + // Replace the value with its replaced value from symbol.js + if (symbols[mode][value] && symbols[mode][value].replace) { + value = symbols[mode][value].replace; + } + return { + value: value, + metrics: fontMetrics.getCharacterMetrics(value, fontFamily), + }; +}; + /** * Makes a symbolNode after translation via the list of symbols in symbols.js. * Correctly pulls out metrics for the character, and optionally takes a list of @@ -40,12 +41,9 @@ const mainitLetters = [ * should if present come first in `classes`. */ const makeSymbol = function(value, fontFamily, mode, options, classes) { - // Replace the value with its replaced value from symbol.js - if (symbols[mode][value] && symbols[mode][value].replace) { - value = symbols[mode][value].replace; - } - - const metrics = fontMetrics.getCharacterMetrics(value, fontFamily); + const lookup = lookupSymbol(value, fontFamily, mode); + const metrics = lookup.metrics; + value = lookup.value; let symbolNode; if (metrics) { @@ -100,29 +98,44 @@ const mathsym = function(value, mode, options, classes) { */ const mathDefault = function(value, mode, options, classes, type) { if (type === "mathord") { - return mathit(value, mode, options, classes); + const fontLookup = mathit(value, mode, options, classes); + return makeSymbol(value, fontLookup.fontName, mode, options, + classes.concat([fontLookup.fontClass])); } else if (type === "textord") { - return makeSymbol( - value, "Main-Regular", mode, options, classes.concat(["mathrm"])); + const font = symbols[mode][value] && symbols[mode][value].font; + if (font === "ams") { + return makeSymbol( + value, "AMS-Regular", mode, options, classes.concat(["amsrm"])); + } else { // if (font === "main") { + return makeSymbol( + value, "Main-Regular", mode, options, + classes.concat(["mathrm"])); + } } else { throw new Error("unexpected type: " + type + " in mathDefault"); } }; /** - * Makes a symbol in the italic math font. + * Determines which of the two font names (Main-Italic and Math-Italic) and + * corresponding style tags (mainit or mathit) to use for font "mathit", + * depending on the symbol. Use this function instead of fontMap for font + * "mathit". */ const mathit = function(value, mode, options, classes) { if (/[0-9]/.test(value.charAt(0)) || // glyphs for \imath and \jmath do not exist in Math-Italic so we // need to use Main-Italic instead - utils.contains(mainitLetters, value) || - utils.contains(greekCapitals, value)) { - return makeSymbol( - value, "Main-Italic", mode, options, classes.concat(["mainit"])); + utils.contains(mainitLetters, value)) { + return { + fontName: "Main-Italic", + fontClass: "mainit", + }; } else { - return makeSymbol( - value, "Math-Italic", mode, options, classes.concat(["mathit"])); + return { + fontName: "Math-Italic", + fontClass: "mathit", + }; } }; @@ -131,25 +144,23 @@ const mathit = function(value, mode, options, classes) { */ const makeOrd = function(group, options, type) { const mode = group.mode; - let value = group.value; - if (symbols[mode][value] && symbols[mode][value].replace) { - value = symbols[mode][value].replace; - } + const value = group.value; const classes = ["mord"]; const font = options.font; if (font) { + let fontLookup; if (font === "mathit" || utils.contains(mainitLetters, value)) { - return mathit(value, mode, options, classes); + fontLookup = mathit(value, mode, options, classes); } else { - const fontName = fontMap[font].fontName; - if (fontMetrics.getCharacterMetrics(value, fontName)) { - return makeSymbol( - value, fontName, mode, options, classes.concat([font])); - } else { - return mathDefault(value, mode, options, classes, type); - } + fontLookup = fontMap[font]; + } + if (lookupSymbol(value, fontLookup.fontName, mode).metrics) { + return makeSymbol(value, fontLookup.fontName, mode, options, + classes.concat([fontLookup.fontClass || font])); + } else { + return mathDefault(value, mode, options, classes, type); } } else { return mathDefault(value, mode, options, classes, type); diff --git a/test/screenshotter/images/Symbols1-chrome.png b/test/screenshotter/images/Symbols1-chrome.png index d2adc7c85e98836d60e8de2568e688177674bd34..49fd13f062ac568d42ccf95c31c37c5604452bd5 100644 GIT binary patch delta 4299 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 delta 3341 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 XVt$I@fq%;&00000NkvXXu0mjf3)l*4