1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | import ParseError from "./ParseError";
|
25 | import Style from "./Style";
|
26 |
|
27 | import {PathNode, SvgNode, SymbolNode} from "./domTree";
|
28 | import buildCommon from "./buildCommon";
|
29 | import {getCharacterMetrics} from "./fontMetrics";
|
30 | import symbols from "./symbols";
|
31 | import utils from "./utils";
|
32 |
|
33 | import type Options from "./Options";
|
34 | import type {CharacterMetrics} from "./fontMetrics";
|
35 | import type {HtmlDomNode, DomSpan, SvgSpan} from "./domTree";
|
36 | import type {Mode} from "./types";
|
37 | import type {StyleInterface} from "./Style";
|
38 | import type {VListElem} from "./buildCommon";
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 | const getMetrics = function(
|
45 | symbol: string,
|
46 | font: string,
|
47 | mode: Mode,
|
48 | ): CharacterMetrics {
|
49 | const replace = symbols.math[symbol] && symbols.math[symbol].replace;
|
50 | const metrics =
|
51 | getCharacterMetrics(replace || symbol, font, mode);
|
52 | if (!metrics) {
|
53 | throw new Error(`Unsupported symbol ${symbol} and font size ${font}.`);
|
54 | }
|
55 | return metrics;
|
56 | };
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | const styleWrap = function(
|
63 | delim: HtmlDomNode,
|
64 | toStyle: StyleInterface,
|
65 | options: Options,
|
66 | classes: string[],
|
67 | ): DomSpan {
|
68 | const newOptions = options.havingBaseStyle(toStyle);
|
69 |
|
70 | const span = buildCommon.makeSpan(
|
71 | classes.concat(newOptions.sizingClasses(options)),
|
72 | [delim], options);
|
73 |
|
74 | const delimSizeMultiplier =
|
75 | newOptions.sizeMultiplier / options.sizeMultiplier;
|
76 | span.height *= delimSizeMultiplier;
|
77 | span.depth *= delimSizeMultiplier;
|
78 | span.maxFontSize = newOptions.sizeMultiplier;
|
79 |
|
80 | return span;
|
81 | };
|
82 |
|
83 | const centerSpan = function(
|
84 | span: DomSpan,
|
85 | options: Options,
|
86 | style: StyleInterface,
|
87 | ) {
|
88 | const newOptions = options.havingBaseStyle(style);
|
89 | const shift =
|
90 | (1 - options.sizeMultiplier / newOptions.sizeMultiplier) *
|
91 | options.fontMetrics().axisHeight;
|
92 |
|
93 | span.classes.push("delimcenter");
|
94 | span.style.top = shift + "em";
|
95 | span.height -= shift;
|
96 | span.depth += shift;
|
97 | };
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 | const makeSmallDelim = function(
|
105 | delim: string,
|
106 | style: StyleInterface,
|
107 | center: boolean,
|
108 | options: Options,
|
109 | mode: Mode,
|
110 | classes: string[],
|
111 | ): DomSpan {
|
112 | const text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
|
113 | const span = styleWrap(text, style, options, classes);
|
114 | if (center) {
|
115 | centerSpan(span, options, style);
|
116 | }
|
117 | return span;
|
118 | };
|
119 |
|
120 |
|
121 |
|
122 |
|
123 | const mathrmSize = function(
|
124 | value: string,
|
125 | size: number,
|
126 | mode: Mode,
|
127 | options: Options,
|
128 | ): SymbolNode {
|
129 | return buildCommon.makeSymbol(value, "Size" + size + "-Regular",
|
130 | mode, options);
|
131 | };
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | const makeLargeDelim = function(delim,
|
138 | size: number,
|
139 | center: boolean,
|
140 | options: Options,
|
141 | mode: Mode,
|
142 | classes: string[],
|
143 | ): DomSpan {
|
144 | const inner = mathrmSize(delim, size, mode, options);
|
145 | const span = styleWrap(
|
146 | buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options),
|
147 | Style.TEXT, options, classes);
|
148 | if (center) {
|
149 | centerSpan(span, options, Style.TEXT);
|
150 | }
|
151 | return span;
|
152 | };
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 | const makeInner = function(
|
159 | symbol: string,
|
160 | font: "Size1-Regular" | "Size4-Regular",
|
161 | mode: Mode,
|
162 | ): VListElem {
|
163 | let sizeClass;
|
164 |
|
165 | if (font === "Size1-Regular") {
|
166 | sizeClass = "delim-size1";
|
167 | } else {
|
168 | sizeClass = "delim-size4";
|
169 | }
|
170 |
|
171 | const inner = buildCommon.makeSpan(
|
172 | ["delimsizinginner", sizeClass],
|
173 | [buildCommon.makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]);
|
174 |
|
175 |
|
176 |
|
177 | return {type: "elem", elem: inner};
|
178 | };
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 | const makeStackedDelim = function(
|
185 | delim: string,
|
186 | heightTotal: number,
|
187 | center: boolean,
|
188 | options: Options,
|
189 | mode: Mode,
|
190 | classes: string[],
|
191 | ): DomSpan {
|
192 |
|
193 |
|
194 | let top;
|
195 | let middle;
|
196 | let repeat;
|
197 | let bottom;
|
198 | top = repeat = bottom = delim;
|
199 | middle = null;
|
200 |
|
201 | let font = "Size1-Regular";
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | if (delim === "\\uparrow") {
|
207 | repeat = bottom = "\u23d0";
|
208 | } else if (delim === "\\Uparrow") {
|
209 | repeat = bottom = "\u2016";
|
210 | } else if (delim === "\\downarrow") {
|
211 | top = repeat = "\u23d0";
|
212 | } else if (delim === "\\Downarrow") {
|
213 | top = repeat = "\u2016";
|
214 | } else if (delim === "\\updownarrow") {
|
215 | top = "\\uparrow";
|
216 | repeat = "\u23d0";
|
217 | bottom = "\\downarrow";
|
218 | } else if (delim === "\\Updownarrow") {
|
219 | top = "\\Uparrow";
|
220 | repeat = "\u2016";
|
221 | bottom = "\\Downarrow";
|
222 | } else if (delim === "[" || delim === "\\lbrack") {
|
223 | top = "\u23a1";
|
224 | repeat = "\u23a2";
|
225 | bottom = "\u23a3";
|
226 | font = "Size4-Regular";
|
227 | } else if (delim === "]" || delim === "\\rbrack") {
|
228 | top = "\u23a4";
|
229 | repeat = "\u23a5";
|
230 | bottom = "\u23a6";
|
231 | font = "Size4-Regular";
|
232 | } else if (delim === "\\lfloor" || delim === "\u230a") {
|
233 | repeat = top = "\u23a2";
|
234 | bottom = "\u23a3";
|
235 | font = "Size4-Regular";
|
236 | } else if (delim === "\\lceil" || delim === "\u2308") {
|
237 | top = "\u23a1";
|
238 | repeat = bottom = "\u23a2";
|
239 | font = "Size4-Regular";
|
240 | } else if (delim === "\\rfloor" || delim === "\u230b") {
|
241 | repeat = top = "\u23a5";
|
242 | bottom = "\u23a6";
|
243 | font = "Size4-Regular";
|
244 | } else if (delim === "\\rceil" || delim === "\u2309") {
|
245 | top = "\u23a4";
|
246 | repeat = bottom = "\u23a5";
|
247 | font = "Size4-Regular";
|
248 | } else if (delim === "(" || delim === "\\lparen") {
|
249 | top = "\u239b";
|
250 | repeat = "\u239c";
|
251 | bottom = "\u239d";
|
252 | font = "Size4-Regular";
|
253 | } else if (delim === ")" || delim === "\\rparen") {
|
254 | top = "\u239e";
|
255 | repeat = "\u239f";
|
256 | bottom = "\u23a0";
|
257 | font = "Size4-Regular";
|
258 | } else if (delim === "\\{" || delim === "\\lbrace") {
|
259 | top = "\u23a7";
|
260 | middle = "\u23a8";
|
261 | bottom = "\u23a9";
|
262 | repeat = "\u23aa";
|
263 | font = "Size4-Regular";
|
264 | } else if (delim === "\\}" || delim === "\\rbrace") {
|
265 | top = "\u23ab";
|
266 | middle = "\u23ac";
|
267 | bottom = "\u23ad";
|
268 | repeat = "\u23aa";
|
269 | font = "Size4-Regular";
|
270 | } else if (delim === "\\lgroup" || delim === "\u27ee") {
|
271 | top = "\u23a7";
|
272 | bottom = "\u23a9";
|
273 | repeat = "\u23aa";
|
274 | font = "Size4-Regular";
|
275 | } else if (delim === "\\rgroup" || delim === "\u27ef") {
|
276 | top = "\u23ab";
|
277 | bottom = "\u23ad";
|
278 | repeat = "\u23aa";
|
279 | font = "Size4-Regular";
|
280 | } else if (delim === "\\lmoustache" || delim === "\u23b0") {
|
281 | top = "\u23a7";
|
282 | bottom = "\u23ad";
|
283 | repeat = "\u23aa";
|
284 | font = "Size4-Regular";
|
285 | } else if (delim === "\\rmoustache" || delim === "\u23b1") {
|
286 | top = "\u23ab";
|
287 | bottom = "\u23a9";
|
288 | repeat = "\u23aa";
|
289 | font = "Size4-Regular";
|
290 | }
|
291 |
|
292 |
|
293 | const topMetrics = getMetrics(top, font, mode);
|
294 | const topHeightTotal = topMetrics.height + topMetrics.depth;
|
295 | const repeatMetrics = getMetrics(repeat, font, mode);
|
296 | const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
|
297 | const bottomMetrics = getMetrics(bottom, font, mode);
|
298 | const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
|
299 | let middleHeightTotal = 0;
|
300 | let middleFactor = 1;
|
301 | if (middle !== null) {
|
302 | const middleMetrics = getMetrics(middle, font, mode);
|
303 | middleHeightTotal = middleMetrics.height + middleMetrics.depth;
|
304 | middleFactor = 2;
|
305 | }
|
306 |
|
307 |
|
308 |
|
309 | const minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal;
|
310 |
|
311 |
|
312 | const repeatCount = Math.ceil(
|
313 | (heightTotal - minHeight) / (middleFactor * repeatHeightTotal));
|
314 |
|
315 |
|
316 | const realHeightTotal =
|
317 | minHeight + repeatCount * middleFactor * repeatHeightTotal;
|
318 |
|
319 |
|
320 |
|
321 |
|
322 |
|
323 | let axisHeight = options.fontMetrics().axisHeight;
|
324 | if (center) {
|
325 | axisHeight *= options.sizeMultiplier;
|
326 | }
|
327 |
|
328 | const depth = realHeightTotal / 2 - axisHeight;
|
329 |
|
330 |
|
331 |
|
332 |
|
333 | const inners = [];
|
334 |
|
335 |
|
336 | inners.push(makeInner(bottom, font, mode));
|
337 |
|
338 | if (middle === null) {
|
339 |
|
340 | for (let i = 0; i < repeatCount; i++) {
|
341 | inners.push(makeInner(repeat, font, mode));
|
342 | }
|
343 | } else {
|
344 |
|
345 |
|
346 | for (let i = 0; i < repeatCount; i++) {
|
347 | inners.push(makeInner(repeat, font, mode));
|
348 | }
|
349 | inners.push(makeInner(middle, font, mode));
|
350 | for (let i = 0; i < repeatCount; i++) {
|
351 | inners.push(makeInner(repeat, font, mode));
|
352 | }
|
353 | }
|
354 |
|
355 |
|
356 | inners.push(makeInner(top, font, mode));
|
357 |
|
358 |
|
359 | const newOptions = options.havingBaseStyle(Style.TEXT);
|
360 | const inner = buildCommon.makeVList({
|
361 | positionType: "bottom",
|
362 | positionData: depth,
|
363 | children: inners,
|
364 | }, newOptions);
|
365 |
|
366 | return styleWrap(
|
367 | buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions),
|
368 | Style.TEXT, options, classes);
|
369 | };
|
370 |
|
371 |
|
372 |
|
373 | const vbPad = 80;
|
374 | const emPad = 0.08;
|
375 |
|
376 | const sqrtSvg = function(
|
377 | sqrtName: string,
|
378 | height: number,
|
379 | viewBoxHeight: number,
|
380 | options: Options,
|
381 | ): SvgSpan {
|
382 | let alternate;
|
383 | if (sqrtName === "sqrtTall") {
|
384 |
|
385 |
|
386 |
|
387 |
|
388 | const vertSegment = viewBoxHeight - 54 - vbPad;
|
389 | alternate = `M702 ${vbPad}H400000v40H742v${vertSegment}l-4 4-4 4c-.667.7
|
390 | -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1h-12l-28-84c-16.667-52-96.667
|
391 | -294.333-240-727l-212 -643 -85 170c-4-3.333-8.333-7.667-13 -13l-13-13l77-155
|
392 | 77-156c66 199.333 139 419.667 219 661 l218 661zM702 ${vbPad}H400000v40H742z`;
|
393 | }
|
394 | const pathNode = new PathNode(sqrtName, alternate);
|
395 |
|
396 | const svg = new SvgNode([pathNode], {
|
397 |
|
398 | "width": "400em",
|
399 | "height": height + "em",
|
400 | "viewBox": "0 0 400000 " + viewBoxHeight,
|
401 | "preserveAspectRatio": "xMinYMin slice",
|
402 | });
|
403 |
|
404 | return buildCommon.makeSvgSpan(["hide-tail"], [svg], options);
|
405 | };
|
406 |
|
407 |
|
408 |
|
409 |
|
410 | const makeSqrtImage = function(
|
411 | height: number,
|
412 | options: Options,
|
413 | ): {
|
414 | span: SvgSpan,
|
415 | ruleWidth: number,
|
416 | advanceWidth: number,
|
417 | } {
|
418 |
|
419 |
|
420 | const newOptions = options.havingBaseSizing();
|
421 |
|
422 |
|
423 | const delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier,
|
424 | stackLargeDelimiterSequence, newOptions);
|
425 |
|
426 | let sizeMultiplier = newOptions.sizeMultiplier;
|
427 |
|
428 |
|
429 | let span;
|
430 | let spanHeight = 0;
|
431 | let texHeight = 0;
|
432 | let viewBoxHeight = 0;
|
433 | let advanceWidth;
|
434 |
|
435 |
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
|
441 | if (delim.type === "small") {
|
442 |
|
443 | viewBoxHeight = 1000 + vbPad;
|
444 | if (height < 1.0) {
|
445 | sizeMultiplier = 1.0;
|
446 | } else if (height < 1.4) {
|
447 | sizeMultiplier = 0.7;
|
448 | }
|
449 | spanHeight = (1.0 + emPad) / sizeMultiplier;
|
450 | texHeight = 1.00 / sizeMultiplier;
|
451 | span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, options);
|
452 | span.style.minWidth = "0.853em";
|
453 | advanceWidth = 0.833 / sizeMultiplier;
|
454 |
|
455 | } else if (delim.type === "large") {
|
456 |
|
457 | viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size];
|
458 | texHeight = sizeToMaxHeight[delim.size] / sizeMultiplier;
|
459 | spanHeight = (sizeToMaxHeight[delim.size] + emPad) / sizeMultiplier;
|
460 | span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, options);
|
461 | span.style.minWidth = "1.02em";
|
462 | advanceWidth = 1.0 / sizeMultiplier;
|
463 |
|
464 | } else {
|
465 |
|
466 |
|
467 | spanHeight = height + emPad;
|
468 | texHeight = height;
|
469 | viewBoxHeight = Math.floor(1000 * height) + vbPad;
|
470 | span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, options);
|
471 | span.style.minWidth = "0.742em";
|
472 | advanceWidth = 1.056;
|
473 | }
|
474 |
|
475 | span.height = texHeight;
|
476 | span.style.height = spanHeight + "em";
|
477 |
|
478 | return {
|
479 | span,
|
480 | advanceWidth,
|
481 |
|
482 |
|
483 |
|
484 |
|
485 | ruleWidth: options.fontMetrics().sqrtRuleThickness * sizeMultiplier,
|
486 | };
|
487 | };
|
488 |
|
489 |
|
490 |
|
491 | const stackLargeDelimiters = [
|
492 | "(", "\\lparen", ")", "\\rparen",
|
493 | "[", "\\lbrack", "]", "\\rbrack",
|
494 | "\\{", "\\lbrace", "\\}", "\\rbrace",
|
495 | "\\lfloor", "\\rfloor", "\u230a", "\u230b",
|
496 | "\\lceil", "\\rceil", "\u2308", "\u2309",
|
497 | "\\surd",
|
498 | ];
|
499 |
|
500 |
|
501 | const stackAlwaysDelimiters = [
|
502 | "\\uparrow", "\\downarrow", "\\updownarrow",
|
503 | "\\Uparrow", "\\Downarrow", "\\Updownarrow",
|
504 | "|", "\\|", "\\vert", "\\Vert",
|
505 | "\\lvert", "\\rvert", "\\lVert", "\\rVert",
|
506 | "\\lgroup", "\\rgroup", "\u27ee", "\u27ef",
|
507 | "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1",
|
508 | ];
|
509 |
|
510 |
|
511 | const stackNeverDelimiters = [
|
512 | "<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt",
|
513 | ];
|
514 |
|
515 |
|
516 |
|
517 |
|
518 | const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
|
519 |
|
520 |
|
521 |
|
522 |
|
523 | const makeSizedDelim = function(
|
524 | delim: string,
|
525 | size: number,
|
526 | options: Options,
|
527 | mode: Mode,
|
528 | classes: string[],
|
529 | ): DomSpan {
|
530 |
|
531 | if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
|
532 | delim = "\\langle";
|
533 | } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
|
534 | delim = "\\rangle";
|
535 | }
|
536 |
|
537 |
|
538 | if (utils.contains(stackLargeDelimiters, delim) ||
|
539 | utils.contains(stackNeverDelimiters, delim)) {
|
540 | return makeLargeDelim(delim, size, false, options, mode, classes);
|
541 | } else if (utils.contains(stackAlwaysDelimiters, delim)) {
|
542 | return makeStackedDelim(
|
543 | delim, sizeToMaxHeight[size], false, options, mode, classes);
|
544 | } else {
|
545 | throw new ParseError("Illegal delimiter: '" + delim + "'");
|
546 | }
|
547 | };
|
548 |
|
549 |
|
550 |
|
551 |
|
552 |
|
553 |
|
554 |
|
555 |
|
556 |
|
557 |
|
558 |
|
559 |
|
560 |
|
561 | type Delimiter =
|
562 | {type: "small", style: StyleInterface} |
|
563 | {type: "large", size: 1 | 2 | 3 | 4} |
|
564 | {type: "stack"};
|
565 |
|
566 |
|
567 | const stackNeverDelimiterSequence = [
|
568 | {type: "small", style: Style.SCRIPTSCRIPT},
|
569 | {type: "small", style: Style.SCRIPT},
|
570 | {type: "small", style: Style.TEXT},
|
571 | {type: "large", size: 1},
|
572 | {type: "large", size: 2},
|
573 | {type: "large", size: 3},
|
574 | {type: "large", size: 4},
|
575 | ];
|
576 |
|
577 |
|
578 | const stackAlwaysDelimiterSequence = [
|
579 | {type: "small", style: Style.SCRIPTSCRIPT},
|
580 | {type: "small", style: Style.SCRIPT},
|
581 | {type: "small", style: Style.TEXT},
|
582 | {type: "stack"},
|
583 | ];
|
584 |
|
585 |
|
586 |
|
587 | const stackLargeDelimiterSequence = [
|
588 | {type: "small", style: Style.SCRIPTSCRIPT},
|
589 | {type: "small", style: Style.SCRIPT},
|
590 | {type: "small", style: Style.TEXT},
|
591 | {type: "large", size: 1},
|
592 | {type: "large", size: 2},
|
593 | {type: "large", size: 3},
|
594 | {type: "large", size: 4},
|
595 | {type: "stack"},
|
596 | ];
|
597 |
|
598 |
|
599 |
|
600 |
|
601 |
|
602 | const delimTypeToFont = function(type: Delimiter): string {
|
603 | if (type.type === "small") {
|
604 | return "Main-Regular";
|
605 | } else if (type.type === "large") {
|
606 | return "Size" + type.size + "-Regular";
|
607 | } else if (type.type === "stack") {
|
608 | return "Size4-Regular";
|
609 | } else {
|
610 | throw new Error(`Add support for delim type '${type.type}' here.`);
|
611 | }
|
612 | };
|
613 |
|
614 |
|
615 |
|
616 |
|
617 |
|
618 | const traverseSequence = function(
|
619 | delim: string,
|
620 | height: number,
|
621 | sequence: Delimiter[],
|
622 | options: Options,
|
623 | ): Delimiter {
|
624 |
|
625 |
|
626 |
|
627 |
|
628 | const start = Math.min(2, 3 - options.style.size);
|
629 | for (let i = start; i < sequence.length; i++) {
|
630 | if (sequence[i].type === "stack") {
|
631 |
|
632 | break;
|
633 | }
|
634 |
|
635 | const metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math");
|
636 | let heightDepth = metrics.height + metrics.depth;
|
637 |
|
638 |
|
639 |
|
640 |
|
641 | if (sequence[i].type === "small") {
|
642 | const newOptions = options.havingBaseStyle(sequence[i].style);
|
643 | heightDepth *= newOptions.sizeMultiplier;
|
644 | }
|
645 |
|
646 |
|
647 | if (heightDepth > height) {
|
648 | return sequence[i];
|
649 | }
|
650 | }
|
651 |
|
652 |
|
653 | return sequence[sequence.length - 1];
|
654 | };
|
655 |
|
656 |
|
657 |
|
658 |
|
659 |
|
660 | const makeCustomSizedDelim = function(
|
661 | delim: string,
|
662 | height: number,
|
663 | center: boolean,
|
664 | options: Options,
|
665 | mode: Mode,
|
666 | classes: string[],
|
667 | ): DomSpan {
|
668 | if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
|
669 | delim = "\\langle";
|
670 | } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
|
671 | delim = "\\rangle";
|
672 | }
|
673 |
|
674 |
|
675 | let sequence;
|
676 | if (utils.contains(stackNeverDelimiters, delim)) {
|
677 | sequence = stackNeverDelimiterSequence;
|
678 | } else if (utils.contains(stackLargeDelimiters, delim)) {
|
679 | sequence = stackLargeDelimiterSequence;
|
680 | } else {
|
681 | sequence = stackAlwaysDelimiterSequence;
|
682 | }
|
683 |
|
684 |
|
685 | const delimType = traverseSequence(delim, height, sequence, options);
|
686 |
|
687 |
|
688 |
|
689 |
|
690 | if (delimType.type === "small") {
|
691 | return makeSmallDelim(delim, delimType.style, center, options,
|
692 | mode, classes);
|
693 | } else if (delimType.type === "large") {
|
694 | return makeLargeDelim(delim, delimType.size, center, options, mode,
|
695 | classes);
|
696 | } else {
|
697 | return makeStackedDelim(delim, height, center, options, mode,
|
698 | classes);
|
699 | }
|
700 | };
|
701 |
|
702 |
|
703 |
|
704 |
|
705 |
|
706 | const makeLeftRightDelim = function(
|
707 | delim: string,
|
708 | height: number,
|
709 | depth: number,
|
710 | options: Options,
|
711 | mode: Mode,
|
712 | classes: string[],
|
713 | ): DomSpan {
|
714 |
|
715 | const axisHeight =
|
716 | options.fontMetrics().axisHeight * options.sizeMultiplier;
|
717 |
|
718 |
|
719 | const delimiterFactor = 901;
|
720 | const delimiterExtend = 5.0 / options.fontMetrics().ptPerEm;
|
721 |
|
722 | const maxDistFromAxis = Math.max(
|
723 | height - axisHeight, depth + axisHeight);
|
724 |
|
725 | const totalHeight = Math.max(
|
726 |
|
727 |
|
728 |
|
729 |
|
730 |
|
731 |
|
732 |
|
733 |
|
734 |
|
735 | maxDistFromAxis / 500 * delimiterFactor,
|
736 | 2 * maxDistFromAxis - delimiterExtend);
|
737 |
|
738 |
|
739 |
|
740 | return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes);
|
741 | };
|
742 |
|
743 | export default {
|
744 | sqrtImage: makeSqrtImage,
|
745 | sizedDelim: makeSizedDelim,
|
746 | customSizedDelim: makeCustomSizedDelim,
|
747 | leftRightDelim: makeLeftRightDelim,
|
748 | };
|