diff --git a/ts/core/MmlTree/MmlNodes/mglyph.ts b/ts/core/MmlTree/MmlNodes/mglyph.ts index f9874a144..d4b76e766 100644 --- a/ts/core/MmlTree/MmlNodes/mglyph.ts +++ b/ts/core/MmlTree/MmlNodes/mglyph.ts @@ -38,6 +38,7 @@ export class MmlMglyph extends AbstractMmlTokenNode { ...AbstractMmlTokenNode.defaults, alt: '', src: '', + index: '', width: 'auto', height: 'auto', valign: '0em' @@ -55,4 +56,16 @@ export class MmlMglyph extends AbstractMmlTokenNode { return 'mglyph'; } + /** + * @override + */ + public verifyAttributes(options: PropertyList) { + const {src, fontfamily, index} = this.attributes.getList('src', 'fontfamily', 'index'); + if (src === '' && (fontfamily === '' || index === '')) { + this.mError('mglyph must have either src or fontfamily and index attributes', options, true); + } else { + super.verifyAttributes(options); + } + } + } diff --git a/ts/output/chtml/Wrappers/mglyph.ts b/ts/output/chtml/Wrappers/mglyph.ts index 707385f34..3b74dd444 100644 --- a/ts/output/chtml/Wrappers/mglyph.ts +++ b/ts/output/chtml/Wrappers/mglyph.ts @@ -24,6 +24,7 @@ import {CHTMLWrapper, CHTMLConstructor} from '../Wrapper.js'; import {CommonMglyphMixin} from '../../common/Wrappers/mglyph.js'; import {MmlMglyph} from '../../../core/MmlTree/MmlNodes/mglyph.js'; +import {CHTMLTextNode} from './TextNode.js'; import {StyleList, StyleData} from '../../../util/StyleList.js'; /*****************************************************************/ @@ -59,6 +60,10 @@ CommonMglyphMixin>(CHTMLWrapper) { */ public toCHTML(parent: N) { const chtml = this.standardCHTMLnode(parent); + if (this.charWrapper) { + (this.charWrapper as CHTMLTextNode).toCHTML(chtml); + return; + } const {src, alt} = this.node.attributes.getList('src', 'alt'); const styles: StyleData = { width: this.em(this.width), diff --git a/ts/output/common/Wrappers/mglyph.ts b/ts/output/common/Wrappers/mglyph.ts index 8cc537e33..ea092fb99 100644 --- a/ts/output/common/Wrappers/mglyph.ts +++ b/ts/output/common/Wrappers/mglyph.ts @@ -22,6 +22,8 @@ */ import {AnyWrapper, WrapperConstructor, Constructor} from '../Wrapper.js'; +import {CommonTextNode} from './TextNode.js'; +import {TextNode} from '../../../core/MmlTree/MmlNode.js'; import {BBox} from '../../../util/BBox.js'; /*****************************************************************/ @@ -30,14 +32,29 @@ import {BBox} from '../../../util/BBox.js'; */ export interface CommonMglyph extends AnyWrapper { /** - * The image's width, height, and valign values converted to em's + * The image's width converted to em's */ width: number; + /** + * The image's height converted to em's + */ height: number; + /* + * The image's valign values converted to em's + */ valign: number; + /** + * TextNode used for deprecated fontfamily/index use case + */ + charWrapper: CommonTextNode; + /** * Obtain the width, height, and valign. + * Note: Currently, the width and height must be specified explicitly, or they default to 1em + * Since loading the image may be asynchronous, it would require a restart. + * A future extension could implement this either by subclassing this object, or + * perhaps as a post-filter on the MathML input jax that adds the needed dimensions */ getParameters(): void; } @@ -58,18 +75,23 @@ export function CommonMglyphMixin(Base: T): Mglyph return class extends Base { /** - * The image's width converted to em's + * @override */ public width: number; /** - * The image's height converted to em's + * @override */ public height: number; /** - * The image's valign values converted to em's + * @override */ public valign: number; + /** + * @override + */ + public charWrapper: CommonTextNode; + /** * @override * @constructor @@ -80,26 +102,34 @@ export function CommonMglyphMixin(Base: T): Mglyph } /** - * Obtain the width, height, and valign. - * Note: Currently, the width and height must be specified explicitly, or they default to 1em - * Since loading the image may be asynchronous, it would require a restart. - * A future extension could implement this either by subclassing this object, or - * perhaps as a post-filter on the MathML input jax that adds the needed dimensions + * @override */ public getParameters() { - const {width, height, valign} = this.node.attributes.getList('width', 'height', 'valign'); - this.width = (width === 'auto' ? 1 : this.length2em(width)); - this.height = (height === 'auto' ? 1 : this.length2em(height)); - this.valign = this.length2em(valign || '0'); + const {width, height, valign, src, index} = + this.node.attributes.getList('width', 'height', 'valign', 'src', 'index'); + if (src) { + this.width = (width === 'auto' ? 1 : this.length2em(width)); + this.height = (height === 'auto' ? 1 : this.length2em(height)); + this.valign = this.length2em(valign || '0'); + } else { + const text = String.fromCodePoint(parseInt(index as string)); + const mmlFactory = this.node.factory; + this.charWrapper = this.wrap((mmlFactory.create('text') as TextNode).setText(text)); + this.charWrapper.parent = this as any as AnyWrapper; + } } /** * @override */ public computeBBox(bbox: BBox, _recompute: boolean = false) { - bbox.w = this.width; - bbox.h = this.height + this.valign; - bbox.d = -this.valign; + if (this.charWrapper) { + bbox.updateFrom(this.charWrapper.getBBox()); + } else { + bbox.w = this.width; + bbox.h = this.height + this.valign; + bbox.d = -this.valign; + } } }; diff --git a/ts/output/svg/Wrappers/mglyph.ts b/ts/output/svg/Wrappers/mglyph.ts index e45835a4e..19ec0d63e 100644 --- a/ts/output/svg/Wrappers/mglyph.ts +++ b/ts/output/svg/Wrappers/mglyph.ts @@ -24,6 +24,7 @@ import {SVGWrapper, SVGConstructor} from '../Wrapper.js'; import {CommonMglyphMixin} from '../../common/Wrappers/mglyph.js'; import {MmlMglyph} from '../../../core/MmlTree/MmlNodes/mglyph.js'; +import {SVGTextNode} from './TextNode.js'; import {OptionList} from '../../../util/Options.js'; /*****************************************************************/ @@ -48,6 +49,10 @@ CommonMglyphMixin>(SVGWrapper) { */ public toSVG(parent: N) { const svg = this.standardSVGnode(parent); + if (this.charWrapper) { + (this.charWrapper as SVGTextNode).toSVG(svg); + return; + } const {src, alt} = this.node.attributes.getList('src', 'alt'); const h = this.fixed(this.height); const w = this.fixed(this.width);