Simplify stacked delimiters

Using a loop to determine the number of symbols we need is intuitive but
hardly efficient.  A Math.ceil in this situation is much better.

After that ceil or the loop that it replaced, the total height should be
equal to the minimal height plus an integral number times the height of the
repeat symbol.  That integer equals (half) number of loop iterations in the
original code, and the repeatCount variable in my new code.  So later on,
the quotient (repeatHeight / repeatHeightTotal) should be an integer, at
least up to numeric errors.  Applying ceil instead of round to that is
asking for these numeric errors to seriously break stuff.  Just reusing the
repeatCount is much simpler, shorter and more elegant.

Having distinct topSymbolCount and bottomSymbolCount seems pointless, since
the only reason why these could ever be different is due to the fact that
bottomRepeatHeight was computed using topHeightTotal, which looks like a
bug.  The old loop and new ceil assume a symmetric repeatCount.
This commit is contained in:
Martin von Gagern 2015-06-13 21:14:35 +02:00
parent 2f7a54877a
commit 397dcb303b

View File

@ -231,28 +231,25 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
var bottomMetrics = getMetrics(bottom, font);
var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
var middleMetrics, middleHeightTotal;
var middleHeightTotal = 0;
var middleFactor = 1;
if (middle !== null) {
middleMetrics = getMetrics(middle, font);
var middleMetrics = getMetrics(middle, font);
middleHeightTotal = middleMetrics.height + middleMetrics.depth;
middleFactor = 2; // repeat symmetrically above and below middle
}
// Calcuate the real height that the delimiter will have. It is at least the
// size of the top, bottom, and optional middle combined.
var realHeightTotal = topHeightTotal + bottomHeightTotal;
if (middle !== null) {
realHeightTotal += middleHeightTotal;
}
// Calcuate the minimal height that the delimiter can have.
// It is at least the size of the top, bottom, and optional middle combined.
var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal;
// Then add repeated pieces until we reach the specified height.
while (realHeightTotal < heightTotal) {
realHeightTotal += repeatHeightTotal;
if (middle !== null) {
// If there is a middle section, we need an equal number of pieces
// on the top and bottom.
realHeightTotal += repeatHeightTotal;
}
}
// Compute the number of copies of the repeat symbol we will need
var repeatCount = Math.ceil(
(heightTotal - minHeight) / (middleFactor * repeatHeightTotal));
// Compute the total height of the delimiter including all the symbols
var realHeightTotal =
minHeight + repeatCount * middleFactor * repeatHeightTotal;
// The center of the delimiter is placed at the center of the axis. Note
// that in this context, "center" means that the delimiter should be
@ -275,39 +272,18 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
var i;
if (middle === null) {
// Calculate the number of repeated symbols we need
var repeatHeight = realHeightTotal - topHeightTotal - bottomHeightTotal;
var symbolCount = Math.ceil(repeatHeight / repeatHeightTotal);
// Add that many symbols
for (i = 0; i < symbolCount; i++) {
for (i = 0; i < repeatCount; i++) {
inners.push(makeInner(repeat, font, mode));
}
} else {
// When there is a middle bit, we need the middle part and two repeated
// sections
// Calculate the number of symbols needed for the top and bottom
// repeated parts
var topRepeatHeight =
realHeightTotal / 2 - topHeightTotal - middleHeightTotal / 2;
var topSymbolCount = Math.ceil(topRepeatHeight / repeatHeightTotal);
var bottomRepeatHeight =
realHeightTotal / 2 - topHeightTotal - middleHeightTotal / 2;
var bottomSymbolCount =
Math.ceil(bottomRepeatHeight / repeatHeightTotal);
// Add the top repeated part
for (i = 0; i < topSymbolCount; i++) {
for (i = 0; i < repeatCount; i++) {
inners.push(makeInner(repeat, font, mode));
}
// Add the middle piece
inners.push(makeInner(middle, font, mode));
// Add the bottom repeated part
for (i = 0; i < bottomSymbolCount; i++) {
for (i = 0; i < repeatCount; i++) {
inners.push(makeInner(repeat, font, mode));
}
}