Skip to content

Commit

Permalink
fix: Use SVGs for some stacked delims (#3686)
Browse files Browse the repository at this point in the history
* fix: Use SVGs for some stacked delims

* Account for script level & correct some geometry

* Fix script level adjustment

* Updated screenshotter images

* Change \vert to round cap

* Fix \vert geometry

* Update screenshotter images
  • Loading branch information
ronkok committed Aug 28, 2022
1 parent 7530849 commit 8a65a2e
Show file tree
Hide file tree
Showing 26 changed files with 124 additions and 25 deletions.
93 changes: 68 additions & 25 deletions src/delimiter.js
Expand Up @@ -25,7 +25,7 @@ import ParseError from "./ParseError";
import Style from "./Style";

import {PathNode, SvgNode, SymbolNode} from "./domTree";
import {sqrtPath, innerPath} from "./svgGeometry";
import {sqrtPath, innerPath, tallDelim} from "./svgGeometry";
import buildCommon from "./buildCommon";
import {getCharacterMetrics} from "./fontMetrics";
import symbols from "./symbols";
Expand Down Expand Up @@ -229,6 +229,8 @@ const makeStackedDelim = function(
let middle;
let repeat;
let bottom;
let svgLabel = "";
let viewBoxWidth = 0;
top = repeat = bottom = delim;
middle = null;
// Also keep track of what font the delimiters are in
Expand All @@ -255,44 +257,64 @@ const makeStackedDelim = function(
bottom = "\\Downarrow";
} else if (utils.contains(verts, delim)) {
repeat = "\u2223";
svgLabel = "vert";
viewBoxWidth = 333;
} else if (utils.contains(doubleVerts, delim)) {
repeat = "\u2225";
svgLabel = "doublevert";
viewBoxWidth = 556;
} else if (delim === "[" || delim === "\\lbrack") {
top = "\u23a1";
repeat = "\u23a2";
bottom = "\u23a3";
font = "Size4-Regular";
svgLabel = "lbrack";
viewBoxWidth = 667;
} else if (delim === "]" || delim === "\\rbrack") {
top = "\u23a4";
repeat = "\u23a5";
bottom = "\u23a6";
font = "Size4-Regular";
svgLabel = "rbrack";
viewBoxWidth = 667;
} else if (delim === "\\lfloor" || delim === "\u230a") {
repeat = top = "\u23a2";
bottom = "\u23a3";
font = "Size4-Regular";
svgLabel = "lfloor";
viewBoxWidth = 667;
} else if (delim === "\\lceil" || delim === "\u2308") {
top = "\u23a1";
repeat = bottom = "\u23a2";
font = "Size4-Regular";
svgLabel = "lceil";
viewBoxWidth = 667;
} else if (delim === "\\rfloor" || delim === "\u230b") {
repeat = top = "\u23a5";
bottom = "\u23a6";
font = "Size4-Regular";
svgLabel = "rfloor";
viewBoxWidth = 667;
} else if (delim === "\\rceil" || delim === "\u2309") {
top = "\u23a4";
repeat = bottom = "\u23a5";
font = "Size4-Regular";
svgLabel = "rceil";
viewBoxWidth = 667;
} else if (delim === "(" || delim === "\\lparen") {
top = "\u239b";
repeat = "\u239c";
bottom = "\u239d";
font = "Size4-Regular";
svgLabel = "lparen";
viewBoxWidth = 875;
} else if (delim === ")" || delim === "\\rparen") {
top = "\u239e";
repeat = "\u239f";
bottom = "\u23a0";
font = "Size4-Regular";
svgLabel = "rparen";
viewBoxWidth = 875;
} else if (delim === "\\{" || delim === "\\lbrace") {
top = "\u23a7";
middle = "\u23a8";
Expand Down Expand Up @@ -365,38 +387,59 @@ const makeStackedDelim = function(
// Calculate the depth
const depth = realHeightTotal / 2 - axisHeight;


// Now, we start building the pieces that will go into the vlist
// Keep a list of the pieces of the stacked delimiter
const stack = [];

// Add the bottom symbol
stack.push(makeGlyphSpan(bottom, font, mode));
stack.push(lap); // overlap

if (middle === null) {
// The middle section will be an SVG. Make it an extra 0.016em tall.
// We'll overlap by 0.008em at top and bottom.
const innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal
+ 2 * lapInEms;
stack.push(makeInner(repeat, innerHeight, options));
if (svgLabel.length > 0) {
// Instead of stacking glyphs, create a single SVG.
// This evades browser problems with imprecise positioning of spans.
const midHeight = realHeightTotal - topHeightTotal - bottomHeightTotal;
const viewBoxHeight = Math.round(realHeightTotal * 1000);
const pathStr = tallDelim(svgLabel, Math.round(midHeight * 1000));
const path = new PathNode(svgLabel, pathStr);
const width = (viewBoxWidth / 1000).toFixed(3) + "em";
const height = (viewBoxHeight / 1000).toFixed(3) + "em";
const svg = new SvgNode([path], {
"width": width,
"height": height,
"viewBox": `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
});
const wrapper = buildCommon.makeSvgSpan([], [svg], options);
wrapper.height = viewBoxHeight / 1000;
wrapper.style.width = width;
wrapper.style.height = height;
stack.push({type: "elem", elem: wrapper});
} else {
// When there is a middle bit, we need the middle part and two repeated
// sections
const innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal -
middleHeightTotal) / 2 + 2 * lapInEms;
stack.push(makeInner(repeat, innerHeight, options));
// Now insert the middle of the brace.
stack.push(lap);
stack.push(makeGlyphSpan(middle, font, mode));
// Stack glyphs
// Start by adding the bottom symbol
stack.push(makeGlyphSpan(bottom, font, mode));
stack.push(lap); // overlap

if (middle === null) {
// The middle section will be an SVG. Make it an extra 0.016em tall.
// We'll overlap by 0.008em at top and bottom.
const innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal
+ 2 * lapInEms;
stack.push(makeInner(repeat, innerHeight, options));
} else {
// When there is a middle bit, we need the middle part and two repeated
// sections
const innerHeight = (realHeightTotal - topHeightTotal -
bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms;
stack.push(makeInner(repeat, innerHeight, options));
// Now insert the middle of the brace.
stack.push(lap);
stack.push(makeGlyphSpan(middle, font, mode));
stack.push(lap);
stack.push(makeInner(repeat, innerHeight, options));
}

// Add the top symbol
stack.push(lap);
stack.push(makeInner(repeat, innerHeight, options));
stack.push(makeGlyphSpan(top, font, mode));
}

// Add the top symbol
stack.push(lap);
stack.push(makeGlyphSpan(top, font, mode));

// Finally, build the vlist
const newOptions = options.havingBaseStyle(Style.TEXT);
const inner = buildCommon.makeVList({
Expand Down
56 changes: 56 additions & 0 deletions src/svgGeometry.js
Expand Up @@ -487,3 +487,59 @@ c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,
c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z
M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z`,
};

export const tallDelim = function(label: string, midHeight: number): string {
switch (label) {
case "lbrack":
return `M403 1759 V84 H666 V0 H319 V1759 v${midHeight} v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v${midHeight} v1759 h84z`;
case "rbrack":
return `M347 1759 V0 H0 V84 H263 V1759 v${midHeight} v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v${midHeight} v1759 h84z`;
case "vert":
return `M145 15 v585 v${midHeight} v585 c2.667,10,9.667,15,21,15
c10,0,16.667,-5,20,-15 v-585 v${-midHeight} v-585 c-2.667,-10,-9.667,-15,-21,-15
c-10,0,-16.667,5,-20,15z M188 15 H145 v585 v${midHeight} v585 h43z`;
case "doublevert":
return `M145 15 v585 v${midHeight} v585 c2.667,10,9.667,15,21,15
c10,0,16.667,-5,20,-15 v-585 v${-midHeight} v-585 c-2.667,-10,-9.667,-15,-21,-15
c-10,0,-16.667,5,-20,15z M188 15 H145 v585 v${midHeight} v585 h43z
M367 15 v585 v${midHeight} v585 c2.667,10,9.667,15,21,15
c10,0,16.667,-5,20,-15 v-585 v${-midHeight} v-585 c-2.667,-10,-9.667,-15,-21,-15
c-10,0,-16.667,5,-20,15z M410 15 H367 v585 v${midHeight} v585 h43z`;
case "lfloor":
return `M319 602 V0 H403 V602 v${midHeight} v1715 h263 v84 H319z
MM319 602 V0 H403 V602 v${midHeight} v1715 H319z`;
case "rfloor":
return `M319 602 V0 H403 V602 v${midHeight} v1799 H0 v-84 H319z
MM319 602 V0 H403 V602 v${midHeight} v1715 H319z`;
case "lceil":
return `M403 1759 V84 H666 V0 H319 V1759 v${midHeight} v602 h84z
M403 1759 V0 H319 V1759 v${midHeight} v602 h84z`;
case "rceil":
return `M347 1759 V0 H0 V84 H263 V1759 v${midHeight} v602 h84z
M347 1759 V0 h-84 V1759 v${midHeight} v602 h84z`;
case "lparen":
return `M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1
c-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,
-36,557 l0,${midHeight + 84}c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,
949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9
c0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,
-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189
l0,-${midHeight + 92}c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,
-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z`;
case "rparen":
return `M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,
63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5
c11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,${midHeight + 9}
c-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664
c-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11
c0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17
c242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558
l0,-${midHeight + 144}c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,
-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z`;
default:
// We should not ever get here.
throw new Error("Unknown stretchy delimiter.");
}
};
Binary file modified test/screenshotter/images/Arrays-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/Arrays-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/Arrays-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/CD-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/CD-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/CD-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/DeepFontSizing-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/DeepFontSizing-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/DeepFontSizing-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/DelimiterSizing-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/DelimiterSizing-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/DelimiterSizing-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/ExtensibleArrows-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/ExtensibleArrows-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/ExtensibleArrows-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/LowerAccent-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/LowerAccent-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/LowerAccent-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/StretchyAccent-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/StretchyAccent-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/StretchyAccent-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/SupSubHorizSpacing-chrome.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/SupSubHorizSpacing-firefox.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/screenshotter/images/SupSubHorizSpacing-safari.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8a65a2e

Please sign in to comment.