Skip to content

Commit 5aea508

Browse files
committed
Move alignment processing to mtr and mtd, and add equalrow support.
1 parent d3f9570 commit 5aea508

File tree

3 files changed

+74
-51
lines changed

3 files changed

+74
-51
lines changed

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

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
100100
protected rSpace: number[];
101101
protected cLines: number[];
102102
protected rLines: number[];
103+
protected cWidths: string[];
103104

104105
/*
105106
* The bounding box information for the table rows and columns
@@ -120,14 +121,18 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
120121
this.numCols = this.childNodes.map(row => (row as CHTMLmtr<N, T, D>).numCells)
121122
.reduce((a, b) => Math.max(a, b), 0);
122123
this.numRows = this.childNodes.length;
124+
//
125+
// Get the frame, row, and column parameters
126+
//
123127
const attributes = node.attributes;
124-
this.cSpace = this.convertLengths(this.getColumnAttributes('columnspacing'));
125-
this.rSpace = this.convertLengths(this.getRowAttributes('rowspacing'));
126128
this.frame = attributes.get('frame') !== 'none';
127129
this.lines = this.frame || attributes.get('columnlines') !== 'none' || attributes.get('rowlines') !== 'none';
128-
this.fSpace = (this.lines ? this.convertLengths(this.getAttributeArray('framespacing')) : []);
130+
this.fSpace = (this.lines ? this.convertLengths(this.getAttributeArray('framespacing')) : [0, 0]);
131+
this.cSpace = this.convertLengths(this.getColumnAttributes('columnspacing'));
132+
this.rSpace = this.convertLengths(this.getRowAttributes('rowspacing'));
129133
this.cLines = this.getColumnAttributes('columnlines').map(x => (x === 'none' ? 0 : .07));
130134
this.rLines = this.getColumnAttributes('rowlines').map(x => (x === 'none' ? 0 : .07));
135+
this.cWidths = this.getColumnAttributes('columnwidth');
131136
//
132137
// Stretch the columns (rows are already taken care of in the CHTMLmtr wrapper)
133138
//
@@ -205,12 +210,11 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
205210
// Finally, add the frame, if needed
206211
//
207212
this.padRows();
208-
this.handleColumnAlign();
209213
this.handleColumnSpacing();
210214
this.handleColumnLines();
211-
this.handleRowAlign();
212215
this.handleRowSpacing();
213216
this.handleRowLines();
217+
this.handleEqualRows();
214218
this.handleFrame();
215219
this.handleWidth();
216220
this.drawBBox();
@@ -241,16 +245,14 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
241245
}
242246
}
243247
const w = this.node.attributes.get('width') as string;
244-
const height = H.concat(D, this.rLines).reduce((a, b) => a + b, 0)
245-
+ this.rSpace.reduce((a, b) => a + b, 0)
248+
const height = H.concat(D, this.rLines, this.rSpace).reduce((a, b) => a + b, 0)
246249
+ (this.frame ? .14 : 0)
247-
+ 2 * (this.fSpace[1] || 0);
250+
+ 2 * this.fSpace[1];
248251
let width;
249252
if (w === 'auto' || w.match(/%$/)) {
250-
width = W.concat(this.cLines).reduce((a, b) => a + b, 0)
251-
+ this.cSpace.reduce((a, b) => a + b, 0)
253+
width = W.concat(this.cLines, this.cSpace).reduce((a, b) => a + b, 0)
252254
+ (this.frame ? .14 : 0)
253-
+ 2 * (this.fSpace[0] || 0);
255+
+ 2 * this.fSpace[0];
254256
} else {
255257
const cwidth = this.metrics.containerWidth / this.metrics.em;
256258
width = this.length2em(w, cwidth) + (this.frame ? .14 : 0);
@@ -263,7 +265,13 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
263265
* @override
264266
*/
265267
public computeBBox(bbox: BBox) {
266-
const {width, height} = this.getTableData();
268+
let {width, height} = this.getTableData();
269+
if (this.node.attributes.get('equalrows')) {
270+
const HD = this.getEqualRowHeight();
271+
height = [].concat(this.rLines, this.rSpace).reduce((a, b) => a + b, 0)
272+
+ HD * this.numRows
273+
+ 2 * this.fSpace[1];
274+
}
267275
const a = this.font.params.axis_height;
268276
bbox.h = height / 2 + a;
269277
bbox.d = height / 2 - a;
@@ -283,23 +291,6 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
283291
}
284292
}
285293

