From ec62ec39d82b6b42ee2ec9ad866a79c56b8e2990 Mon Sep 17 00:00:00 2001 From: Kevin Barabash Date: Mon, 1 Aug 2016 17:51:40 -0700 Subject: [PATCH] Add support for Latin-1, Cyrillic, and CJK characters inside \text{} (#508) Summary: This diff provides support for Latin-1, Cyrillic, and CJK characters inside \text{} groups. For Latin-1 and Cyrillic characters we use glyph metrics from a glyph from Basic Latin that has roughly the same bounding box. We use the metrics for a capital 'M' to approximate the full-width CJK characters. Half-width characters are not supported yet. Test Plan: - make test - make screenshots Reviewers: emily --- .gitignore | 1 + .travis.yml | 1 + Makefile | 8 +- server.js | 2 + src/Parser.js | 6 + src/domTree.js | 29 +++- src/fontMetrics.js | 148 +++++++++++++++++- src/symbols.js | 22 +++ src/unicodeRegexes.js | 15 ++ static/katex.less | 2 +- test/screenshotter/images/Unicode-chrome.png | Bin 0 -> 25212 bytes test/screenshotter/images/Unicode-firefox.png | Bin 0 -> 24792 bytes test/screenshotter/ss_data.yaml | 1 + test/screenshotter/test.html | 14 ++ test/unicode-spec.js | 103 ++++++++++++ 15 files changed, 348 insertions(+), 4 deletions(-) create mode 100644 src/unicodeRegexes.js create mode 100644 test/screenshotter/images/Unicode-chrome.png create mode 100644 test/screenshotter/images/Unicode-firefox.png create mode 100644 test/unicode-spec.js diff --git a/.gitignore b/.gitignore index 058d8cf4..ddaaa933 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ diff.png /test/symgroups.aux /test/symgroups.log /test/symgroups.pdf +/test/screenshotter/unicode-fonts diff --git a/.travis.yml b/.travis.yml index 4228096c..5b6e2880 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,5 @@ before_script: - docker images --no-trunc script: - npm test + - git clone https://github.com/Khan/KaTeX-test-fonts test/screenshotter/unicode-fonts - dockers/Screenshotter/screenshotter.sh --verify diff --git a/Makefile b/Makefile index 546cbaa1..03d3d959 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,12 @@ build/fonts: cp static/fonts/$$font* $@; \ done +test/screenshotter/unicode-fonts: + git clone https://github.com/Khan/KaTeX-test-fonts test/screenshotter/unicode-fonts + cd test/screenshotter/unicode-fonts && \ + git checkout 99fa66a2da643218754c8236b9f9151cac71ba7c && \ + cd ../../../ + contrib: build/contrib .PHONY: build/contrib @@ -90,5 +96,5 @@ extended_metrics: clean: rm -rf build/* -screenshots: +screenshots: test/screenshotter/unicode-fonts dockers/Screenshotter/screenshotter.sh diff --git a/server.js b/server.js index a6213449..08eacf1f 100644 --- a/server.js +++ b/server.js @@ -81,6 +81,8 @@ app.use(express["static"](path.join(__dirname, "static"))); app.use(express["static"](path.join(__dirname, "build"))); app.use("/test", express["static"](path.join(__dirname, "test"))); app.use("/contrib", express["static"](path.join(__dirname, "contrib"))); +// app.use("/unicode-fonts", +// express["static"](path.join(__dirname, "static", "unicode-fonts"))); app.use(function(err, req, res, next) { console.error(err.stack); diff --git a/src/Parser.js b/src/Parser.js index 4bfde913..97bbbf3f 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -4,6 +4,7 @@ var environments = require("./environments"); var MacroExpander = require("./MacroExpander"); var symbols = require("./symbols"); var utils = require("./utils"); +var cjkRegex = require("./unicodeRegexes").cjkRegex; var parseData = require("./parseData"); var ParseError = require("./ParseError"); @@ -794,6 +795,11 @@ Parser.prototype.parseSymbol = function() { new ParseNode(symbols[this.mode][nucleus.text].group, nucleus.text, this.mode, nucleus), false, nucleus); + } else if (this.mode === "text" && cjkRegex.test(nucleus.text)) { + this.consume(); + return new ParseFuncOrArgument( + new ParseNode("textord", nucleus.text, this.mode, nucleus), + false, nucleus); } else { return null; } diff --git a/src/domTree.js b/src/domTree.js index e0d8e925..46b515ea 100644 --- a/src/domTree.js +++ b/src/domTree.js @@ -7,7 +7,7 @@ * * Similar functions for working with MathML nodes exist in mathMLTree.js. */ - +var unicodeRegexes = require("./unicodeRegexes"); var utils = require("./utils"); /** @@ -169,6 +169,14 @@ documentFragment.prototype.toMarkup = function() { return markup; }; +var iCombinations = { + 'î': '\u0131\u0302', + 'ï': '\u0131\u0308', + 'í': '\u0131\u0301', + // 'ī': '\u0131\u0304', // enable when we add Extended Latin + 'ì': '\u0131\u0300', +}; + /** * A symbol node contains information about a single symbol. It either renders * to a single text node, or a span with a single text node in it, depending on @@ -183,6 +191,25 @@ function symbolNode(value, height, depth, italic, skew, classes, style) { this.classes = classes || []; this.style = style || {}; this.maxFontSize = 0; + + // Mark CJK characters with specific classes so that we can specify which + // fonts to use. This allows us to render these characters with a serif + // font in situations where the browser would either default to a sans serif + // or render a placeholder character. + if (unicodeRegexes.cjkRegex.test(value)) { + // I couldn't find any fonts that contained Hangul as well as all of + // the other characters we wanted to test there for it gets its own + // CSS class. + if (unicodeRegexes.hangulRegex.test(value)) { + this.classes.push('hangul_fallback'); + } else { + this.classes.push('cjk_fallback'); + } + } + + if (/[îïíì]/.test(this.value)) { // add ī when we add Extended Latin + this.value = iCombinations[this.value]; + } } /** diff --git a/src/fontMetrics.js b/src/fontMetrics.js index db9e44bf..e4e440a7 100644 --- a/src/fontMetrics.js +++ b/src/fontMetrics.js @@ -1,6 +1,7 @@ /* eslint no-unused-vars:0 */ var Style = require("./Style"); +var cjkRegex = require("./unicodeRegexes").cjkRegex; /** * This file contains metrics regarding fonts and individual symbols. The sigma @@ -121,6 +122,145 @@ var metrics = { // This map is generated via `make metrics`. It should not be changed manually. var metricMap = require("./fontMetricsData"); +// These are very rough approximations. We default to Times New Roman which +// should have Latin-1 and Cyrillic characters, but may not depending on the +// operating system. The metrics do not account for extra height from the +// accents. In the case of Cyrillic characters which have both ascenders and +// descenders we prefer approximations with ascenders, primarily to prevent +// the fraction bar or root line from intersecting the glyph. +// TODO(kevinb) allow union of multiple glyph metrics for better accuracy. +var extraCharacterMap = { + // Latin-1 + 'À': 'A', + 'Á': 'A', + 'Â': 'A', + 'Ã': 'A', + 'Ä': 'A', + 'Å': 'A', + 'Æ': 'A', + 'Ç': 'C', + 'È': 'E', + 'É': 'E', + 'Ê': 'E', + 'Ë': 'E', + 'Ì': 'I', + 'Í': 'I', + 'Î': 'I', + 'Ï': 'I', + 'Ð': 'D', + 'Ñ': 'N', + 'Ò': 'O', + 'Ó': 'O', + 'Ô': 'O', + 'Õ': 'O', + 'Ö': 'O', + 'Ø': 'O', + 'Ù': 'U', + 'Ú': 'U', + 'Û': 'U', + 'Ü': 'U', + 'Ý': 'Y', + 'Þ': 'o', + 'ß': 'B', + 'à': 'a', + 'á': 'a', + 'â': 'a', + 'ã': 'a', + 'ä': 'a', + 'å': 'a', + 'æ': 'a', + 'ç': 'c', + 'è': 'e', + 'é': 'e', + 'ê': 'e', + 'ë': 'e', + 'ì': 'i', + 'í': 'i', + 'î': 'i', + 'ï': 'i', + 'ð': 'd', + 'ñ': 'n', + 'ò': 'o', + 'ó': 'o', + 'ô': 'o', + 'õ': 'o', + 'ö': 'o', + 'ø': 'o', + 'ù': 'u', + 'ú': 'u', + 'û': 'u', + 'ü': 'u', + 'ý': 'y', + 'þ': 'o', + 'ÿ': 'y', + + // Cyrillic + 'А': 'A', + 'Б': 'B', + 'В': 'B', + 'Г': 'F', + 'Д': 'A', + 'Е': 'E', + 'Ж': 'K', + 'З': '3', + 'И': 'N', + 'Й': 'N', + 'К': 'K', + 'Л': 'N', + 'М': 'M', + 'Н': 'H', + 'О': 'O', + 'П': 'N', + 'Р': 'P', + 'С': 'C', + 'Т': 'T', + 'У': 'y', + 'Ф': 'O', + 'Х': 'X', + 'Ц': 'U', + 'Ч': 'h', + 'Ш': 'W', + 'Щ': 'W', + 'Ъ': 'B', + 'Ы': 'X', + 'Ь': 'B', + 'Э': '3', + 'Ю': 'X', + 'Я': 'R', + 'а': 'a', + 'б': 'b', + 'в': 'a', + 'г': 'r', + 'д': 'y', + 'е': 'e', + 'ж': 'm', + 'з': 'e', + 'и': 'n', + 'й': 'n', + 'к': 'n', + 'л': 'n', + 'м': 'm', + 'н': 'n', + 'о': 'o', + 'п': 'n', + 'р': 'p', + 'с': 'c', + 'т': 'o', + 'у': 'y', + 'ф': 'b', + 'х': 'x', + 'ц': 'n', + 'ч': 'n', + 'ш': 'w', + 'щ': 'w', + 'ъ': 'a', + 'ы': 'm', + 'ь': 'a', + 'э': 'e', + 'ю': 'm', + 'я': 'r', +}; + /** * This function is a convenience function for looking up information in the * metricMap table. It takes a character as a string, and a style. @@ -129,7 +269,13 @@ var metricMap = require("./fontMetricsData"); * built using `Make extended_metrics`. */ var getCharacterMetrics = function(character, style) { - var metrics = metricMap[style][character.charCodeAt(0)]; + var ch = character.charCodeAt(0); + if (character[0] in extraCharacterMap) { + ch = extraCharacterMap[character[0]].charCodeAt(0); + } else if (cjkRegex.test(character[0])) { + ch = 'M'.charCodeAt(0); + } + var metrics = metricMap[style][ch]; if (metrics) { return { depth: metrics[0], diff --git a/src/symbols.js b/src/symbols.js index aef7c874..55301a4e 100644 --- a/src/symbols.js +++ b/src/symbols.js @@ -630,3 +630,25 @@ for (i = 0; i < letters.length; i++) { defineSymbol(math, main, mathord, ch, ch); defineSymbol(text, main, textord, ch, ch); } + +// Latin-1 letters +for (i = 0x00C0; i <= 0x00D6; i++) { + ch = String.fromCharCode(i); + defineSymbol(text, main, textord, ch, ch); +} + +for (i = 0x00D8; i <= 0x00F6; i++) { + ch = String.fromCharCode(i); + defineSymbol(text, main, textord, ch, ch); +} + +for (i = 0x00F8; i <= 0x00FF; i++) { + ch = String.fromCharCode(i); + defineSymbol(text, main, textord, ch, ch); +} + +// Cyrillic +for (i = 0x0410; i <= 0x044F; i++) { + ch = String.fromCharCode(i); + defineSymbol(text, main, textord, ch, ch); +} diff --git a/src/unicodeRegexes.js b/src/unicodeRegexes.js new file mode 100644 index 00000000..a05d7cd5 --- /dev/null +++ b/src/unicodeRegexes.js @@ -0,0 +1,15 @@ +var hangulRegex = /[\uAC00-\uD7AF]/; + +// This regex combines +// - Hiragana: [\u3040-\u309F] +// - Katakana: [\u30A0-\u30FF] +// - CJK ideograms: [\u4E00-\u9FAF] +// - Hangul syllables: [\uAC00-\uD7AF] +// Notably missing are halfwidth Katakana and Romanji glyphs. +var cjkRegex = + /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/; + +module.exports = { + cjkRegex: cjkRegex, + hangulRegex: hangulRegex, +}; diff --git a/static/katex.less b/static/katex.less index b7c8f84d..8b11048a 100644 --- a/static/katex.less +++ b/static/katex.less @@ -15,7 +15,7 @@ } .katex { - font: normal 1.21em KaTeX_Main; + font: normal 1.21em KaTeX_Main, Times New Roman, serif; line-height: 1.2; white-space: nowrap; diff --git a/test/screenshotter/images/Unicode-chrome.png b/test/screenshotter/images/Unicode-chrome.png new file mode 100644 index 0000000000000000000000000000000000000000..6d7472f4a94d7566034152468d5a4ca4d9aa6a8a GIT binary patch literal 25212 zcmeAS@N?(olHy`uVBq!ia0y~yU}0cjU}oT8U|?XFf6?nA14ELtr;B4q#hkZuD;M~= z${&BOx2|^j+Bd(2yk>8j8Wc1w$U{ZcbFZ$KVBohFuP!fc*Gy$srBiZBu8TBM?#KR) zo%j9BOw04d(=2Zn&wo9y`uXpli{H(hX?)(Mzu4~i982TKRvK*7%IC5;(<^K{Ysw4;ZiSz6bql7R3!6Uc-=3?y|4zM{mcn(| zqs4vmE<=UGED;O~FD$Wn+BHkyzpX@*7#O+Vzx!G=a zmvkj3y*{_L^``v^(Kq##VaK4<*xmgFTOkfzQSykbnuO1d*^+hcc82y;I4<}vb-l&61mZ9mTV7QowM8j z=kJX0ukY2K$9`vWRQtfhv3BK>dBKr)dHnzQS?hkPmH7JaH_!QNdvCb$p5I-bWPK&v z-0br%F_*hi+|C)bu3OfduU5JHMtJutM=^mK#+JTqi`j22kG#vnKWE)ylP%Ylz0kH0 zJnnaE=BsO$a~>C+-)(=QY)9DLAN|}3u3yd?8qVJK?pf@^x6QAl4}MPyvp>PKsgc2H zVd2gx+~@a4-sLKn3p>}oPO>T@F_z=!jojZ-*B<|CdcLn&hNq+WnF{>-(;*Qlp6kKDR_8Nj)_BdU+S90y+CmXD*_4xDuUf6rMB3`!Z^ZVVezkXn7ab~_{|0~)}S|st-gYPWwMV9l= zliA(RAU-EYsbS8kmD7K;v`c)u%HI9-4|m^z*G&$Sl36~8zW=PXL3MTXqxO4yuBzN> zWOhtX=X@(|H}9%1qf${1!?u`1{9D*=X7IeTx%ceHL{Kt+bmywdne@oJ5()~(ITT7> znAI()tTWzQ|Mt!Hc-gOyHe6g^Z%}>q-IX&rb7mY)jqL8Om)~u5d7J)B!;e!F4;qiADjMq$e5j*86#JD_-53G{okvf2N%olSKD8AeUdqUwDjMU2Ck-KGwv1fm_9c* zNjY!uXbRXnn->I*q?puj8m+ZL>A+^`*}XtD{0MOHF$%IQ#dka-perifS_M%Uzwf z{>7&6|4n|bycQ}{q1(FtmD!)qy~`3^)9ZfMJo$Tl<@cb@tG8`FzuV-z>&)bwR{>8& z7aI3(RP4*Q{y*=*A>j(fJF8@`|Fq@ps0`*+{II6B(YgHduP*x!sZS(-KKW!G_57LS z`ky%unfAp$*Gqes6?-y{;idV7xu?3`nP2-L)&J@36{(!v4701JpVMFQQ~9m^SA+XY z|8So^{LT9J;mhJ1uQ81ir}vw+^vZs5z6;?xvvEmTSoxm! zEPt!xGOzmHObc6X!V=5CE_^sVD8D$z>`F-2vD)+VvF*dQ<0tdHZcZ{Y z-z)#=_M_!T{|0iu4F1b8-?v2QfK@bO&Z6n}|98$0J;O9(<=l_VSI+8hIa_D*KRj=1 zHLJO2dtO?l@7m?}3Z_l&&i(kjFZ}G%MWP3^q8{>2T3uO1! zr?w~j(fj^LOa4iCpUp$>X8s6Y&u{CObPIf1bY9JhQ{ko`!*l&`xsUdnR$lzZ*Wi0J za$&At!p;AmKG$#9uxU$sL|*afH49R8n){#bpO`yyx7cFQ0}G2zz0c`!|B~*!^u}qw zuMOOO2UtJ&&-o-!xl6&C&9;Bq&&~5HGVa!VvzcgdyDr?-g1L6vMNfu>MrKSi7T@8! z?I*M03u8#i?VsPJ%|36uJ?HWs?*s2j6Rr9m-#$C(vh!clAE#S=UsyN9Ig4TNZOElzZ!1-|Nry zzE0V?TEUA^N6sefL$i*g&5f0E1qV5IFuc<0|E#(2{ZGz~YROYSE^P9h({{{9;fd$` zt5#eO8Z(?eMX(6my0kZG-?E3nreBWBwtl|5VangVv-Te9DSwghzb!QU&4gOP>P7Y3 z44W7aiXC8E)c3|$`!L_3<3=Gjx38JBBYqB-?kD-T_W~IfCn+NB zPd({OD`H@ou$XfT!==;0LG$iy_WqHpBHyV9KSYAJW
%o&>Ur*Y- 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 literal 0 HcmV?d00001 diff --git a/test/screenshotter/ss_data.yaml b/test/screenshotter/ss_data.yaml index 4f2ce6d6..59bc5bd6 100644 --- a/test/screenshotter/ss_data.yaml +++ b/test/screenshotter/ss_data.yaml @@ -114,6 +114,7 @@ Symbols1: | \maltese\degree\pounds\$ \text{\maltese\degree} Text: \frac{a}{b}\text{c~ {ab} \ e}+fg +Unicode: \begin{matrix}\text{ÀàÇçÉéÏïÖöÛû} \\ \text{БГДЖЗЙЛФЦШЫЮЯ} \\ \text{여보세요} \\ \text{私はバナナです} \end{matrix} UnsupportedCmds: tex: \err\,\frac\fracerr3\,2^\superr_\suberr\,\sqrt\sqrterr noThrow: 1 diff --git a/test/screenshotter/test.html b/test/screenshotter/test.html index 4da2a8b8..3694ba98 100644 --- a/test/screenshotter/test.html +++ b/test/screenshotter/test.html @@ -11,6 +11,20 @@ body { font-family: "DejaVu Serif",serif; } + @font-face { + font-family: "Mincho"; + src: url("unicode-fonts/mincho/font_1_honokamin.ttf") format("truetype"); + } + @font-face { + font-family: "Batang"; + src: url("unicode-fonts/batang/batang.ttf") format("truetype"); + } + .katex .cjk_fallback { + font-family: "Mincho",serif; + } + .katex .hangul_fallback { + font-family: "Batang",serif; + } diff --git a/test/unicode-spec.js b/test/unicode-spec.js new file mode 100644 index 00000000..a78a83aa --- /dev/null +++ b/test/unicode-spec.js @@ -0,0 +1,103 @@ +/* eslint max-len:0 */ +/* global beforeEach: false */ +/* global jasmine: false */ +/* global expect: false */ +/* global it: false */ +/* global describe: false */ +var ParseError = require("../src/ParseError"); +var parseTree = require("../src/parseTree"); +var Settings = require("../src/Settings"); + +var defaultSettings = new Settings({}); + +var parseAndSetResult = function(expr, result, settings) { + try { + return parseTree(expr, settings || defaultSettings); + } catch (e) { + result.pass = false; + if (e instanceof ParseError) { + result.message = "'" + expr + "' failed " + + "parsing with error: " + e.message; + } else { + result.message = "'" + expr + "' failed " + + "parsing with unknown error: " + e.message; + } + } +}; + +describe("unicode", function() { + beforeEach(function() { + jasmine.addMatchers({ + + toParse: function() { + return { + compare: function(actual, settings) { + var usedSettings = settings ? settings : defaultSettings; + + var result = { + pass: true, + message: "'" + actual + "' succeeded parsing", + }; + parseAndSetResult(actual, result, usedSettings); + return result; + }, + }; + }, + + toNotParse: function() { + return { + compare: function(actual, settings) { + var usedSettings = settings ? settings : defaultSettings; + + var result = { + pass: false, + message: "Expected '" + actual + "' to fail " + + "parsing, but it succeeded", + }; + + try { + parseTree(actual, usedSettings); + } catch (e) { + if (e instanceof ParseError) { + result.pass = true; + result.message = "'" + actual + "' correctly " + + "didn't parse with error: " + e.message; + } else { + result.message = "'" + actual + "' failed " + + "parsing with unknown error: " + e.message; + } + } + + return result; + }, + }; + }, + }); + }); + + it("should parse Latin-1 inside \\text{}", function() { + expect('\\text{ÀàÇçÉéÏïÖöÛû}').toParse(); + }); + + it("should not parse Latin-1 outside \\text{}", function() { + expect('ÀàÇçÉéÏïÖöÛû').toNotParse(); + }); + + it("should parse Cyrillic inside \\text{}", function() { + expect('\\text{БГДЖЗЙЛФЦШЫЮЯ}').toParse(); + }); + + it("should not parse Cyrillic outside \\text{}", function() { + expect('БГДЖЗЙЛФЦШЫЮЯ').toNotParse(); + }); + + it("should parse CJK inside \\text{}", function() { + expect('\\text{私はバナナです}').toParse(); + expect('\\text{여보세요}').toParse(); + }); + + it("should not parse CJK outside \\text{}", function() { + expect('私はバナナです。').toNotParse(); + expect('여보세요').toNotParse(); + }); +});