/************************************************************* * * Copyright (c) 2017-2025 The MathJax Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file Implements the CommonMunderover wrapper mixin for the MmlMunderover object * and the special cases CommonMunder and CommonMsup * * @author dpvc@mathjax.org (Davide Cervone) */ import { CommonWrapper, CommonWrapperClass } from '../Wrapper.js'; import { CommonWrapperFactory } from '../WrapperFactory.js'; import { CharOptions, VariantData, DelimiterData, FontData, FontDataClass, } from '../FontData.js'; import { CommonOutputJax } from '../../common.js'; import { CommonScriptbase, CommonScriptbaseClass, CommonScriptbaseConstructor, } from './scriptbase.js'; import { MmlMunderover, MmlMunder, MmlMover, } from '../../../core/MmlTree/MmlNodes/munderover.js'; import { BBox } from '../../../util/BBox.js'; /*****************************************************************/ /** * The CommonMunder interface * * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type */ export interface CommonMunder< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, > extends CommonScriptbase {} /** * The CommonMunderClass interface * * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type */ export interface CommonMunderClass< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, > extends CommonScriptbaseClass {} /*****************************************************************/ /** * The CommonMunder wrapper mixin for the MmlMunder object * * @param {CommonScriptbaseConstructor} Base The constructor class to extend * @returns {B} The mixin constructor * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type * * @template B The mixin interface to create */ export function CommonMunderMixin< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, B extends CommonScriptbaseClass, >( Base: CommonScriptbaseConstructor ): B { return class CommonMunderMixin extends Base implements CommonMunder { /** * @override */ public get scriptChild() { return this.childNodes[(this.node as MmlMunder).under]; } /** * @override * @class */ constructor(...args: any[]) { super(...args); this.stretchChildren(); } /** * @override */ public computeBBox(bbox: BBox, recompute: boolean = false) { if (this.hasMovableLimits()) { super.computeBBox(bbox, recompute); return; } bbox.empty(); const basebox = this.baseChild.getOuterBBox(); const underbox = this.scriptChild.getOuterBBox(); const v = this.getUnderKV(basebox, underbox)[1]; const delta = this.isLineBelow ? 0 : this.getDelta(this.scriptChild, true); const [bw, uw] = this.getDeltaW([basebox, underbox], [0, -delta]); bbox.combine(basebox, bw, 0); bbox.combine(underbox, uw, v); bbox.d += this.font.params.big_op_spacing5; bbox.clean(); this.setChildPWidths(recompute); } } as any as B; } /*****************************************************************/ /** * The CommonMover interface * * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type */ export interface CommonMover< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, > extends CommonScriptbase {} /** * The CommonMoverClass interface * * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type */ export interface CommonMoverClass< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, > extends CommonScriptbaseClass {} /*****************************************************************/ /** * The CommonMover wrapper mixin for the MmlMover object * * @param {CommonScriptbaseConstructor} Base The constructor class to extend * @returns {B} The mixin constructor * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type * @template B The mixin interface to create */ export function CommonMoverMixin< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, B extends CommonWrapperClass, >( Base: CommonScriptbaseConstructor ): B { return class CommonMoverMixin extends Base implements CommonMover { /** * @override */ public get scriptChild() { return this.childNodes[(this.node as MmlMover).over]; } /** * @override * @class */ constructor(...args: any[]) { super(...args); this.stretchChildren(); } /** * @override */ public computeBBox(bbox: BBox) { if (this.hasMovableLimits()) { super.computeBBox(bbox); return; } bbox.empty(); const basebox = this.baseChild.getOuterBBox(); const overbox = this.scriptChild.getOuterBBox(); if (this.node.attributes.get('accent')) { basebox.h = Math.max( basebox.h, this.font.params.x_height * this.baseScale ); } const u = this.getOverKU(basebox, overbox)[1]; const delta = this.isLineAbove ? 0 : this.getDelta(this.scriptChild); const [bw, ow] = this.getDeltaW([basebox, overbox], [0, delta]); bbox.combine(basebox, bw, 0); bbox.combine(overbox, ow, u); bbox.h += this.font.params.big_op_spacing5; bbox.clean(); } } as any as B; } /*****************************************************************/ /** * The CommonMunderover interface * * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type */ export interface CommonMunderover< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, > extends CommonScriptbase { /* * The wrapped under node */ readonly underChild: WW; /* * The wrapped overder node */ readonly overChild: WW; } /** * The CommonMunderoverClass interface * * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type */ export interface CommonMunderoverClass< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, > extends CommonScriptbaseClass {} /*****************************************************************/ /** * The CommonMunderover wrapper for the MmlMunderover object * * @param {CommonScriptbaseConstructor} Base The constructor class to extend * @returns {B} The mixin constructor * @template N The DOM node type * @template T The DOM text node type * @template D The DOM document type * @template JX The OutputJax type * @template WW The Wrapper type * @template WF The WrapperFactory type * @template WC The WrapperClass type * @template CC The CharOptions type * @template VV The VariantData type * @template DD The DelimiterData type * @template FD The FontData type * @template FC The FontDataClass type * * @template B The mixin interface to create */ export function CommonMunderoverMixin< N, T, D, JX extends CommonOutputJax, WW extends CommonWrapper, WF extends CommonWrapperFactory, WC extends CommonWrapperClass, CC extends CharOptions, VV extends VariantData, DD extends DelimiterData, FD extends FontData, FC extends FontDataClass, B extends CommonWrapperClass, >( Base: CommonScriptbaseConstructor ): B { return class CommonMunderoverMixin extends Base implements CommonMunderover { /* * @override */ public get underChild() { return this.childNodes[(this.node as MmlMunderover).under]; } /* * @override */ public get overChild() { return this.childNodes[(this.node as MmlMunderover).over]; } /**************************************************/ /* * Needed for movablelimits * * @override */ public get subChild() { return this.underChild; } /* * Needed for movablelimits * * @override */ public get supChild() { return this.overChild; } /** * @override * @class */ constructor(...args: any[]) { super(...args); this.stretchChildren(); } /** * @override */ public computeBBox(bbox: BBox) { if (this.hasMovableLimits()) { super.computeBBox(bbox); return; } bbox.empty(); const overbox = this.overChild.getOuterBBox(); const basebox = this.baseChild.getOuterBBox(); const underbox = this.underChild.getOuterBBox(); if (this.node.attributes.get('accent')) { basebox.h = Math.max( basebox.h, this.font.params.x_height * this.baseScale ); } const u = this.getOverKU(basebox, overbox)[1]; const v = this.getUnderKV(basebox, underbox)[1]; const odelta = this.getDelta(this.overChild); const udelta = this.getDelta(this.underChild, true); const [bw, uw, ow] = this.getDeltaW( [basebox, underbox, overbox], [0, this.isLineBelow ? 0 : -udelta, this.isLineAbove ? 0 : odelta] ); bbox.combine(basebox, bw, 0); bbox.combine(overbox, ow, u); bbox.combine(underbox, uw, v); const z = this.font.params.big_op_spacing5; bbox.h += z; bbox.d += z; bbox.clean(); } } as any as B; }