Skip to content

Commit 79331a1

Browse files
committed
Merge branch stretchy-enum into chtml
2 parents a4fb049 + 9057f6f commit 79331a1

File tree

7 files changed

+117
-72
lines changed

7 files changed

+117
-72
lines changed

mathjax3-ts/output/chtml/BBox.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ export class BBox {
9696
this.pwidth = '';
9797
}
9898

99+
/*
100+
* Set up a bbox for append() and combine() operations
101+
* @return{BBOX} the boox itself (for chaining calls)
102+
*/
103+
public empty() {
104+
this.w = 0;
105+
this.h = this.d = -BIGDIMEN;
106+
return this;
107+
}
108+
99109
/*
100110
* Convert any unspecified values into zeros
101111
*/
@@ -123,15 +133,12 @@ export class BBox {
123133
cbox.x = x;
124134
cbox.x = y;
125135
let rscale = cbox.rscale;
126-
if (x + rscale * (cbox.w + cbox.L + cbox.R) > this.w) {
127-
this.w = x + rscale * (cbox.w + cbox.L + cbox.R);
128-
}
129-
if (y + rscale * cbox.h > this.h) {
130-
this.h = y + rscale * cbox.h;
131-
}
132-
if (rscale * cbox.d - y > this.d) {
133-
this.d = rscale * cbox.d - y;
134-
}
136+
let w = x + rscale * (cbox.w + cbox.L + cbox.R);
137+
let h = y + rscale * cbox.h;
138+
let d = rscale * cbox.d - y;
139+
if (w > this.w) this.w = w;
140+
if (h > this.h) this.h = h;
141+
if (d > this.d) this.d = d;
135142
}
136143

137144
/*

mathjax3-ts/output/chtml/Wrapper.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ import {StyleList} from './CssStyles.js';
4343
*/
4444
export type StringMap = {[key: string]: string};
4545

