Text mode: Combine adjacent spans when possible for cleaner HTML.

So `\text{Hi}` becomes one <span...>Hi</span>, rather than two
<span...>H</span><span...>i</span>.

This allows the font renderer to apply kerning, which changes some
test output.
This commit is contained in:
Eddie Kohler 2016-11-28 11:24:12 -05:00
parent b88bc7723d
commit 576380c11c
6 changed files with 49 additions and 7 deletions

View File

@ -249,9 +249,15 @@ groupTypes.ordgroup = function(group, options) {
};
groupTypes.text = function(group, options) {
var inner = buildExpression(group.value.body, options, true);
for (var i = 0; i < inner.length - 1; i++) {
if (inner[i].tryCombine(inner[i + 1])) {
inner.splice(i + 1, 1);
i--;
}
}
return makeSpan(["mord", "text", options.style.cls()],
buildExpression(group.value.body, options.reset(), true),
options);
inner, options);
};
groupTypes.color = function(group, options) {
@ -706,16 +712,20 @@ groupTypes.spacing = function(group, options) {
// Spaces are generated by adding an actual space. Each of these
// things has an entry in the symbols table, so these will be turned
// into appropriate outputs.
return makeSpan(
["mspace"],
[buildCommon.mathsym(group.value, group.mode)]
);
if (group.mode === "text") {
return buildCommon.makeOrd(group, options, "textord");
} else {
return makeSpan(["mspace"],
[buildCommon.mathsym(group.value, group.mode, options)],
options);
}
} else {
// Other kinds of spaces are of arbitrary width. We use CSS to
// generate these.
return makeSpan(
["mspace",
buildCommon.spacingFunctions[group.value].className]);
buildCommon.spacingFunctions[group.value].className],
[], options);
}
};

View File

@ -57,6 +57,10 @@ span.prototype.setAttribute = function(attribute, value) {
this.attributes[attribute] = value;
};
span.prototype.tryCombine = function(sibling) {
return false;
};
/**
* Convert the span into an HTML node
*/
@ -220,6 +224,34 @@ function symbolNode(value, height, depth, italic, skew, classes, style) {
}
}
symbolNode.prototype.tryCombine = function(sibling) {
if (!sibling
|| !(sibling instanceof symbolNode)
|| this.italic > 0
|| createClass(this.classes) !== createClass(sibling.classes)
|| this.skew !== sibling.skew
|| this.maxFontSize !== sibling.maxFontSize) {
return false;
}
for (var style in this.style) {
if (this.style.hasOwnProperty(style)
&& this.style[style] !== sibling.style[style]) {
return false;
}
}
for (style in sibling.style) {
if (sibling.style.hasOwnProperty(style)
&& this.style[style] !== sibling.style[style]) {
return false;
}
}
this.value += sibling.value;
this.height = Math.max(this.height, sibling.height);
this.depth = Math.max(this.depth, sibling.depth);
this.italic = sibling.italic;
return true;
};
/**
* Creates a text node or span from a symbol node. Note that a span is only
* created if it is needed.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB