diff --git a/ts/output/chtml/Wrappers/mrow.ts b/ts/output/chtml/Wrappers/mrow.ts index 8ef1f5e83..e1a8f5036 100644 --- a/ts/output/chtml/Wrappers/mrow.ts +++ b/ts/output/chtml/Wrappers/mrow.ts @@ -250,8 +250,7 @@ export const ChtmlMrow = (function (): ChtmlMrowClass { ); adaptor.setAttribute(parents[i], 'align', align); if (shift) { - adaptor.setStyle(parents[i], 'position', 'relative'); - adaptor.setStyle(parents[i], 'left', this.em(shift)); + adaptor.setStyle(parents[i], 'margin-left', this.em(shift)); } if (i < n && this.jax.math.display) { adaptor.setStyle( diff --git a/ts/output/chtml/Wrappers/mtr.ts b/ts/output/chtml/Wrappers/mtr.ts index 920807865..4a0b906c6 100644 --- a/ts/output/chtml/Wrappers/mtr.ts +++ b/ts/output/chtml/Wrappers/mtr.ts @@ -164,6 +164,8 @@ export const ChtmlMtr = (function (): ChtmlMtrClass { if (align !== 'baseline') { this.adaptor.setAttribute(this.dom[0], 'rowalign', align); } + const { h, d } = this.getBBox(); + this.adaptor.setStyle(this.dom[0], 'height', this.em(h + d)); } }; })(); diff --git a/ts/output/common/Wrapper.ts b/ts/output/common/Wrapper.ts index 77a23b491..3dfdeca84 100644 --- a/ts/output/common/Wrapper.ts +++ b/ts/output/common/Wrapper.ts @@ -457,7 +457,7 @@ export class CommonWrapper< * @returns {number} The container width */ get containerWidth(): number { - return this.jax.containerWidth; + return this.parent ? this.parent.containerWidth : this.jax.containerWidth; } /** diff --git a/ts/output/common/Wrappers/mpadded.ts b/ts/output/common/Wrappers/mpadded.ts index 7affee373..35eff53ca 100644 --- a/ts/output/common/Wrappers/mpadded.ts +++ b/ts/output/common/Wrappers/mpadded.ts @@ -171,6 +171,18 @@ export function CommonMpaddedMixin< extends Base implements CommonMpadded { + get containerWidth(): number { + const attributes = this.node.attributes; + const w = attributes.get('width') as string; + if ( + !w.match(/^[-+]|%$/) && + attributes.get('data-overflow') === 'linebreak' + ) { + return this.length2em(w); + } + return this.parent.containerWidth; + } + /** * @override */ diff --git a/ts/output/common/Wrappers/mrow.ts b/ts/output/common/Wrappers/mrow.ts index e33b34f2f..01dd522d8 100644 --- a/ts/output/common/Wrappers/mrow.ts +++ b/ts/output/common/Wrappers/mrow.ts @@ -327,7 +327,7 @@ export function CommonMrowMixin< lines[n].R = this.bbox.R; } else { bbox.w = Math.max(...this.lineBBox.map((bbox) => bbox.w)); // natural width - this.shiftLines(bbox.w); + this.shiftLines(bbox); if (!this.jax.math.display && !this.linebreakOptions.inline) { bbox.pwidth = BBox.fullWidth; if (this.node.isInferred) { @@ -391,11 +391,12 @@ export function CommonMrowMixin< } /** - * Handle alignment and shifting if lines + * Handle alignment and shifting of lines * - * @param {number} W The width of the container + * @param {BBox} BBOX The bounding box of the container */ - protected shiftLines(W: number) { + protected shiftLines(BBOX: BBox) { + const W = BBOX.w; const lines = this.lineBBox; const n = lines.length - 1; const [alignfirst, shiftfirst] = lines[1].indentData?.[0] || [ @@ -417,6 +418,10 @@ export function CommonMrowMixin< ); bbox.L = 0; bbox.L = this.getAlignX(W, bbox, align) + shift; + const w = bbox.L + bbox.w; + if (w > BBOX.w) { + BBOX.w = w; + } } } @@ -432,7 +437,7 @@ export function CommonMrowMixin< if (recompute) return false; if (w !== null && this.bbox.w !== w) { this.bbox.w = w; - this.shiftLines(w); + this.shiftLines(this.bbox); } return true; } diff --git a/ts/output/common/Wrappers/mtable.ts b/ts/output/common/Wrappers/mtable.ts index ee78f71a0..6b588ba9d 100644 --- a/ts/output/common/Wrappers/mtable.ts +++ b/ts/output/common/Wrappers/mtable.ts @@ -243,7 +243,6 @@ export interface CommonMtable< * @param {number[]} D The maximum depth for each of the rows * @param {number[]} W The maximum width for each column * @param {number} M The current height for items aligned top and bottom - * @returns {number} The updated value for M */ updateHDW( cell: WW, @@ -254,17 +253,7 @@ export interface CommonMtable< D: number[], W: number[], M: number - ): number; - - /** - * Extend the H and D of a row to cover the maximum height needed by top/bottom aligned items - * - * @param {number} i The row whose hight and depth should be adjusted - * @param {number[]} H The row heights - * @param {number[]} D The row depths - * @param {number} M The maximum height of top/bottom aligned items - */ - extendHD(i: number, H: number[], D: number[], M: number): void; + ): void; /** * @param {WW} cell The cell to check for percentage widths @@ -744,21 +733,29 @@ export function CommonMtableMixin< if ( this.jax.math.root.attributes.get('overflow') !== 'linebreak' || !this.jax.math.display - ) + ) { return; - const { D } = this.getTableData(); + } + const { H, D } = this.getTableData(); let j = 0; let w = 0; for (const row of this.tableRows) { const cell = row.getChild(i); - if (cell && cell.getBBox().w > W) { - cell.childNodes[0].breakToWidth(W); + if (cell) { + const r = row.getBBox().rscale; const bbox = cell.getBBox(); - D[j] = Math.max(D[j], bbox.d); - if (bbox.w > w) { - w = bbox.w; + if (cell && bbox.w * r > W) { + cell.childNodes[0].breakToWidth(W); + const align = row.node.attributes.get('rowalign') as string; + this.updateHDW(cell, i, j, align, H, D); + } + if (bbox.w * r > w) { + w = bbox.w * r; } } + const bbox = row.getBBox(); + bbox.h = H[j]; + bbox.d = D[j]; j++; } // @@ -791,27 +788,72 @@ export function CommonMtableMixin< const LW = [0]; const rows = this.tableRows; for (let j = 0; j < rows.length; j++) { - let M = 0; const row = rows[j]; const align = row.node.attributes.get('rowalign') as string; for (let i = 0; i < row.numCells; i++) { const cell = row.getChild(i); - M = this.updateHDW(cell, i, j, align, H, D, W, M); + this.updateHDW(cell, i, j, align, H, D, W); this.recordPWidthCell(cell, i); } NH[j] = H[j]; ND[j] = D[j]; if (row.labeled) { - M = this.updateHDW(row.childNodes[0], 0, j, align, H, D, LW, M); + this.updateHDW(row.childNodes[0], 0, j, align, H, D, LW); } - this.extendHD(j, H, D, M); - this.extendHD(j, NH, ND, M); + row.bbox.h = H[j]; + row.bbox.d = D[j]; } const L = LW[0]; this.data = { H, D, W, NH, ND, L }; return this.data; } + /** + * Functions for adjusting the H and D values for cells + * that are aligned by top, bottom, center, axis, and baseline. + */ + protected adjustHD: { + [name: string]: ( + h: number, + d: number, + H: number[], + D: number[], + j: number + ) => void; + } = { + top: (h, d, H, D, j) => { + if (h > H[j]) { + D[j] -= h - H[j]; + H[j] = h; + } + if (h + d > H[j] + D[j]) { + D[j] = h + d - H[j]; + } + }, + bottom: (h, d, H, D, j) => { + if (d > D[j]) { + H[j] -= d - D[j]; + D[j] = d; + } + if (h + d > H[j] + D[j]) { + H[j] = h + d - D[j]; + } + }, + center: (h, d, H, D, j) => { + if (h + d > H[j] + D[j]) { + H[j] = D[j] = (h + d) / 2; + } + }, + other: (h, d, H, D, j) => { + if (h > H[j]) { + H[j] = h; + } + if (d > D[j]) { + D[j] = d; + } + }, + }; + /** * @override */ @@ -822,9 +864,8 @@ export function CommonMtableMixin< align: string, H: number[], D: number[], - W: number[], - M: number - ): number { + W: number[] = null + ) { let { h, d, w } = cell.getBBox(); const scale = cell.parent.bbox.rscale; if (cell.parent.bbox.rscale !== 1) { @@ -836,27 +877,12 @@ export function CommonMtableMixin< if (h < 0.75) h = 0.75; if (d < 0.25) d = 0.25; } - let m = 0; align = (cell.node.attributes.get('rowalign') as string) || align; - if (align !== 'baseline' && align !== 'axis') { - m = h + d; - h = d = 0; + if (!Object.hasOwn(this.adjustHD, align)) { + align = 'other'; } - if (h > H[j]) H[j] = h; - if (d > D[j]) D[j] = d; - if (m > M) M = m; + this.adjustHD[align](h, d, H, D, j); if (W && w > W[i]) W[i] = w; - return M; - } - - /** - * @override - */ - public extendHD(i: number, H: number[], D: number[], M: number) { - const d = (M - (H[i] + D[i])) / 2; - if (d < 0.00001) return; - H[i] += d; - D[i] += d; } /**