Improve \sqrt (#810)

* Improve \sqrt

Make \sqrt out of inline SVGs to ensure a perfect match at the junction between surd and viniculum.

* Tweak for kern clarity

* Fix lint error

* regenerate screenshot tests with sqrts

* Correct advance

Edit the SVG paths so that they have the correct left bearing and advance width values.

This will correct the spacing on the left side of each surd and it will also improve the placment of a root indice.

* Revise scriptstyle surds

In the `main` size, delimiters *do* scale with scriptstyle and scriptscriptstyle.

* update screenshot images containing sqrts
This commit is contained in:
Ron Kok
2017-08-22 18:39:15 -07:00
committed by Kevin Barabash
parent dd0c14ac01
commit e88256b397
17 changed files with 146 additions and 49 deletions

View File

@@ -1042,7 +1042,13 @@ groupTypes.sqrt = function(group, options) {
// First, we do the same steps as in overline to build the inner group
// and line
const inner = buildGroup(group.value.body, options.havingCrampedStyle());
let inner = buildGroup(group.value.body, options.havingCrampedStyle());
// Some groups can return document fragments. Handle those by wrapping
// them in a span.
if (inner instanceof domTree.documentFragment) {
inner = makeSpan([], [inner], options);
}
// Calculate the minimum size for the \surd delimiter
const metrics = options.fontMetrics();
@@ -1059,20 +1065,18 @@ groupTypes.sqrt = function(group, options) {
const minDelimiterHeight = (inner.height + inner.depth +
lineClearance + theta) * options.sizeMultiplier;
// Create a \surd delimiter of the required minimum size
const delimChar = delimiter.customSizedDelim("\\surd", minDelimiterHeight,
false, options, group.mode);
const delim = makeSpan(["sqrt-sign"], [delimChar], options);
// Create a sqrt SVG of the required minimum size
const img = delimiter.customSizedDelim("\\surd", minDelimiterHeight,
false, options, group.mode);
// Calculate the actual line width.
// This actually should depend on the chosen font -- e.g. \boldmath
// should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and
// have thicker rules.
const ruleWidth = options.fontMetrics().sqrtRuleThickness *
delimChar.delimSizeMultiplier;
const line = makeLineSpan("sqrt-line", options, ruleWidth);
img.sizeMultiplier;
const delimDepth = (delim.height + delim.depth) - ruleWidth;
const delimDepth = img.height - ruleWidth;
// Adjust the clearance based on the delimiter size
if (delimDepth > inner.height + inner.depth + lineClearance) {
@@ -1080,12 +1084,8 @@ groupTypes.sqrt = function(group, options) {
(lineClearance + delimDepth - inner.height - inner.depth) / 2;
}
// Shift the delimiter so that its top lines up with the top of the line
const delimShift = -(inner.height + lineClearance + ruleWidth) +
delim.height;
delim.style.top = delimShift + "em";
delim.height -= delimShift;
delim.depth += delimShift;
// Shift the sqrt image
const imgShift = img.height - inner.height - lineClearance - ruleWidth;
// 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
@@ -1096,16 +1096,20 @@ groupTypes.sqrt = function(group, options) {
if (inner.height === 0 && inner.depth === 0) {
body = makeSpan();
} else {
inner.style.paddingLeft = img.surdWidth + "em";
// Overlay the image and the argument.
body = buildCommon.makeVList([
{type: "elem", elem: inner},
{type: "kern", size: lineClearance},
{type: "elem", elem: line},
{type: "kern", size: -(inner.height + imgShift)},
{type: "elem", elem: img},
{type: "kern", size: ruleWidth},
], "firstBaseline", null, options);
body.children[0].children[0].classes.push("svg-align");
}
if (!group.value.index) {
return makeSpan(["mord", "sqrt"], [delim, body], options);
return makeSpan(["mord", "sqrt"], [body], options);
} else {
// Handle the optional root index
@@ -1113,13 +1117,9 @@ groupTypes.sqrt = function(group, options) {
const newOptions = options.havingStyle(Style.SCRIPTSCRIPT);
const rootm = buildGroup(group.value.index, newOptions, options);
// Figure out the height and depth of the inner part
const innerRootHeight = Math.max(delim.height, body.height);
const innerRootDepth = Math.max(delim.depth, body.depth);
// The amount the index is shifted by. This is taken from the TeX
// source, in the definition of `\r@@t`.
const toShift = 0.6 * (innerRootHeight - innerRootDepth);
const toShift = 0.6 * (body.height - body.depth);
// Build a VList with the superscript shifted up correctly
const rootVList = buildCommon.makeVList(
@@ -1130,7 +1130,7 @@ groupTypes.sqrt = function(group, options) {
const rootVListWrap = makeSpan(["root"], [rootVList]);
return makeSpan(["mord", "sqrt"],
[rootVListWrap, delim, body], options);
[rootVListWrap, body], options);
}
};