Add vlist builder for more consistent stacking
Summary: Add a way to automatically build vlists correctly. Previously, we built vlists manually in ~4 different places, which made it difficult to manage changes, and led to a large amount of duplication in the less. This also fixes the vlist construction in safari, where the `display: inline-table` wasn't being applied because of CSS specificity. This leads to the only significant change in the huxley tests, with the vertical spacing. Test Plan: - Make sure the tests still work - Make sure most of the huxley screenshots didn't change, and that the new changes are insignificant. - Make sure vlists now work in Safari - Make sure the change to the VerticalSpacing screenshot is caused by the fix-baseline span now correctly applying `display: inline-table` by creating the construct in master and adding `display: inline-table !important` to the `.fix-ie` css rule Reviewers: alpert Reviewed By: alpert Differential Revision: http://phabricator.khanacademy.org/D13082
130
buildCommon.js
|
@ -94,11 +94,139 @@ var makeFontSizer = function(options, fontSize) {
|
|||
return fontSizer;
|
||||
};
|
||||
|
||||
/*
|
||||
* Makes a vertical list by stacking elements and kerns on top of each other.
|
||||
* Allows for many different ways of specifying the positioning method.
|
||||
*
|
||||
* Arguments:
|
||||
* - children: A list of child or kern nodes to be stacked on top of each other
|
||||
* (i.e. the first element will be at the bottom, and the last at
|
||||
* the top). Element nodes are specified as
|
||||
* {type: "elem", elem: node}
|
||||
* while kern nodes are specified as
|
||||
* {type: "kern", size: size}
|
||||
* - positionType: The method by which the vlist should be positioned. Valid
|
||||
* values are:
|
||||
* - "individualShift": The children list only contains elem
|
||||
* nodes, and each node contains an extra
|
||||
* "shift" value of how much it should be
|
||||
* shifted (note that shifting is always
|
||||
* moving downwards). positionData is
|
||||
* ignored.
|
||||
* - "top": The positionData specifies the topmost point of
|
||||
* the vlist (note this is expected to be a height,
|
||||
* so positive values move up)
|
||||
* - "bottom": The positionData specifies the bottommost point
|
||||
* of the vlist (note this is expected to be a
|
||||
* depth, so positive values move down
|
||||
* - "shift": The vlist will be positioned such that its
|
||||
* baseline is positionData away from the baseline
|
||||
* of the first child. Positive values move
|
||||
* downwards.
|
||||
* - "firstBaseline": The vlist will be positioned such that
|
||||
* its baseline is aligned with the
|
||||
* baseline of the first child.
|
||||
* positionData is ignored. (this is
|
||||
* equivalent to "shift" with
|
||||
* positionData=0)
|
||||
* - positionData: Data used in different ways depending on positionType
|
||||
* - options: An Options object
|
||||
*
|
||||
*/
|
||||
var makeVList = function(children, positionType, positionData, options) {
|
||||
var depth;
|
||||
if (positionType === "individualShift") {
|
||||
var oldChildren = children;
|
||||
children = [oldChildren[0]];
|
||||
|
||||
// Add in kerns to the list of children to get each element to be
|
||||
// shifted to the correct specified shift
|
||||
depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
|
||||
var currPos = depth;
|
||||
for (var i = 1; i < oldChildren.length; i++) {
|
||||
var diff = -oldChildren[i].shift - currPos -
|
||||
oldChildren[i].elem.depth;
|
||||
var size = diff -
|
||||
(oldChildren[i - 1].elem.height +
|
||||
oldChildren[i - 1].elem.depth);
|
||||
|
||||
currPos = currPos + diff;
|
||||
|
||||
children.push({type: "kern", size: size});
|
||||
children.push(oldChildren[i]);
|
||||
}
|
||||
} else if (positionType === "top") {
|
||||
// We always start at the bottom, so calculate the bottom by adding up
|
||||
// all the sizes
|
||||
var bottom = positionData;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
if (children[i].type === "kern") {
|
||||
bottom -= children[i].size;
|
||||
} else {
|
||||
bottom -= children[i].elem.height + children[i].elem.depth;
|
||||
}
|
||||
}
|
||||
depth = bottom;
|
||||
} else if (positionType === "bottom") {
|
||||
depth = -positionData;
|
||||
} else if (positionType === "shift") {
|
||||
depth = -children[0].elem.depth - positionData;
|
||||
} else if (positionType === "firstBaseline") {
|
||||
depth = -children[0].elem.depth;
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
|
||||
// Make the fontSizer
|
||||
var maxFontSize = 0;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
if (children[i].type === "elem") {
|
||||
maxFontSize = Math.max(maxFontSize, children[i].elem.maxFontSize);
|
||||
}
|
||||
}
|
||||
var fontSizer = makeFontSizer(options, maxFontSize);
|
||||
|
||||
// Create a new list of actual children at the correct offsets
|
||||
var realChildren = [];
|
||||
var currPos = depth;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
if (children[i].type === "kern") {
|
||||
currPos += children[i].size;
|
||||
} else {
|
||||
var child = children[i].elem;
|
||||
|
||||
var shift = -child.depth - currPos;
|
||||
currPos += child.height + child.depth;
|
||||
|
||||
var childWrap = makeSpan([], [fontSizer, child]);
|
||||
childWrap.height -= shift;
|
||||
childWrap.depth += shift;
|
||||
childWrap.style.top = shift + "em";
|
||||
|
||||
realChildren.push(childWrap);
|
||||
}
|
||||
}
|
||||
|
||||
// Add in an element at the end with no offset to fix the calculation of
|
||||
// baselines in some browsers (namely IE, sometimes safari)
|
||||
var baselineFix = makeSpan(
|
||||
["baseline-fix"], [fontSizer, new domTree.textNode("\u00a0")]);
|
||||
realChildren.push(baselineFix);
|
||||
|
||||
var vlist = makeSpan(["vlist"], realChildren);
|
||||
// Fix the final height and depth, in case there were kerns at the ends
|
||||
// since the makeSpan calculation won't take that in to account.
|
||||
vlist.height = Math.max(currPos, vlist.height);
|
||||
vlist.depth = Math.max(-depth, vlist.depth);
|
||||
return vlist;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
makeText: makeText,
|
||||
mathit: mathit,
|
||||
mathrm: mathrm,
|
||||
makeSpan: makeSpan,
|
||||
makeFragment: makeFragment,
|
||||
makeFontSizer: makeFontSizer
|
||||
makeFontSizer: makeFontSizer,
|
||||
makeVList: makeVList
|
||||
};
|
||||
|
|
178
buildTree.js
|
@ -147,12 +147,13 @@ var groupTypes = {
|
|||
[options.style.reset(), options.style.sub().cls()], [sub]);
|
||||
}
|
||||
|
||||
var u, v;
|
||||
if (isCharacterBox(group.value.base)) {
|
||||
var u = 0;
|
||||
var v = 0;
|
||||
u = 0;
|
||||
v = 0;
|
||||
} else {
|
||||
var u = base.height - fontMetrics.metrics.supDrop;
|
||||
var v = base.depth + fontMetrics.metrics.subDrop;
|
||||
u = base.height - fontMetrics.metrics.supDrop;
|
||||
v = base.depth + fontMetrics.metrics.subDrop;
|
||||
}
|
||||
|
||||
var p;
|
||||
|
@ -172,43 +173,24 @@ var groupTypes = {
|
|||
var supsub;
|
||||
|
||||
if (!group.value.sup) {
|
||||
var fontSizer = buildCommon.makeFontSizer(options, submid.maxFontSize);
|
||||
var subwrap = makeSpan(["msub"], [fontSizer, submid]);
|
||||
|
||||
v = Math.max(v, fontMetrics.metrics.sub1,
|
||||
sub.height - 0.8 * fontMetrics.metrics.xHeight);
|
||||
|
||||
subwrap.style.top = v + "em";
|
||||
subwrap.style.marginRight = scriptspace;
|
||||
supsub = buildCommon.makeVList([
|
||||
{type: "elem", elem: submid}
|
||||
], "shift", v, options);
|
||||
|
||||
subwrap.depth = subwrap.depth + v;
|
||||
subwrap.height = 0;
|
||||
|
||||
var fixIE = makeSpan(["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
|
||||
|
||||
supsub = makeSpan(["msupsub"], [subwrap, fixIE]);
|
||||
supsub.children[0].style.marginRight = scriptspace;
|
||||
} else if (!group.value.sub) {
|
||||
var fontSizer = buildCommon.makeFontSizer(options, supmid.maxFontSize);
|
||||
var supwrap = makeSpan(["msup"], [fontSizer, supmid]);
|
||||
|
||||
u = Math.max(u, p,
|
||||
sup.depth + 0.25 * fontMetrics.metrics.xHeight);
|
||||
|
||||
supwrap.style.top = -u + "em";
|
||||
supwrap.style.marginRight = scriptspace;
|
||||
supsub = buildCommon.makeVList([
|
||||
{type: "elem", elem: supmid}
|
||||
], "shift", -u, options);
|
||||
|
||||
supwrap.height = supwrap.height + u;
|
||||
supwrap.depth = 0;
|
||||
|
||||
var fixIE = makeSpan(["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
|
||||
|
||||
supsub = makeSpan(["msupsub"], [supwrap, fixIE]);
|
||||
supsub.children[0].style.marginRight = scriptspace;
|
||||
} else {
|
||||
var fontSizer = buildCommon.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);
|
||||
|
@ -224,21 +206,13 @@ var groupTypes = {
|
|||
}
|
||||
}
|
||||
|
||||
supwrap.style.top = -u + "em";
|
||||
subwrap.style.top = v + "em";
|
||||
supsub = buildCommon.makeVList([
|
||||
{type: "elem", elem: submid, shift: v},
|
||||
{type: "elem", elem: supmid, shift: -u}
|
||||
], "individualShift", null, options);
|
||||
|
||||
supwrap.style.marginRight = scriptspace;
|
||||
subwrap.style.marginRight = scriptspace;
|
||||
|
||||
supwrap.height = supwrap.height + u;
|
||||
supwrap.depth = 0;
|
||||
|
||||
subwrap.height = 0;
|
||||
subwrap.depth = subwrap.depth + v;
|
||||
|
||||
var fixIE = makeSpan(["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
|
||||
|
||||
supsub = makeSpan(["msupsub"], [supwrap, subwrap, fixIE]);
|
||||
supsub.children[0].style.marginRight = scriptspace;
|
||||
supsub.children[1].style.marginRight = scriptspace;
|
||||
}
|
||||
|
||||
return makeSpan([getTypeOfGroup(group.value.base)],
|
||||
|
@ -273,22 +247,16 @@ var groupTypes = {
|
|||
var dstyle = fstyle.fracDen();
|
||||
|
||||
var numer = buildGroup(group.value.numer, options.withStyle(nstyle));
|
||||
var numernumer = makeSpan([fstyle.reset(), nstyle.cls()], [numer]);
|
||||
var numerreset = makeSpan([fstyle.reset(), nstyle.cls()], [numer]);
|
||||
|
||||
var denom = buildGroup(group.value.denom, options.withStyle(dstyle));
|
||||
var denomdenom = makeSpan([fstyle.reset(), dstyle.cls()], [denom])
|
||||
|
||||
var fontSizer = buildCommon.makeFontSizer(options,
|
||||
Math.max(numer.maxFontSize, denom.maxFontSize));
|
||||
|
||||
var line = makeSpan([options.style.reset(), Style.TEXT.cls(), "line"]);
|
||||
|
||||
var numerrow = makeSpan(["mfracnum"], [fontSizer, numernumer]);
|
||||
var mid = makeSpan(["mfracmid"], [fontSizer, line]);
|
||||
var denomrow = makeSpan(["mfracden"], [fontSizer, denomdenom]);
|
||||
var denomreset = makeSpan([fstyle.reset(), dstyle.cls()], [denom])
|
||||
|
||||
var theta = fontMetrics.metrics.defaultRuleThickness / options.style.sizeMultiplier;
|
||||
|
||||
var mid = makeSpan([options.style.reset(), Style.TEXT.cls(), "frac-line"]);
|
||||
mid.height = theta;
|
||||
|
||||
var u, v, phi;
|
||||
if (fstyle.size === Style.DISPLAY.size) {
|
||||
u = fontMetrics.metrics.num1;
|
||||
|
@ -310,30 +278,20 @@ var groupTypes = {
|
|||
v += phi - ((a - 0.5 * theta) - (denom.height - v));
|
||||
}
|
||||
|
||||
numerrow.style.top = -u + "em";
|
||||
mid.style.top = -(a - 0.5 * theta) + "em";
|
||||
denomrow.style.top = v + "em";
|
||||
var midShift = -(a - 0.5 * theta);
|
||||
|
||||
numerrow.height = numerrow.height + u;
|
||||
numerrow.depth = 0;
|
||||
|
||||
denomrow.height = 0;
|
||||
denomrow.depth = denomrow.depth + v;
|
||||
|
||||
var fixIE = makeSpan(["fix-ie"], [
|
||||
fontSizer, new domTree.textNode("\u00a0")]);
|
||||
|
||||
var frac = makeSpan([], [numerrow, mid, denomrow, fixIE]);
|
||||
var frac = buildCommon.makeVList([
|
||||
{type: "elem", elem: denomreset, shift: v},
|
||||
{type: "elem", elem: mid, shift: midShift},
|
||||
{type: "elem", elem: numerreset, shift: -u}
|
||||
], "individualShift", null, options);
|
||||
|
||||
frac.height *= fstyle.sizeMultiplier / options.style.sizeMultiplier;
|
||||
frac.depth *= fstyle.sizeMultiplier / options.style.sizeMultiplier;
|
||||
|
||||
var wrap = makeSpan(
|
||||
[options.style.reset(), fstyle.cls()], [frac]);
|
||||
|
||||
return makeSpan(["minner"], [
|
||||
makeSpan(["mfrac"], [wrap])
|
||||
], options.getColor());
|
||||
return makeSpan(
|
||||
["minner", "mfrac", options.style.reset(), fstyle.cls()],
|
||||
[frac], options.getColor());
|
||||
},
|
||||
|
||||
color: function(group, options, prev) {
|
||||
|
@ -434,26 +392,18 @@ var groupTypes = {
|
|||
},
|
||||
|
||||
sqrt: function(group, options, prev) {
|
||||
var innerGroup = buildGroup(group.value.body,
|
||||
var inner = buildGroup(group.value.body,
|
||||
options.withStyle(options.style.cramp()));
|
||||
|
||||
var fontSizer = buildCommon.makeFontSizer(
|
||||
options, Math.max(innerGroup.maxFontSize, 1.0));
|
||||
|
||||
// The theta variable in the TeXbook
|
||||
var lineWidth = fontMetrics.metrics.defaultRuleThickness;
|
||||
|
||||
var lineInner =
|
||||
makeSpan([options.style.reset(), Style.TEXT.cls(), "line"]);
|
||||
lineInner.maxFontSize = 1.0;
|
||||
var line = makeSpan(["sqrt-line"], [fontSizer, lineInner]);
|
||||
|
||||
var inner = makeSpan(["sqrt-inner"], [fontSizer, innerGroup]);
|
||||
var fixIE = makeSpan(
|
||||
["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
|
||||
|
||||
var theta = fontMetrics.metrics.defaultRuleThickness /
|
||||
options.style.sizeMultiplier;
|
||||
|
||||
var line = makeSpan(
|
||||
[options.style.reset(), Style.TEXT.cls(), "sqrt-line"], [],
|
||||
options.getColor());
|
||||
line.height = theta;
|
||||
line.maxFontSize = 1.0;
|
||||
|
||||
var phi = theta;
|
||||
if (options.style.id < Style.TEXT.id) {
|
||||
phi = fontMetrics.metrics.xHeight;
|
||||
|
@ -467,18 +417,19 @@ var groupTypes = {
|
|||
|
||||
var delim = makeSpan(["sqrt-sign"], [
|
||||
delimiter.customSizedDelim("\\surd", minDelimiterHeight,
|
||||
false, options, group.mode)]);
|
||||
false, options, group.mode)],
|
||||
options.getColor());
|
||||
|
||||
var delimDepth = delim.height + delim.depth;
|
||||
var delimDepth = (delim.height + delim.depth) - theta;
|
||||
|
||||
if (delimDepth > inner.height + inner.depth + psi) {
|
||||
psi = (psi + delimDepth - inner.height - inner.depth) / 2;
|
||||
}
|
||||
|
||||
delim.style.top = (-inner.height - psi + delim.height - theta) + "em";
|
||||
|
||||
line.style.top = (-inner.height - psi) + "em";
|
||||
line.height = inner.height + psi + 2 * theta;
|
||||
delimShift = -(inner.height + psi + theta) + delim.height;
|
||||
delim.style.top = delimShift + "em";
|
||||
delim.height -= delimShift;
|
||||
delim.depth += delimShift;
|
||||
|
||||
// We add a special case here, because even when `inner` is empty, we
|
||||
// still get a line. So, we use a simple heuristic to decide if we
|
||||
|
@ -489,7 +440,12 @@ var groupTypes = {
|
|||
if (inner.height === 0 && inner.depth === 0) {
|
||||
body = makeSpan();
|
||||
} else {
|
||||
body = makeSpan(["sqrt-body"], [line, inner, fixIE]);
|
||||
body = buildCommon.makeVList([
|
||||
{type: "elem", elem: inner},
|
||||
{type: "kern", size: psi},
|
||||
{type: "elem", elem: line},
|
||||
{type: "kern", size: theta}
|
||||
], "firstBaseline", null, options);
|
||||
}
|
||||
|
||||
return makeSpan(["sqrt", "mord"], [delim, body]);
|
||||
|
@ -499,26 +455,22 @@ var groupTypes = {
|
|||
var innerGroup = buildGroup(group.value.body,
|
||||
options.withStyle(options.style.cramp()));
|
||||
|
||||
var fontSizer = buildCommon.makeFontSizer(options, innerGroup.maxFontSize);
|
||||
|
||||
// The theta variable in the TeXbook
|
||||
var lineWidth = fontMetrics.metrics.defaultRuleThickness /
|
||||
var theta = fontMetrics.metrics.defaultRuleThickness /
|
||||
options.style.sizeMultiplier;
|
||||
|
||||
var line = makeSpan(
|
||||
["overline-line"], [fontSizer, makeSpan([options.style.reset(), Style.TEXT.cls(), "line"])]);
|
||||
var inner = makeSpan(["overline-inner"], [fontSizer, innerGroup]);
|
||||
var fixIE = makeSpan(
|
||||
["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]);
|
||||
[options.style.reset(), Style.TEXT.cls(), "overline-line"]);
|
||||
line.height = theta;
|
||||
line.maxFontSize = 1.0;
|
||||
|
||||
line.style.top = (-inner.height - 3 * lineWidth) + "em";
|
||||
// The line is supposed to have 1 extra line width above it in height
|
||||
// (TeXbook pg. 443, nr. 9)
|
||||
line.height = inner.height + 5 * lineWidth;
|
||||
var vlist = buildCommon.makeVList([
|
||||
{type: "elem", elem: innerGroup},
|
||||
{type: "kern", size: 3 * theta},
|
||||
{type: "elem", elem: line},
|
||||
{type: "kern", size: theta}
|
||||
], "firstBaseline", null, options);
|
||||
|
||||
return makeSpan(["overline", "mord"], [
|
||||
line, inner, fixIE
|
||||
], options.getColor());
|
||||
return makeSpan(["overline", "mord"], [vlist], options.getColor());
|
||||
},
|
||||
|
||||
sizing: function(group, options, prev) {
|
||||
|
|
81
delimiter.js
|
@ -77,23 +77,19 @@ var makeLargeDelim = function(delim, size, center, options, mode) {
|
|||
};
|
||||
|
||||
// Make an inner span with the given offset and in the given font
|
||||
var makeInner = function(symbol, offset, font, mode) {
|
||||
var makeInner = function(symbol, font, mode) {
|
||||
var sizeClass;
|
||||
if (font === "Size1-Regular") {
|
||||
sizeClass = "size1";
|
||||
sizeClass = "delim-size1";
|
||||
} else if (font === "Size4-Regular") {
|
||||
sizeClass = "size4";
|
||||
sizeClass = "delim-size4";
|
||||
}
|
||||
|
||||
var inner = makeSpan(
|
||||
["delimsizinginner", sizeClass],
|
||||
[makeSpan([], [buildCommon.makeText(symbol, font, mode)])]);
|
||||
|
||||
inner.style.top = offset + "em";
|
||||
inner.height -= offset;
|
||||
inner.depth += offset;
|
||||
|
||||
return inner;
|
||||
return {type: "elem", elem: inner};
|
||||
};
|
||||
|
||||
var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
||||
|
@ -102,7 +98,6 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
|||
top = repeat = bottom = delim;
|
||||
middle = null;
|
||||
var font = "Size1-Regular";
|
||||
var overlap = false;
|
||||
|
||||
// We set the parts and font based on the symbol. Note that we use
|
||||
// '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
|
||||
|
@ -123,62 +118,44 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
|||
top = "\\Uparrow";
|
||||
repeat = "\u2016";
|
||||
bottom = "\\Downarrow";
|
||||
|
||||
// For some reason, the sizes of this one delimiter don't work out
|
||||
// right, so we shrink it a bit to make it now add an extraneous
|
||||
// repeating part
|
||||
if (height + depth <= 1.21) {
|
||||
height -= 0.01;
|
||||
depth -= 0.01;
|
||||
}
|
||||
} else if (delim === "|" || delim === "\\vert") {
|
||||
overlap = true;
|
||||
} else if (delim === "\\|" || delim === "\\Vert") {
|
||||
overlap = true;
|
||||
} else if (delim === "[" || delim === "\\lbrack") {
|
||||
top = "\u23a1";
|
||||
repeat = "\u23a2";
|
||||
bottom = "\u23a3";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === "]" || delim === "\\rbrack") {
|
||||
top = "\u23a4";
|
||||
repeat = "\u23a5";
|
||||
bottom = "\u23a6";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === "\\lfloor") {
|
||||
repeat = top = "\u23a2";
|
||||
bottom = "\u23a3";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === "\\lceil") {
|
||||
top = "\u23a1";
|
||||
repeat = bottom = "\u23a2";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === "\\rfloor") {
|
||||
repeat = top = "\u23a5";
|
||||
bottom = "\u23a6";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === "\\rceil") {
|
||||
top = "\u23a4";
|
||||
repeat = bottom = "\u23a5";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === "(") {
|
||||
top = "\u239b";
|
||||
repeat = "\u239c";
|
||||
bottom = "\u239d";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === ")") {
|
||||
top = "\u239e";
|
||||
repeat = "\u239f";
|
||||
bottom = "\u23a0";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
} else if (delim === "\\{" || delim === "\\lbrace") {
|
||||
top = "\u23a7";
|
||||
middle = "\u23a8";
|
||||
|
@ -196,7 +173,6 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
|||
bottom = "\u23b7";
|
||||
repeat = "\ue000";
|
||||
font = "Size4-Regular";
|
||||
overlap = true;
|
||||
}
|
||||
|
||||
// Get the metrics of the three sections
|
||||
|
@ -234,32 +210,16 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
|||
// Keep a list of the inner spans
|
||||
var inners = [];
|
||||
|
||||
// Add the top symbol
|
||||
inners.push(
|
||||
makeInner(top, topMetrics.height - height, font, mode));
|
||||
// Add the bottom symbol
|
||||
inners.push(makeInner(bottom, font, mode));
|
||||
|
||||
if (middle === null) {
|
||||
var repeatHeight = realHeightTotal - topHeightTotal - bottomHeightTotal;
|
||||
var symbolCount = Math.ceil(repeatHeight / repeatHeightTotal);
|
||||
|
||||
var overlapAmount;
|
||||
if (overlap) {
|
||||
// 2 * overlapAmount + repeatHeight =
|
||||
// (symbolCount - 1) * (repeatHeightTotal - overlapAmount) +
|
||||
// repeatHeightTotal
|
||||
overlapAmount = (symbolCount * repeatHeightTotal -
|
||||
repeatHeight) / (symbolCount + 1);
|
||||
} else {
|
||||
overlapAmount = 0;
|
||||
}
|
||||
|
||||
// Add repeat symbols until there's only space for the bottom symbol
|
||||
var currHeight = height - topHeightTotal + overlapAmount;
|
||||
for (var i = 0; i < symbolCount; i++) {
|
||||
inners.push(
|
||||
makeInner(repeat,
|
||||
repeatMetrics.height - currHeight, font, mode));
|
||||
currHeight -= repeatHeightTotal - overlapAmount;
|
||||
inners.push(makeInner(repeat, font, mode));
|
||||
}
|
||||
} else {
|
||||
// When there is a middle bit, we need the middle part and two repeated
|
||||
|
@ -277,40 +237,25 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
|||
Math.ceil(bottomRepeatHeight / repeatHeightTotal);
|
||||
|
||||
// Add the top repeated part
|
||||
var currHeight = height - topHeightTotal;
|
||||
for (var i = 0; i < topSymbolCount; i++) {
|
||||
inners.push(
|
||||
makeInner(repeat,
|
||||
repeatMetrics.height - currHeight, font, mode));
|
||||
currHeight -= repeatHeightTotal;
|
||||
inners.push(makeInner(repeat, font, mode));
|
||||
}
|
||||
|
||||
// Add the middle piece
|
||||
var midPoint = realHeightTotal / 2 - depth;
|
||||
inners.push(
|
||||
makeInner(middle,
|
||||
middleMetrics.height - midPoint - middleHeightTotal / 2,
|
||||
font, mode));
|
||||
inners.push(makeInner(middle, font, mode));
|
||||
|
||||
// Add the bottom repeated part
|
||||
currHeight = midPoint - middleHeightTotal / 2;
|
||||
for (var i = 0; i < bottomSymbolCount; i++) {
|
||||
inners.push(
|
||||
makeInner(repeat,
|
||||
repeatMetrics.height - currHeight, font, mode));
|
||||
currHeight -= repeatHeightTotal;
|
||||
inners.push(makeInner(repeat, font, mode));
|
||||
}
|
||||
}
|
||||
|
||||
// Add the bottom symbol
|
||||
inners.push(
|
||||
makeInner(bottom, depth - bottomMetrics.depth, font, mode));
|
||||
inners.push(makeInner(top, font, mode));
|
||||
|
||||
var fixIE = makeSpan(["fix-ie"], [new domTree.textNode("\u00a0")]);
|
||||
inners.push(fixIE);
|
||||
var inner = buildCommon.makeVList(inners, "bottom", depth, options);
|
||||
|
||||
return styleWrap(
|
||||
makeSpan(["delimsizing", "mult"], inners, options.getColor()),
|
||||
makeSpan(["delimsizing", "mult"], [inner], options.getColor()),
|
||||
Style.TEXT, options);
|
||||
};
|
||||
|
||||
|
|
|
@ -34,11 +34,6 @@ big parens
|
|||
font-family: KaTeX_AMS;
|
||||
}
|
||||
|
||||
.fix-ie {
|
||||
display: inline-table;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
// This value is also used in fontMetrics.js, if you change it make sure the
|
||||
// values match.
|
||||
@ptperem: 10.0;
|
||||
|
@ -171,52 +166,35 @@ big parens
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.baseline-align-hack-outer() {
|
||||
.vlist {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.baseline-align-hack-middle() {
|
||||
display: block;
|
||||
height: 0;
|
||||
}
|
||||
> span {
|
||||
display: block;
|
||||
height: 0;
|
||||
position: relative;
|
||||
|
||||
.baseline-align-hack-inner() {
|
||||
display: inline-block;
|
||||
> span {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.baseline-fix {
|
||||
display: inline-table;
|
||||
table-layout: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
.msupsub {
|
||||
.baseline-align-hack-outer;
|
||||
text-align: left;
|
||||
|
||||
.msup,
|
||||
.msub,
|
||||
.fix-ie {
|
||||
.baseline-align-hack-middle;
|
||||
position: relative;
|
||||
|
||||
> span {
|
||||
.baseline-align-hack-inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mfrac {
|
||||
.baseline-align-hack-outer;
|
||||
|
||||
.mfracnum,
|
||||
.mfracmid,
|
||||
.mfracden,
|
||||
.fix-ie {
|
||||
.baseline-align-hack-middle;
|
||||
position: relative;
|
||||
> span > span {
|
||||
text-align: center;
|
||||
|
||||
> span {
|
||||
.baseline-align-hack-inner;
|
||||
}
|
||||
}
|
||||
|
||||
.mfracmid > .line {
|
||||
.frac-line {
|
||||
width: 100%;
|
||||
|
||||
&:before {
|
||||
|
@ -316,21 +294,8 @@ big parens
|
|||
}
|
||||
|
||||
.overline {
|
||||
.baseline-align-hack-outer;
|
||||
|
||||
> .overline-line,
|
||||
> .overline-inner,
|
||||
> .fix-ie {
|
||||
.baseline-align-hack-middle;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
||||
> span {
|
||||
.baseline-align-hack-inner;
|
||||
}
|
||||
}
|
||||
|
||||
> .overline-line > .line {
|
||||
.overline-line {
|
||||
width: 100%;
|
||||
|
||||
&:before {
|
||||
|
@ -355,37 +320,22 @@ big parens
|
|||
position: relative;
|
||||
}
|
||||
|
||||
> .sqrt-body {
|
||||
.baseline-align-hack-outer;
|
||||
.sqrt-line {
|
||||
width: 100%;
|
||||
|
||||
> .sqrt-line,
|
||||
> .sqrt-inner,
|
||||
> .fix-ie {
|
||||
.baseline-align-hack-middle;
|
||||
position: relative;
|
||||
|
||||
> span {
|
||||
.baseline-align-hack-inner;
|
||||
}
|
||||
&:before {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
content: "";
|
||||
display: block;
|
||||
}
|
||||
|
||||
> .sqrt-line > .line {
|
||||
width: 100%;
|
||||
|
||||
&:before {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
content: "";
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 0.04em;
|
||||
content: "";
|
||||
display: block;
|
||||
margin-top: -1px;
|
||||
}
|
||||
&:after {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 0.04em;
|
||||
content: "";
|
||||
display: block;
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -434,19 +384,11 @@ big parens
|
|||
&.size4 { font-family: KaTeX_Size4; }
|
||||
|
||||
&.mult {
|
||||
.baseline-align-hack-outer;
|
||||
|
||||
> .fix-ie,
|
||||
> .delimsizinginner {
|
||||
.baseline-align-hack-middle;
|
||||
position: relative;
|
||||
|
||||
&.size1 > span {
|
||||
font-family: Katex_Size1;
|
||||
}
|
||||
&.size4 > span {
|
||||
font-family: Katex_Size4;
|
||||
}
|
||||
.delim-size1 > span {
|
||||
font-family: Katex_Size1;
|
||||
}
|
||||
.delim-size4 > span {
|
||||
font-family: Katex_Size4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |