From 006a0a761c59a99acbfc2ce48ce717dae1e76a6b Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Tue, 14 Oct 2014 17:01:19 -0700 Subject: [PATCH] Add support for \{,d,t}binom Test Plan: `\binom xy^{\binom xy^{\binom xy}}` looks like something. `\dbinom` and `\tbinom` also seem to work. Reviewers: emily Reviewed By: emily Subscribers: jessie Differential Revision: http://phabricator.khanacademy.org/D13315 --- src/buildTree.js | 138 +++++++++++++----- src/fontMetrics.js | 24 ++- src/functions.js | 45 +++++- test/huxley/Huxleyfile.json | 6 + .../Huxleyfolder/BinomTest.hux/firefox-1.png | Bin 0 -> 24093 bytes .../huxley/Huxleyfolder/BinomTest.record.json | 5 + 6 files changed, 171 insertions(+), 47 deletions(-) create mode 100644 test/huxley/Huxleyfolder/BinomTest.hux/firefox-1.png create mode 100644 test/huxley/Huxleyfolder/BinomTest.record.json diff --git a/src/buildTree.js b/src/buildTree.js index cbdf0525d..1939331b3 100644 --- a/src/buildTree.js +++ b/src/buildTree.js @@ -364,14 +364,14 @@ var groupTypes = { [base, supsub]); }, - frac: function(group, options, prev) { + genfrac: function(group, options, prev) { // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e). // Figure out what style this fraction should be in based on the // function used var fstyle = options.style; - if (group.value.size === "dfrac") { + if (group.value.size === "display") { fstyle = Style.DISPLAY; - } else if (group.value.size === "tfrac") { + } else if (group.value.size === "text") { fstyle = Style.TEXT; } @@ -384,60 +384,118 @@ var groupTypes = { var denom = buildGroup(group.value.denom, options.withStyle(dstyle)); var denomreset = makeSpan([fstyle.reset(), dstyle.cls()], [denom]); - var ruleWidth = fontMetrics.metrics.defaultRuleThickness / - options.style.sizeMultiplier; + var ruleWidth; + if (group.value.hasBarLine) { + ruleWidth = fontMetrics.metrics.defaultRuleThickness / + options.style.sizeMultiplier; + } else { + ruleWidth = 0; + } - var mid = makeSpan( - [options.style.reset(), Style.TEXT.cls(), "frac-line"]); - // Manually set the height of the line because its height is created in - // CSS - mid.height = ruleWidth; - - // Rule 15b, 15d - var numShift, denomShift, clearance; + // Rule 15b + var numShift; + var clearance; + var denomShift; if (fstyle.size === Style.DISPLAY.size) { numShift = fontMetrics.metrics.num1; + if (ruleWidth > 0) { + clearance = 3 * ruleWidth; + } else { + clearance = 7 * fontMetrics.metrics.defaultRuleThickness; + } denomShift = fontMetrics.metrics.denom1; - clearance = 3 * ruleWidth; } else { - numShift = fontMetrics.metrics.num2; + if (ruleWidth > 0) { + numShift = fontMetrics.metrics.num2; + clearance = ruleWidth; + } else { + numShift = fontMetrics.metrics.num3; + clearance = 3 * fontMetrics.metrics.defaultRuleThickness; + } denomShift = fontMetrics.metrics.denom2; - clearance = ruleWidth; } - var axisHeight = fontMetrics.metrics.axisHeight; + var frac; + if (ruleWidth === 0) { + // Rule 15c + var candiateClearance = + (numShift - numer.depth) - (denom.height - denomShift); + if (candiateClearance < clearance) { + numShift += 0.5 * (clearance - candiateClearance); + denomShift += 0.5 * (clearance - candiateClearance); + } - // Rule 15d - if ((numShift - numer.depth) - (axisHeight + 0.5 * ruleWidth) - < clearance) { - numShift += - clearance - ((numShift - numer.depth) - - (axisHeight + 0.5 * ruleWidth)); + frac = buildCommon.makeVList([ + {type: "elem", elem: denomreset, shift: denomShift}, + {type: "elem", elem: numerreset, shift: -numShift} + ], "individualShift", null, options); + } else { + // Rule 15d + var axisHeight = fontMetrics.metrics.axisHeight; + + if ((numShift - numer.depth) - (axisHeight + 0.5 * ruleWidth) + < clearance) { + numShift += + clearance - ((numShift - numer.depth) - + (axisHeight + 0.5 * ruleWidth)); + } + + if ((axisHeight - 0.5 * ruleWidth) - (denom.height - denomShift) + < clearance) { + denomShift += + clearance - ((axisHeight - 0.5 * ruleWidth) - + (denom.height - denomShift)); + } + + var mid = makeSpan( + [options.style.reset(), Style.TEXT.cls(), "frac-line"]); + // Manually set the height of the line because its height is + // created in CSS + mid.height = ruleWidth; + + var midShift = -(axisHeight - 0.5 * ruleWidth); + + frac = buildCommon.makeVList([ + {type: "elem", elem: denomreset, shift: denomShift}, + {type: "elem", elem: mid, shift: midShift}, + {type: "elem", elem: numerreset, shift: -numShift} + ], "individualShift", null, options); } - if ((axisHeight - 0.5 * ruleWidth) - (denom.height - denomShift) - < clearance) { - denomShift += - clearance - ((axisHeight - 0.5 * ruleWidth) - - (denom.height - denomShift)); - } - - var midShift = -(axisHeight - 0.5 * ruleWidth); - - var frac = buildCommon.makeVList([ - {type: "elem", elem: denomreset, shift: denomShift}, - {type: "elem", elem: mid, shift: midShift}, - {type: "elem", elem: numerreset, shift: -numShift} - ], "individualShift", null, options); - // Since we manually change the style sometimes (with \dfrac or \tfrac), // account for the possible size change here. frac.height *= fstyle.sizeMultiplier / options.style.sizeMultiplier; frac.depth *= fstyle.sizeMultiplier / options.style.sizeMultiplier; + // Rule 15e + var innerChildren = [makeSpan(["mfrac"], [frac])]; + + var delimSize; + if (fstyle.size === Style.DISPLAY.size) { + delimSize = fontMetrics.metrics.delim1; + } else { + delimSize = fontMetrics.metrics.getDelim2(fstyle); + } + + if (group.value.leftDelim != null) { + innerChildren.unshift( + delimiter.customSizedDelim( + group.value.leftDelim, delimSize, true, + options.withStyle(fstyle), group.mode) + ); + } + if (group.value.rightDelim != null) { + innerChildren.push( + delimiter.customSizedDelim( + group.value.rightDelim, delimSize, true, + options.withStyle(fstyle), group.mode) + ); + } + return makeSpan( - ["minner", "mfrac", options.style.reset(), fstyle.cls()], - [frac], options.getColor()); + ["minner", options.style.reset(), fstyle.cls()], + innerChildren, + options.getColor()); }, spacing: function(group, options, prev) { diff --git a/src/fontMetrics.js b/src/fontMetrics.js index 3d6bbae13..04423635c 100644 --- a/src/fontMetrics.js +++ b/src/fontMetrics.js @@ -1,5 +1,7 @@ /* jshint unused:false */ +var Style = require("./Style"); + /** * This file contains metrics regarding fonts and individual symbols. The sigma * and xi variables, as well as the metricMap map contain data extracted from @@ -35,7 +37,9 @@ var sigma17 = 0.247; var sigma18 = 0.386; var sigma19 = 0.050; var sigma20 = 2.390; -var sigma21 = 0.101; +var sigma21 = 1.01; +var sigma21Script = 0.81; +var sigma21ScriptScript = 0.71; var sigma22 = 0.250; // These font metrics are extracted from TeX by using @@ -81,8 +85,6 @@ var metrics = { sub2: sigma17, supDrop: sigma18, subDrop: sigma19, - delim1: sigma20, - delim2: sigma21, axisHeight: sigma22, defaultRuleThickness: xi8, bigOpSpacing1: xi9, @@ -90,7 +92,21 @@ var metrics = { bigOpSpacing3: xi11, bigOpSpacing4: xi12, bigOpSpacing5: xi13, - ptPerEm: ptPerEm + ptPerEm: ptPerEm, + + // TODO(alpert): Missing parallel structure here. We should probably add + // style-specific metrics for all of these. + delim1: sigma20, + getDelim2: function(style) { + if (style.size === Style.TEXT.size) { + return sigma21; + } else if (style.size === Style.SCRIPT.size) { + return sigma21Script; + } else if (style.size === Style.SCRIPTSCRIPT.size) { + return sigma21ScriptScript; + } + throw new Error("Unexpected style size: " + style.size); + } }; // This map contains a mapping from font name and character code to character diff --git a/src/functions.js b/src/functions.js index d51d38b4d..0d4992130 100644 --- a/src/functions.js +++ b/src/functions.js @@ -329,16 +329,55 @@ var duplicatedFunctions = [ // Fractions { - funcs: ["\\dfrac", "\\frac", "\\tfrac"], + funcs: [ + "\\dfrac", "\\frac", "\\tfrac", + "\\dbinom", "\\binom", "\\tbinom" + ], data: { numArgs: 2, greediness: 2, handler: function(func, numer, denom) { + var hasBarLine; + var leftDelim = null; + var rightDelim = null; + var size = "auto"; + + switch (func) { + case "\\dfrac": + case "\\frac": + case "\\tfrac": + hasBarLine = true; + break; + case "\\dbinom": + case "\\binom": + case "\\tbinom": + hasBarLine = false; + leftDelim = "("; + rightDelim = ")"; + break; + default: + throw new Error("Unrecognized genfrac command"); + } + + switch (func) { + case "\\dfrac": + case "\\dbinom": + size = "display"; + break; + case "\\tfrac": + case "\\tbinom": + size = "text"; + break; + } + return { - type: "frac", + type: "genfrac", numer: numer, denom: denom, - size: func.slice(1) + hasBarLine: hasBarLine, + leftDelim: leftDelim, + rightDelim: rightDelim, + size: size }; } } diff --git a/test/huxley/Huxleyfile.json b/test/huxley/Huxleyfile.json index 81a8a8c35..673b58927 100644 --- a/test/huxley/Huxleyfile.json +++ b/test/huxley/Huxleyfile.json @@ -11,6 +11,12 @@ "url": "http://localhost:7936/test/huxley/test.html?m=\\dfrac{a}{b}\\frac{a}{b}\\tfrac{a}{b}" }, + { + "name": "BinomTest", + "screenSize": [1024, 768], + "url": "http://localhost:7936/test/huxley/test.html?m=\\dbinom{a}{b}\\tbinom{a}{b}^{\\binom{a}{b}+17}" + }, + { "name": "NestedFractions", "screenSize": [1024, 768], diff --git a/test/huxley/Huxleyfolder/BinomTest.hux/firefox-1.png b/test/huxley/Huxleyfolder/BinomTest.hux/firefox-1.png new file mode 100644 index 0000000000000000000000000000000000000000..2f45dc3c1815d328352c3fc707c79f10301f2c42 GIT binary patch literal 24093 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 KNj_?D{eJ*-IAah1 literal 0 HcmV?d00001 diff --git a/test/huxley/Huxleyfolder/BinomTest.record.json b/test/huxley/Huxleyfolder/BinomTest.record.json new file mode 100644 index 000000000..3cae6ac65 --- /dev/null +++ b/test/huxley/Huxleyfolder/BinomTest.record.json @@ -0,0 +1,5 @@ +[ + { + "action": "screenshot" + } +]