46-
/*
47-
* The value to use for each spacing size
48-
*/
49-
export const SPACE: StringMap = {
50-
thinmathspace: '1',
51-
mediummathspace: '2',
52-
thickmathspace: '3'
53-
};
54-
5546
/*
5647
* Some standard sizes to use in predefind CSS properties
5748
*/
@@ -268,6 +259,7 @@ export class CHTMLWrapper extends AbstractWrapper<MmlNode, CHTMLWrapper> {
268259
this.getStyles();
269260
this.getVariant();
270261
this.getScale();
262+
this.getSpace();
271263
this.childNodes = node.childNodes.map((child: Node) => {
272264
return this.wrap(child as MmlNode);
273265
});
@@ -324,7 +316,7 @@ export class CHTMLWrapper extends AbstractWrapper<MmlNode, CHTMLWrapper> {
324316
* @return{BBox} The computed bounding box for the wrapped node
325317
*/
326318
protected computeBBox() {
327-
const bbox = BBox.empty();
319+
const bbox = this.bbox.empty();
328320
for (const child of this.childNodes) {
329321
bbox.append(child.getBBox());
330322
}
@@ -453,6 +445,12 @@ export class CHTMLWrapper extends AbstractWrapper<MmlNode, CHTMLWrapper> {
453445
this.bbox.rscale = scale / pscale;
454446
}
455447

448+
protected getSpace() {
449+
const space = this.node.texSpacing();
450+
if (space) {
451+
this.bbox.L = this.length2em(space);
452+
}
453+
}
456454
/*******************************************************************/
457455

458456
/*
@@ -525,10 +523,8 @@ export class CHTMLWrapper extends AbstractWrapper<MmlNode, CHTMLWrapper> {
525523
* FIXME: still need to handle MathML spacing
526524
*/
527525
protected handleSpace() {
528-
const space = this.node.texSpacing();
529-
if (space) {
530-
this.bbox.L = this.length2em(space);
531-
this.chtml.setAttribute('space', SPACE[space]);
526+
if (this.bbox.L) {
527+
this.chtml.setAttribute('space', (this.bbox.L * 18 - 2).toString());
532528
}
533529
}
534530

@@ -620,6 +616,34 @@ export class CHTMLWrapper extends AbstractWrapper<MmlNode, CHTMLWrapper> {
620616
return this.stretch !== DIRECTION.None;
621617
}
622618

619+
/*******************************************************************/
620+
/*
621+
* For debugging
622+
*/
623+
624+
public drawBBox() {
625+
const bbox = this.getBBox();
626+
const box = this.html('mjx-box', {style: {
627+
opacity: .25, 'margin-left': this.em(-bbox.w)
628+
}}, [
629+
this.html('mjx-box', {style: {
630+
height: this.em(bbox.h),
631+
width: this.em(bbox.w),
632+
'background-color': 'red'
633+
}}),
634+
this.html('mjx-box', {style: {
635+
height: this.em(bbox.d),
636+
width: this.em(bbox.w),
637+
'margin-left': this.em(-bbox.w),
638+
'vertical-align': this.em(-bbox.d),
639+
'background-color': 'green'
640+
}})
641+
]);
642+
const node = this.chtml || this.parent.chtml;
643+
node.appendChild(box);
644+
node.style.backgroundColor = '#FFEE00';
645+
}
646+
623647
/*******************************************************************/
624648
/*
625649
* Easy access to some utility routines

mathjax3-ts/output/chtml/Wrappers/mfrac.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,24 @@ export class CHTMLmfrac extends CHTMLWrapper {
4141
display: 'inline-block',
4242
height: '1em',
4343
width: 0,
44-
'vertical-align': '-.2em'
44+
'vertical-align': '-.25em'
4545
},
4646
'mjx-hstrut': {
4747
display: 'inline-block',
48-
height: '.8em',
48+
height: '.75em',
4949
width: 0
5050
},
5151
'mjx-dstrut': {
5252
display: 'inline-block',
53-
height: '.2em',
53+
height: '.25em',
5454
width: 0,
55-
'vertical-align': '-.2em'
55+
'vertical-align': '-.25em'
5656
},
5757

5858
'mjx-frac': {
5959
display: 'inline-block',
6060
'vertical-align': '0.145em',
61-
padding: '0 3px'
61+
padding: '0 .1em'
6262
},
6363
'mjx-dtable': {
6464
display: 'inline-table',
@@ -87,9 +87,9 @@ export class CHTMLmfrac extends CHTMLWrapper {
8787
display: 'block',
8888
'box-sizing': 'border-box',
8989
'min-height': '1px',
90-
height: '.07em',
91-
'border-top': '.07em solid',
92-
margin: '.07em -3px',
90+
height: '.06em',
91+
'border-top': '.06em solid',
92+
margin: '.06em -.1em',
9393
overflow: 'hidden'
9494
}
9595
};
@@ -120,15 +120,15 @@ export class CHTMLmfrac extends CHTMLWrapper {
120120
* @override
121121
*/
122122
public computeBBox() {
123-
const bbox = BBox.empty();
123+
const bbox = this.bbox.empty();
124124
const nbox = this.childNodes[0].getBBox();
125125
const dbox = this.childNodes[1].getBBox();
126126
const pad = (this.node.getProperty('withDelims') as boolean ? this.font.params.nulldelimiterspace : 0);
127127
const a = this.font.params.axis_height;
128128
const t = this.font.params.rule_thickness;
129-
bbox.combine(dbox, pad, a + 1.5 * t + nbox.d);
130-
bbox.combine(nbox, pad, a - 1.5 * t - dbox.h);
131-
bbox.w += pad;
129+
bbox.combine(nbox, pad, a + 1.5 * t + Math.max(nbox.d, .25));
130+
bbox.combine(dbox, pad, a - 1.5 * t - Math.max(dbox.h, .75));
131+
bbox.w += pad + .2;
132132
bbox.clean();
133133
return bbox;
134134
}

mathjax3-ts/output/chtml/Wrappers/mo.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,9 @@ export class CHTMLmo extends CHTMLWrapper {
236236
* Determint variant for vertically/horizontally stretched character
237237
*
238238
* @param{number[]} WH size to stretch to, either [W] or [H, D]
239+
* @param{boolean} exact True if not allowed to use delimiter factor and shortfall
239240
*/
240-
public getStretchedVariant(WH: number[]) {
241+
public getStretchedVariant(WH: number[], exact: boolean = false) {
241242
if (this.stretch) {
242243
let D = this.getWH(WH);
243244
const min = this.getSize('minsize', 0);
@@ -247,8 +248,8 @@ export class CHTMLmo extends CHTMLWrapper {
247248
// then get the minimum size via TeX rules
248249
//
249250
D = Math.max(min, Math.min(max, D));
250-
const m = (min ? D : Math.max(D * this.font.params.delimiterfactor / 1000,
251-
D - this.font.params.delimitershortfall));
251+
const m = (min || exact ? D : Math.max(D * this.font.params.delimiterfactor / 1000,
252+
D - this.font.params.delimitershortfall));
252253
//
253254
// Look through the delimiter sizes for one that matches
254255
//

mathjax3-ts/output/chtml/Wrappers/mroot.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ export class CHTMLmroot extends CHTMLmsqrt {
5555
*/
5656
protected addRoot(ROOT: HTMLElement, root: CHTMLWrapper, sbox: BBox) {
5757
root.toCHTML(ROOT);
58-
const [x, h, dx, scale] = this.getRootDimens(sbox);
58+
const [x, h, dx] = this.getRootDimens(sbox);
5959
const bbox = root.getBBox();
60-
ROOT.style.verticalAlign = this.em(h / scale);
61-
ROOT.style.width = this.em(x / scale);
60+
ROOT.style.verticalAlign = this.em(h);
61+
ROOT.style.width = this.em(x);
6262
if (dx) (ROOT.firstChild as HTMLElement).style.paddingLeft = this.em(dx);
6363
}
6464

@@ -76,24 +76,26 @@ export class CHTMLmroot extends CHTMLmsqrt {
7676
*/
7777
protected getRootDimens(sbox: BBox) {
7878
const surd = this.childNodes[this.surd] as CHTMLmo;
79-
const offset = (surd.size < -1 ? .5 : .6) * sbox.w;
8079
const bbox = this.childNodes[this.root].getBBox();
80+
const offset = (surd.size < 0 ? .5 : .6) * sbox.w;
8181
const {w, rscale} = bbox;
8282
const W = Math.max(w, offset / rscale);
8383
const dx = Math.max(0, W - w);
84-
const h = this.rootHeight(bbox, sbox, offset);
84+
const h = this.rootHeight(bbox, sbox, surd.size);
8585
const x = W * rscale - offset;
86-
return [x, h, dx, rscale];
86+
return [x, h, dx];
8787
}
8888

8989
/*
90-
* @param{BBox} bbox The bbox of the root
90+
* @param{BBox} rbox The bbox of the root
9191
* @param{BBox} sbox The bbox of the surd
92-
* @param{number} offset The computed offset for the root within the surd
92+
* @param{number} size The size of the surd
9393
* @return{number} The height of the root within the surd
9494
*/
95-
protected rootHeight(bbox: BBox, sbox: BBox, offset: number) {
96-
return .45 * (sbox.h + sbox.d - .9) + offset + Math.max(0, bbox.d - .075);
95+
protected rootHeight(rbox: BBox, sbox: BBox, size: number) {
96+
const H = sbox.h + sbox.d;
97+
const b = (size < 0 ? 2 + .3 * (H - 4) : .55 * H) - sbox.d;
98+
return b + Math.max(0, rbox.d * rbox.rscale);
9799
}
98100

99101
}

mathjax3-ts/output/chtml/Wrappers/mspace.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class CHTMLmspace extends CHTMLWrapper {
4949
}
5050
h = Math.max(0, h + d);
5151
if (h) {
52-
chtml.style.height = this.em(Math.max(0, h + d));
52+
chtml.style.height = this.em(Math.max(0, h));
5353
}
5454
if (d) {
5555
chtml.style.verticalAlign = this.em(-d);

mathjax3-ts/output/chtml/Wrappers/msqrt.ts

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {CHTMLWrapperFactory} from '../WrapperFactory.js';
2626
import {CHTMLmo} from './mo.js';
2727
import {BBox} from '../BBox.js';
2828
import {MmlMsqrt} from '../../../core/MmlTree/MmlNodes/msqrt.js';
29-
import {MmlNode, AbstractMmlNode, TextNode} from '../../../core/MmlTree/MmlNode.js';
29+
import {MmlNode, AbstractMmlNode, TextNode, AttributeList} from '../../../core/MmlTree/MmlNode.js';
3030
import {StyleList} from '../CssStyles.js';
3131
import {DIRECTION} from '../FontData.js';
3232

@@ -40,11 +40,19 @@ export class CHTMLmsqrt extends CHTMLWrapper {
4040

4141
public static styles: StyleList = {
4242
'mjx-root': {
43-
display: 'inline-block'
43+
display: 'inline-block',
44+
'white-space': 'nowrap'
4445
},
4546
'mjx-surd': {
4647
display: 'inline-block',
4748
'vertical-align': 'top'
49+
},
50+
'mjx-sqrt': {
51+
display: 'inline-block',
52+
'padding-top': '.07em'
53+
},
54+
'mjx-sqrt > mjx-box': {
55+
'border-top': '.07em solid'
4856
}
4957
};
5058

@@ -87,17 +95,28 @@ export class CHTMLmsqrt extends CHTMLWrapper {
8795
const t = this.font.params.rule_thickness;
8896
const p = (this.node.attributes.get('displaystyle') ? this.font.params.x_height : t);
8997
this.surdH = h + d + 2 * t + p / 4;
90-
surd.getStretchedVariant([this.surdH, 0]);
98+
surd.getStretchedVariant([this.surdH - d, d], true);
9199
}
92100

93101
/*
94-
* Create an mo wrapper with the given text;
102+
* Create an mo wrapper with the given text,
103+
* link it in, and give it the right defaults.
95104
*
96105
* @param{string} text The text for the wrapped element
97106
* @return{CHTMLWrapper} The wrapped MmlMo node
98107
*/
99108
protected createMo(text: string) {
100-
const node = this.wrap(this.mmlNode('mo', {stretchy: true}, [this.mmlText(text)])) as CHTMLmo;
109+
const mmlFactory = (this.node as AbstractMmlNode).factory;
110+
const textNode = (mmlFactory.create('text') as TextNode).setText(text);
111+
const mml = mmlFactory.create('mo', {stretchy: true}, [textNode]);
112+
const attributes = this.node.attributes;
113+
const display = attributes.get('display') as boolean;
114+
const scriptlevel = attributes.get('scriptlevel') as number;
115+
const defaults: AttributeList = {
116+
mathsize: ['math', attributes.get('mathsize')]
117+
};
118+
mml.setInheritedAttributes(defaults, display, scriptlevel, false);
119+
const node = this.wrap(mml) as CHTMLmo;
101120
node.parent = this;
102121
this.childNodes.push(node);
103122
return node;
@@ -115,9 +134,6 @@ export class CHTMLmsqrt extends CHTMLWrapper {
115134
const sbox = surd.getBBox();
116135
const bbox = base.getBBox();
117136
const [p, q] = this.getPQ(sbox);
118-
const [x] = this.getRootDimens(sbox);
119-
const t = this.font.params.rule_thickness;
120-
const T = this.font.params.surd_height;
121137
//
122138
// Create the HTML structure for the root
123139
//
@@ -127,14 +143,9 @@ export class CHTMLmsqrt extends CHTMLWrapper {
127143
ROOT = CHTML.appendChild(this.html('mjx-root'));
128144
root = this.childNodes[this.root];
129145
}
130-
const SQRT = CHTML.appendChild(this.html('mjx-box', {
131-
style: {paddingTop: this.px(2 * t - T, 1)}
132-
}, [
146+
const SQRT = CHTML.appendChild(this.html('mjx-sqrt', {}, [
133147
SURD = this.html('mjx-surd'),
134-
BASE = this.html('mjx-box', {style: {
135-
paddingTop: this.px(q, 1),
136-
borderTop: this.px(T * bbox.scale, 1) + ' solid'
137-
}})
148+
BASE = this.html('mjx-box', {style: {paddingTop: this.em(q)}})
138149
]));
139150
//
140151
// Add the child content
@@ -158,19 +169,19 @@ export class CHTMLmsqrt extends CHTMLWrapper {
158169
* @override
159170
*/
160171
public computeBBox() {
161-
const box = BBox.empty();
172+
const BBOX = this.bbox.empty();
162173
const sbox = this.childNodes[this.surd].getBBox();
163174
const bbox = new BBox(this.childNodes[this.base].getBBox());
164175
const [p, q] = this.getPQ(sbox);
165176
const [x] = this.getRootDimens(sbox);
166177
const t = this.font.params.rule_thickness;
167178
const H = bbox.h + q + t;
168-
bbox.h += q + 2 * t; // FIXME: should take into account minimums for this.px() used above
169-
this.combineRootBBox(box, sbox);
170-
box.combine(sbox, x, H - sbox.h);
171-
box.combine(bbox, x + sbox.w, 0);
172-
box.clean();
173-
return box;
179+
bbox.h = H + t;
180+
this.combineRootBBox(BBOX, sbox);
181+
BBOX.combine(sbox, x, H - sbox.h);
182+
BBOX.combine(bbox, x + sbox.w, 0);
183+
BBOX.clean();
184+
return BBOX;
174185
}
175186

176187
/*
@@ -183,7 +194,7 @@ export class CHTMLmsqrt extends CHTMLWrapper {
183194
}
184195

185196
/*
186-
* @param{BBox} sbox The bounding box for the surd character
197+
* @param{BBox} sbox The bounding box for the surd character
187198
* @return{number[]} The p, q, and x values for the TeX layout computations
188199
*/
189200
protected getPQ(sbox: BBox) {

0 commit comments

Comments
 (0)