286-
/*
287-
* Set the cell aligments based on the table, row, or cell columnalign attributes
288-
*/
289-
protected handleColumnAlign() {
290-
const colAlign = this.getColumnAttributes('columnalign') || [];
291-
for (const row of this.childNodes) {
292-
const aligns = this.getColumnAttributes('columnalign', row) || colAlign;
293-
let i = 0;
294-
for (const cell of row.childNodes) {
295-
let align = (cell.node.attributes.get('columnalign') as string) || aligns[i++];
296-
if (align !== 'center') {
297-
this.adaptor.setStyle(cell.chtml, 'textAlign', align);
298-
}
299-
}
300-
}
301-
}
302-
303294
/*
304295
* Set the inter-column spacing for all columns
305296
* (Use frame spacing on the outsides, if needed, and use half the column spacing on each
@@ -310,7 +301,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
310301
//
311302
// Get the column spacing values, and add the frame spacing values at the left and right
312303
//
313-
const fspace = this.em(this.fSpace[0] || 0);
304+
const fspace = this.em(this.fSpace[0]);
314305
const spacing = this.addEm(this.cSpace, 2);
315306
if (!spacing) return;
316307
spacing.unshift(fspace);
@@ -362,26 +353,6 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
362353
}
363354
}
364355

365-
/*
366-
* Add vertical alignment to rows, and override in the cells, if needed
367-
*/
368-
protected handleRowAlign() {
369-
const rowAlign = this.getRowAttributes('rowalign') || [];
370-
let i = 0;
371-
for (const row of this.childNodes) {
372-
const align = (row.node.attributes.get('rowalign') as string) || rowAlign[i++];
373-
if (align !== 'baseline') {
374-
this.adaptor.setAttribute(row.chtml, 'rowalign', align);
375-
}
376-
for (const cell of row.childNodes) {
377-
const calign = cell.node.attributes.get('rowalign') as string;
378-
if (calign && calign !== align) {
379-
this.adaptor.setStyle(cell.chtml, 'verticalAlign', calign);
380-
}
381-
}
382-
}
383-
}
384-
385356
/*
386357
* Set the inter-row spacing for all rows
387358
* (Use frame spacing on the outsides, if needed, and use half the row spacing on each
@@ -392,7 +363,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
392363
//
393364
// Get the row spacing values, and add the frame spacing values at the left and right
394365
//
395-
const fspacing = this.em(this.fSpace[1] || 0);
366+
const fspacing = this.em(this.fSpace[1]);
396367
const spacing = this.addEm(this.rSpace, 2);
397368
if (!spacing) return;
398369
spacing.unshift(fspacing);
@@ -443,6 +414,30 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
443414
}
444415
}
445416

417+
protected handleEqualRows() {
418+
if (!this.node.attributes.get('equalrows')) return;
419+
const space = this.rSpace.map(x => x / 2);
420+
space.unshift(this.fSpace[1]);
421+
space.push(this.fSpace[1]);
422+
const {H, D} = this.getTableData();
423+
const HD = this.getEqualRowHeight();
424+
const HDem = this.em(HD);
425+
for (const i of Array.from(this.childNodes.keys())) {
426+
const row = this.childNodes[i];
427+
this.adaptor.setStyle(row.chtml, 'height', this.em(space[i] + HD + space[i + 1]));
428+
const ralign = row.node.attributes.get('rowalign');
429+
for (const cell of row.childNodes) {
430+
const calign = cell.node.attributes.get('rowalign');
431+
if (calign === 'baseline' || calign === 'axis') {
432+
const child = this.adaptor.lastChild(cell.chtml) as N;
433+
this.adaptor.setStyle(child, 'height', HDem);
434+
this.adaptor.setStyle(child, 'verticalAlign', this.em(-((HD - H[i] + D[i]) / 2)));
435+
if (ralign === 'baseline' || ralign === 'axis') break;
436+
}
437+
}
438+
}
439+
}
440+
446441
/*
447442
* Add a frame to the mtable, if needed
448443
*/
@@ -470,6 +465,15 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
470465

471466
/******************************************************************/
472467

468+
/*
469+
* Get the maximum height of a row
470+
*/
471+
protected getEqualRowHeight() {
472+
const {H, D} = this.getTableData();
473+
const HD = Array.from(H.keys()).map(i => H[i] + D[i]);
474+
return Math.max.apply(Math, HD);
475+
}
476+
473477
/*
474478
* @param{string} name The name of the attribute to get as an array
475479
* @param{CHTMLWrapper} wrapper The wrapper whose attribute is to be used

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ export class CHTMLmtd<N, T, D> extends CHTMLWrapper<N, T, D> {
6868
*/
6969
public toCHTML(parent: N) {
7070
super.toCHTML(parent);
71+
const ralign = this.node.attributes.get('rowalign') as string;
72+
const calign = this.node.attributes.get('columnalign') as string;
73+
if (ralign !== 'baseline' && ralign !== 'axis') {
74+
this.adaptor.setStyle(this.chtml, 'verticalAlign', (ralign === 'center' ? 'middle' : ralign));
75+
}
76+
if (calign !== 'center') {
77+
this.adaptor.setStyle(this.chtml, 'textAlign', calign);
78+
}
7179
//
7280
// Include a strut to force minimum height and depth
7381
//

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ export class CHTMLmtr<N, T, D> extends CHTMLWrapper<N, T, D> {
7777
this.stretchChildren();
7878
}
7979

80+
/*
81+
* @override
82+
*/
83+
public toCHTML(parent: N) {
84+
super.toCHTML(parent);
85+
const align = this.node.attributes.get('rowalign') as string;
86+
if (align !== 'baseline' && align !== 'axis') {
87+
this.adaptor.setStyle(this.chtml, 'verticalAlign', (align === 'center' ? 'middle' : align));
88+
}
89+
}
90+
8091
/*
8192
* Handle vertical stretching of cells to match height of
8293
* other cells in the row.

0 commit comments

Comments
 (0)