diff --git a/Options.js b/Options.js
index 8d2a8d032..ca33a30bd 100644
--- a/Options.js
+++ b/Options.js
@@ -1,14 +1,8 @@
-function Options(style, size, color, deep, parentStyle, parentSize) {
+function Options(style, size, color, parentStyle, parentSize) {
this.style = style;
this.color = color;
this.size = size;
- // TODO(emily): Get rid of deep when we can actually use sizing everywhere
- if (deep === undefined) {
- deep = false;
- }
- this.deep = deep;
-
if (parentStyle === undefined) {
parentStyle = style;
}
@@ -21,28 +15,20 @@ function Options(style, size, color, deep, parentStyle, parentSize) {
}
Options.prototype.withStyle = function(style) {
- return new Options(style, this.size, this.color, this.deep,
- this.style, this.size);
+ return new Options(style, this.size, this.color, this.style, this.size);
};
Options.prototype.withSize = function(size) {
- return new Options(this.style, size, this.color, this.deep,
- this.style, this.size);
+ return new Options(this.style, size, this.color, this.style, this.size);
};
Options.prototype.withColor = function(color) {
- return new Options(this.style, this.size, color, this.deep,
- this.style, this.size);
-};
-
-Options.prototype.deepen = function() {
- return new Options(this.style, this.size, this.color, true,
- this.parentStyle, this.parentSize);
+ return new Options(this.style, this.size, color, this.style, this.size);
};
Options.prototype.reset = function() {
- return new Options(this.style, this.size, this.color, this.deep,
- this.style, this.size);
+ return new Options(
+ this.style, this.size, this.color, this.style, this.size);
};
var colorMap = {
diff --git a/buildTree.js b/buildTree.js
index 6e8b654fa..d9eeb10e7 100644
--- a/buildTree.js
+++ b/buildTree.js
@@ -21,6 +21,7 @@ var buildExpression = function(expression, options, prev) {
var makeSpan = function(classes, children, color) {
var height = 0;
var depth = 0;
+ var maxFontSize = 0;
if (children) {
for (var i = 0; i < children.length; i++) {
@@ -30,10 +31,14 @@ var makeSpan = function(classes, children, color) {
if (children[i].depth > depth) {
depth = children[i].depth;
}
+ if (children[i].maxFontSize > maxFontSize) {
+ maxFontSize = children[i].maxFontSize;
+ }
}
}
- var span = new domTree.span(classes, children, height, depth);
+ var span = new domTree.span(
+ classes, children, height, depth, maxFontSize);
if (color) {
span.style.color = color;
@@ -42,6 +47,17 @@ var makeSpan = function(classes, children, color) {
return span;
};
+var makeFontSizer = function(options, fontSize) {
+ var fontSizeInner = makeSpan([], [new domTree.textNode("\u200b")]);
+ fontSizeInner.style.fontSize = (fontSize / options.style.sizeMultiplier) + "em";
+
+ var fontSizer = makeSpan(
+ ["fontsize-ensurer", "reset-" + options.size, "size5"],
+ [fontSizeInner]);
+
+ return fontSizer;
+};
+
var groupToType = {
mathord: "mord",
textord: "mord",
@@ -142,7 +158,7 @@ var groupTypes = {
text: function(group, options, prev) {
return makeSpan(["text mord", options.style.cls()],
- [buildGroup(group.value, options.deepen())]
+ [buildGroup(group.value, options.reset())]
);
},
@@ -151,18 +167,16 @@ var groupTypes = {
if (group.value.sup) {
var sup = buildGroup(group.value.sup,
- options.withStyle(options.style.sup()).deepen());
+ options.withStyle(options.style.sup()));
var supmid = makeSpan(
[options.style.reset(), options.style.sup().cls()], [sup]);
- var supwrap = makeSpan(["msup", options.style.reset()], [supmid]);
}
if (group.value.sub) {
var sub = buildGroup(group.value.sub,
- options.withStyle(options.style.sub()).deepen());
+ options.withStyle(options.style.sub()));
var submid = makeSpan(
[options.style.reset(), options.style.sub().cls()], [sub]);
- var subwrap = makeSpan(["msub"], [submid]);
}
if (isCharacterBox(group.value.base)) {
@@ -183,9 +197,11 @@ var groupTypes = {
}
var supsub;
- var fixIE = makeSpan(["fix-ie"], [new domTree.textNode("\u00a0")]);
if (!group.value.sup) {
+ var fontSizer = makeFontSizer(options, submid.maxFontSize);
+ var subwrap = makeSpan(["msub"], [fontSizer, submid]);
+
v = Math.max(v, fontMetrics.metrics.sub1,
sub.height - 0.8 * fontMetrics.metrics.xHeight);
@@ -194,8 +210,13 @@ var groupTypes = {
subwrap.depth = subwrap.depth + v;
subwrap.height = 0;
+ var fixIE = makeSpan(["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
+
supsub = makeSpan(["msupsub"], [subwrap, fixIE]);
} else if (!group.value.sub) {
+ var fontSizer = makeFontSizer(options, supmid.maxFontSize);
+ var supwrap = makeSpan(["msup"], [fontSizer, supmid]);
+
u = Math.max(u, p,
sup.depth + 0.25 * fontMetrics.metrics.xHeight);
@@ -204,8 +225,15 @@ var groupTypes = {
supwrap.height = supwrap.height + u;
supwrap.depth = 0;
+ var fixIE = makeSpan(["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
+
supsub = makeSpan(["msupsub"], [supwrap, fixIE]);
} else {
+ var fontSizer = makeFontSizer(options,
+ Math.max(submid.maxFontSize, supmid.maxFontSize));
+ var subwrap = makeSpan(["msub"], [fontSizer, submid]);
+ var supwrap = makeSpan(["msup"], [fontSizer, supmid]);
+
u = Math.max(u, p,
sup.depth + 0.25 * fontMetrics.metrics.xHeight);
v = Math.max(v, fontMetrics.metrics.sub2);
@@ -230,6 +258,8 @@ var groupTypes = {
subwrap.height = 0;
subwrap.depth = subwrap.depth + v;
+ var fixIE = makeSpan(["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
+
supsub = makeSpan(["msupsub"], [supwrap, subwrap, fixIE]);
}
@@ -263,15 +293,18 @@ var groupTypes = {
var nstyle = fstyle.fracNum();
var dstyle = fstyle.fracDen();
- var numer = buildGroup(group.value.numer, options.withStyle(nstyle).deepen());
+ var numer = buildGroup(group.value.numer, options.withStyle(nstyle));
var numernumer = makeSpan([fstyle.reset(), nstyle.cls()], [numer]);
- var numerrow = makeSpan(["mfracnum"], [numernumer]);
- var mid = makeSpan(["mfracmid"], [makeSpan()]);
-
- var denom = buildGroup(group.value.denom, options.withStyle(dstyle).deepen());
+ var denom = buildGroup(group.value.denom, options.withStyle(dstyle));
var denomdenom = makeSpan([fstyle.reset(), dstyle.cls()], [denom])
- var denomrow = makeSpan(["mfracden"], [denomdenom]);
+
+ var fontSizer = makeFontSizer(options,
+ Math.max(numer.maxFontSize, denom.maxFontSize));
+
+ var numerrow = makeSpan(["mfracnum"], [fontSizer, numernumer]);
+ var mid = makeSpan(["mfracmid"], [fontSizer, makeSpan(["line"])]);
+ var denomrow = makeSpan(["mfracden"], [fontSizer, denomdenom]);
var theta = fontMetrics.metrics.defaultRuleThickness;
@@ -306,7 +339,8 @@ var groupTypes = {
denomrow.height = 0;
denomrow.depth = denomrow.depth + v;
- var fixIE = makeSpan(["fix-ie"], [new domTree.textNode("\u00a0")]);
+ var fixIE = makeSpan(["fix-ie"], [
+ fontSizer, new domTree.textNode("\u00a0")]);
var frac = makeSpan([], [numerrow, mid, denomrow, fixIE]);
@@ -366,14 +400,14 @@ var groupTypes = {
llap: function(group, options, prev) {
var inner = makeSpan(
- ["inner"], [buildGroup(group.value, options.deepen())]);
+ ["inner"], [buildGroup(group.value, options.reset())]);
var fix = makeSpan(["fix"], []);
return makeSpan(["llap", options.style.cls()], [inner, fix]);
},
rlap: function(group, options, prev) {
var inner = makeSpan(
- ["inner"], [buildGroup(group.value, options.deepen())]);
+ ["inner"], [buildGroup(group.value, options.reset())]);
var fix = makeSpan(["fix"], []);
return makeSpan(["rlap", options.style.cls()], [inner, fix]);
},
@@ -422,14 +456,18 @@ var groupTypes = {
overline: function(group, options, prev) {
var innerGroup = buildGroup(group.value.result,
- options.withStyle(options.style.cramp()).deepen());
+ options.withStyle(options.style.cramp()));
+
+ var fontSizer = makeFontSizer(options, innerGroup.maxFontSize);
// The theta variable in the TeXbook
var lineWidth = fontMetrics.metrics.defaultRuleThickness;
- var line = makeSpan(["overline-line"], [makeSpan([])]);
- var inner = makeSpan(["overline-inner"], [innerGroup]);
- var fixIE = makeSpan(["fix-ie"], []);
+ var line = makeSpan(
+ ["overline-line"], [fontSizer, makeSpan(["line"])]);
+ var inner = makeSpan(["overline-inner"], [fontSizer, innerGroup]);
+ var fixIE = makeSpan(
+ ["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
line.style.top = (-inner.height - 3 * lineWidth) + "em";
// The line is supposed to have 1 extra line width above it in height
@@ -445,10 +483,27 @@ var groupTypes = {
var inner = buildGroup(group.value.value,
options.withSize(group.value.size), prev);
- return makeSpan(
- ["sizing", "reset-" + options.size, group.value.size,
- getTypeOfGroup(group.value.value)],
- [inner]);
+ var span = makeSpan([getTypeOfGroup(group.value.value)],
+ [makeSpan(["sizing", "reset-" + options.size, group.value.size],
+ [inner])]);
+
+ var sizeToFontSize = {
+ "size1": 0.5,
+ "size2": 0.7,
+ "size3": 0.8,
+ "size4": 0.9,
+ "size5": 1.0,
+ "size6": 1.2,
+ "size7": 1.44,
+ "size8": 1.73,
+ "size9": 2.07,
+ "size10": 2.49
+ };
+
+ var fontSize = sizeToFontSize[group.value.size];
+ span.maxFontSize = fontSize * options.style.sizeMultiplier;
+
+ return span;
},
delimsizing: function(group, options, prev) {
@@ -518,9 +573,21 @@ var groupTypes = {
var inner = mathrmSize(
original, group.value.size, group.mode);
- return makeSpan(
- ["delimsizing", size, groupToType[group.value.type]],
- [inner], options.getColor());
+ var node = makeSpan(
+ [options.style.reset(), Style.TEXT.cls(),
+ groupToType[group.value.type]],
+ [makeSpan(
+ ["delimsizing", size, groupToType[group.value.type]],
+ [inner], options.getColor())]);
+
+ var multiplier = Style.TEXT.sizeMultiplier /
+ options.style.sizeMultiplier;
+
+ node.height *= multiplier;
+ node.depth *= multiplier;
+ node.maxFontSize = 1.0;
+
+ return node;
} else if (utils.contains(stackDelimiters, original)) {
// These delimiters can be created by stacking other delimiters on
// top of each other to create the correct size
@@ -602,9 +669,20 @@ var groupTypes = {
var fixIE = makeSpan(["fix-ie"], [new domTree.textNode("\u00a0")]);
inners.push(fixIE);
- return makeSpan(
- ["delimsizing", "mult", groupToType[group.value.type]],
- inners, options.getColor());
+ var node = makeSpan(
+ [options.style.reset(), Style.TEXT.cls(),
+ groupToType[group.value.type]],
+ [makeSpan(["delimsizing", "mult"],
+ inners, options.getColor())]);
+
+ var multiplier = Style.TEXT.sizeMultiplier /
+ options.style.sizeMultiplier;
+
+ node.height *= multiplier;
+ node.depth *= multiplier;
+ node.maxFontSize = 1.0;
+
+ return node;
} else {
throw new ParseError("Illegal delimiter: '" + original + "'");
}
@@ -644,11 +722,6 @@ var buildGroup = function(group, options, prev) {
var multiplier = sizingMultiplier[options.size] /
sizingMultiplier[options.parentSize];
- if (options.deep) {
- throw new ParseError(
- "Can't use sizing outside of the root node");
- }
-
groupNode.height *= multiplier;
groupNode.depth *= multiplier;
}
diff --git a/domTree.js b/domTree.js
index b8e183cd0..d87607cff 100644
--- a/domTree.js
+++ b/domTree.js
@@ -3,11 +3,12 @@
// function. They are useful for both storing extra properties on the nodes, as
// well as providing a way to easily work with the DOM.
-function span(classes, children, height, depth, style) {
+function span(classes, children, height, depth, maxFontSize, style) {
this.classes = classes || [];
this.children = children || [];
this.height = height || 0;
this.depth = depth || 0;
+ this.maxFontSize = maxFontSize || 0;
this.style = style || {};
}
diff --git a/static/katex.less b/static/katex.less
index c60d249b5..822b9c3ca 100644
--- a/static/katex.less
+++ b/static/katex.less
@@ -34,6 +34,11 @@ big parens
font-family: KaTeX_AMS;
}
+ .fix-ie {
+ display: inline-table;
+ table-layout: fixed;
+ }
+
@thinspace: 0.16667em;
@mediumspace: 0.22222em;
@thickspace: 0.27778em;
@@ -188,10 +193,6 @@ big parens
.baseline-align-hack-inner;
}
}
-
- .fix-ie {
- display: inline-block;
- }
}
.mfrac {
@@ -210,11 +211,7 @@ big parens
}
}
- .fix-ie {
- display: inline-block;
- }
-
- .mfracmid > span {
+ .mfracmid > .line {
width: 100%;
&:before {
@@ -323,11 +320,7 @@ big parens
}
}
- > .fix-ie {
- display: inline-block;
- }
-
- > .overline-line > span {
+ > .overline-line > .line {
width: 100%;
&:before {
@@ -347,7 +340,7 @@ big parens
}
}
- .sizing {
+ .sizing, .fontsize-ensurer {
display: inline-block;
@size1: 0.5;
diff --git a/test/huxley/DeepFontSizing.hux/firefox-1.png b/test/huxley/DeepFontSizing.hux/firefox-1.png
new file mode 100644
index 000000000..99b18ddad
Binary files /dev/null and b/test/huxley/DeepFontSizing.hux/firefox-1.png differ
diff --git a/test/huxley/DeepFontSizing.hux/record.json b/test/huxley/DeepFontSizing.hux/record.json
new file mode 100644
index 000000000..3cae6ac65
--- /dev/null
+++ b/test/huxley/DeepFontSizing.hux/record.json
@@ -0,0 +1,5 @@
+[
+ {
+ "action": "screenshot"
+ }
+]
diff --git a/test/huxley/DelimiterSizing.hux/firefox-1.png b/test/huxley/DelimiterSizing.hux/firefox-1.png
index 4ad62c262..cf432632b 100644
Binary files a/test/huxley/DelimiterSizing.hux/firefox-1.png and b/test/huxley/DelimiterSizing.hux/firefox-1.png differ
diff --git a/test/huxley/Huxleyfile.json b/test/huxley/Huxleyfile.json
index d265f333e..c023443ab 100644
--- a/test/huxley/Huxleyfile.json
+++ b/test/huxley/Huxleyfile.json
@@ -105,5 +105,17 @@
"name": "Overline",
"screenSize": [1024, 768],
"url": "http://localhost:7936/test/huxley/test.html?m=\\overline{x}\\overline{x}\\overline{x^{x^{x^x}}} \\blue\\overline{y}"
+ },
+
+ {
+ "name": "DeepFontSizing",
+ "screenSize": [1024, 768],
+ "url": "http://localhost:7936/test/huxley/test.html?m=a^{\\big| x^{\\big(}}_{\\Big\\uparrow} + i^{i^{\\Huge x}_y}_{\\Huge z} + \\dfrac{\\Huge x}{y}"
+ },
+
+ {
+ "name": "VerticalSpacing",
+ "screenSize": [1024, 768],
+ "url": "http://localhost:7936/test/huxley/test.html?pre=potato
&post=
moo&m=x^{\\Huge y}z"
}
]
diff --git a/test/huxley/Overline.hux/firefox-1.png b/test/huxley/Overline.hux/firefox-1.png
index d16429077..0ae10a096 100644
Binary files a/test/huxley/Overline.hux/firefox-1.png and b/test/huxley/Overline.hux/firefox-1.png differ
diff --git a/test/huxley/VerticalSpacing.hux/firefox-1.png b/test/huxley/VerticalSpacing.hux/firefox-1.png
new file mode 100644
index 000000000..302f89b80
Binary files /dev/null and b/test/huxley/VerticalSpacing.hux/firefox-1.png differ
diff --git a/test/huxley/VerticalSpacing.hux/record.json b/test/huxley/VerticalSpacing.hux/record.json
new file mode 100644
index 000000000..3cae6ac65
--- /dev/null
+++ b/test/huxley/VerticalSpacing.hux/record.json
@@ -0,0 +1,5 @@
+[
+ {
+ "action": "screenshot"
+ }
+]