diff --git a/src/delimiter.js b/src/delimiter.js index 99ee1f2a35..3ceb31a05c 100644 --- a/src/delimiter.js +++ b/src/delimiter.js @@ -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"; @@ -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 @@ -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"; @@ -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({ diff --git a/src/svgGeometry.js b/src/svgGeometry.js index 8307cb0542..96af2ac304 100644 --- a/src/svgGeometry.js +++ b/src/svgGeometry.js @@ -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."); + } +}; diff --git a/test/screenshotter/images/Arrays-chrome.png b/test/screenshotter/images/Arrays-chrome.png index 04d1862879..987d18651e 100644 Binary files a/test/screenshotter/images/Arrays-chrome.png and b/test/screenshotter/images/Arrays-chrome.png differ diff --git a/test/screenshotter/images/Arrays-firefox.png b/test/screenshotter/images/Arrays-firefox.png index 74beffcc9e..6aacc39218 100644 Binary files a/test/screenshotter/images/Arrays-firefox.png and b/test/screenshotter/images/Arrays-firefox.png differ diff --git a/test/screenshotter/images/Arrays-safari.png b/test/screenshotter/images/Arrays-safari.png index 30fb4c394a..c1d40cdfbd 100644 Binary files a/test/screenshotter/images/Arrays-safari.png and b/test/screenshotter/images/Arrays-safari.png differ diff --git a/test/screenshotter/images/CD-chrome.png b/test/screenshotter/images/CD-chrome.png index d5cd1c11a4..d171decb5c 100644 Binary files a/test/screenshotter/images/CD-chrome.png and b/test/screenshotter/images/CD-chrome.png differ diff --git a/test/screenshotter/images/CD-firefox.png b/test/screenshotter/images/CD-firefox.png index db5918220b..6d9c289dfe 100644 Binary files a/test/screenshotter/images/CD-firefox.png and b/test/screenshotter/images/CD-firefox.png differ diff --git a/test/screenshotter/images/CD-safari.png b/test/screenshotter/images/CD-safari.png index 3103b80baf..e25ba89baa 100644 Binary files a/test/screenshotter/images/CD-safari.png and b/test/screenshotter/images/CD-safari.png differ diff --git a/test/screenshotter/images/DeepFontSizing-chrome.png b/test/screenshotter/images/DeepFontSizing-chrome.png index 776bc6c6b4..5195d76cf0 100644 Binary files a/test/screenshotter/images/DeepFontSizing-chrome.png and b/test/screenshotter/images/DeepFontSizing-chrome.png differ diff --git a/test/screenshotter/images/DeepFontSizing-firefox.png b/test/screenshotter/images/DeepFontSizing-firefox.png index 44a90b1161..edf8c1c96b 100644 Binary files a/test/screenshotter/images/DeepFontSizing-firefox.png and b/test/screenshotter/images/DeepFontSizing-firefox.png differ diff --git a/test/screenshotter/images/DeepFontSizing-safari.png b/test/screenshotter/images/DeepFontSizing-safari.png index 6024fb5d54..fd57f6cd78 100644 Binary files a/test/screenshotter/images/DeepFontSizing-safari.png and b/test/screenshotter/images/DeepFontSizing-safari.png differ diff --git a/test/screenshotter/images/DelimiterSizing-chrome.png b/test/screenshotter/images/DelimiterSizing-chrome.png index fb62045a87..b407a4d788 100644 Binary files a/test/screenshotter/images/DelimiterSizing-chrome.png and b/test/screenshotter/images/DelimiterSizing-chrome.png differ diff --git a/test/screenshotter/images/DelimiterSizing-firefox.png b/test/screenshotter/images/DelimiterSizing-firefox.png index 73cae9c753..10db9e9777 100644 Binary files a/test/screenshotter/images/DelimiterSizing-firefox.png and b/test/screenshotter/images/DelimiterSizing-firefox.png differ diff --git a/test/screenshotter/images/DelimiterSizing-safari.png b/test/screenshotter/images/DelimiterSizing-safari.png index 2493a4ae4b..08e9906349 100644 Binary files a/test/screenshotter/images/DelimiterSizing-safari.png and b/test/screenshotter/images/DelimiterSizing-safari.png differ diff --git a/test/screenshotter/images/ExtensibleArrows-chrome.png b/test/screenshotter/images/ExtensibleArrows-chrome.png index 3fdceb5dc8..797202475b 100644 Binary files a/test/screenshotter/images/ExtensibleArrows-chrome.png and b/test/screenshotter/images/ExtensibleArrows-chrome.png differ diff --git a/test/screenshotter/images/ExtensibleArrows-firefox.png b/test/screenshotter/images/ExtensibleArrows-firefox.png index df21c0c12e..6da45aa494 100644 Binary files a/test/screenshotter/images/ExtensibleArrows-firefox.png and b/test/screenshotter/images/ExtensibleArrows-firefox.png differ diff --git a/test/screenshotter/images/ExtensibleArrows-safari.png b/test/screenshotter/images/ExtensibleArrows-safari.png index 71b2d5248c..b772499bf6 100644 Binary files a/test/screenshotter/images/ExtensibleArrows-safari.png and b/test/screenshotter/images/ExtensibleArrows-safari.png differ diff --git a/test/screenshotter/images/LowerAccent-chrome.png b/test/screenshotter/images/LowerAccent-chrome.png index 48f3016902..4cbe0a4c13 100644 Binary files a/test/screenshotter/images/LowerAccent-chrome.png and b/test/screenshotter/images/LowerAccent-chrome.png differ diff --git a/test/screenshotter/images/LowerAccent-firefox.png b/test/screenshotter/images/LowerAccent-firefox.png index 730ece3142..78f3567301 100644 Binary files a/test/screenshotter/images/LowerAccent-firefox.png and b/test/screenshotter/images/LowerAccent-firefox.png differ diff --git a/test/screenshotter/images/LowerAccent-safari.png b/test/screenshotter/images/LowerAccent-safari.png index 2c1ada81c8..08ebcd3b4a 100644 Binary files a/test/screenshotter/images/LowerAccent-safari.png and b/test/screenshotter/images/LowerAccent-safari.png differ diff --git a/test/screenshotter/images/StretchyAccent-chrome.png b/test/screenshotter/images/StretchyAccent-chrome.png index a350b55f1c..2f2b2f018c 100644 Binary files a/test/screenshotter/images/StretchyAccent-chrome.png and b/test/screenshotter/images/StretchyAccent-chrome.png differ diff --git a/test/screenshotter/images/StretchyAccent-firefox.png b/test/screenshotter/images/StretchyAccent-firefox.png index 5ed6039608..99107f62a7 100644 Binary files a/test/screenshotter/images/StretchyAccent-firefox.png and b/test/screenshotter/images/StretchyAccent-firefox.png differ diff --git a/test/screenshotter/images/StretchyAccent-safari.png b/test/screenshotter/images/StretchyAccent-safari.png index a767bdf6b0..467d41880a 100644 Binary files a/test/screenshotter/images/StretchyAccent-safari.png and b/test/screenshotter/images/StretchyAccent-safari.png differ diff --git a/test/screenshotter/images/SupSubHorizSpacing-chrome.png b/test/screenshotter/images/SupSubHorizSpacing-chrome.png index 0c016b79b8..f15e76c7f2 100644 Binary files a/test/screenshotter/images/SupSubHorizSpacing-chrome.png and b/test/screenshotter/images/SupSubHorizSpacing-chrome.png differ diff --git a/test/screenshotter/images/SupSubHorizSpacing-firefox.png b/test/screenshotter/images/SupSubHorizSpacing-firefox.png index 87953bf456..80eaf2bf8b 100644 Binary files a/test/screenshotter/images/SupSubHorizSpacing-firefox.png and b/test/screenshotter/images/SupSubHorizSpacing-firefox.png differ diff --git a/test/screenshotter/images/SupSubHorizSpacing-safari.png b/test/screenshotter/images/SupSubHorizSpacing-safari.png index 610168aa6f..a37a3e5c32 100644 Binary files a/test/screenshotter/images/SupSubHorizSpacing-safari.png and b/test/screenshotter/images/SupSubHorizSpacing-safari.png differ