123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- /*************************************************************
- *
- * Copyright (c) 2017-2022 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.
- */
- /**
- * @fileoverview Implements the CommonMsubsup wrapper mixin for the MmlMsubsup object
- * and the special cases CommonMsub and CommonMsup
- *
- * @author dpvc@mathjax.org (Davide Cervone)
- */
- import {AnyWrapper, Constructor} from '../Wrapper.js';
- import {CommonScriptbase, ScriptbaseConstructor} from './scriptbase.js';
- import {BBox} from '../../../util/BBox.js';
- import {MmlMsubsup, MmlMsub, MmlMsup} from '../../../core/MmlTree/MmlNodes/msubsup.js';
- /*****************************************************************/
- /**
- * The CommonMsub interface
- *
- * @template W The child-node Wrapper class
- */
- export interface CommonMsub<W extends AnyWrapper> extends CommonScriptbase<W> {
- }
- /**
- * Shorthand for the CommonMsub constructor
- *
- * @template W The child-node Wrapper class
- */
- export type MsubConstructor<W extends AnyWrapper> = Constructor<CommonMsub<W>>;
- /*****************************************************************/
- /**
- * The CommonMsub wrapper mixin for the MmlMsub object
- *
- * @template W The child-node Wrapper class
- * @template T The Wrapper class constructor type
- */
- export function CommonMsubMixin<
- W extends AnyWrapper,
- T extends ScriptbaseConstructor<W>
- >(Base: T): MsubConstructor<W> & T {
- return class extends Base {
- /**
- * Do not include italic correction
- */
- public static useIC: boolean = false;
- /**
- * @override
- */
- public get scriptChild() {
- return this.childNodes[(this.node as MmlMsub).sub];
- }
- /**
- * Get the shift for the subscript
- *
- * @override
- */
- public getOffset() {
- return [0, -this.getV()];
- }
- };
- }
- /*****************************************************************/
- /**
- * The CommonMsup interface
- *
- * @template W The child-node Wrapper class
- */
- export interface CommonMsup<W extends AnyWrapper> extends CommonScriptbase<W> {
- }
- /**
- * Shorthand for the CommonMsup constructor
- *
- * @template W The child-node Wrapper class
- */
- export type MsupConstructor<W extends AnyWrapper> = Constructor<CommonMsup<W>>;
- /*****************************************************************/
- /**
- * The CommonMsup wrapper mixin for the MmlMsup object
- *
- * @template W The child-node Wrapper class
- * @template T The Wrapper class constructor type
- */
- export function CommonMsupMixin<
- W extends AnyWrapper,
- T extends ScriptbaseConstructor<W>
- >(Base: T): MsupConstructor<W> & T {
- return class extends Base {
- /**
- * @override
- */
- public get scriptChild() {
- return this.childNodes[(this.node as MmlMsup).sup];
- }
- /**
- * Get the shift for the superscript
- *
- * @override
- */
- public getOffset() {
- const x = this.getAdjustedIc() - (this.baseRemoveIc ? 0 : this.baseIc);
- return [x, this.getU()];
- }
- };
- }
- /*****************************************************************/
- /**
- * The CommonMsubsup interface
- *
- * @template W The child-node Wrapper class
- */
- export interface CommonMsubsup<W extends AnyWrapper> extends CommonScriptbase<W> {
- /**
- * Cached values for the script offsets and separation (so if they are
- * computed in computeBBox(), they don't have to be recomputed during output)
- */
- UVQ: number[];
- /**
- * The wrapper for the subscript
- */
- readonly subChild: W;
- /**
- * The wrapper for the superscript
- */
- readonly supChild: W;
- /**
- * Get the shift for the scripts and their separation (TeXBook Appendix G 18adef)
- *
- * @param {BBox} subbox The bounding box of the superscript
- * @param {BBox} supbox The bounding box of the subscript
- * @return {number[]} The vertical offsets for super and subscripts, and the space between them
- */
- getUVQ(subbox?: BBox, supbox?: BBox): number[];
- }
- /**
- * Shorthand for the CommonMsubsup constructor
- *
- * @template W The child-node Wrapper class
- */
- export type MsubsupConstructor<W extends AnyWrapper> = Constructor<CommonMsubsup<W>>;
- /*****************************************************************/
- /**
- * The CommomMsubsup wrapper for the MmlMsubsup object
- *
- * @template W The child-node Wrapper class
- * @template T The Wrapper class constructor type
- */
- export function CommonMsubsupMixin<
- W extends AnyWrapper,
- T extends ScriptbaseConstructor<W>
- >(Base: T): MsubsupConstructor<W> & T {
- return class extends Base {
- /**
- * Do not include italic correction
- */
- public static useIC: boolean = false;
- /**
- * Cached values for the script offsets and separation (so if they are
- * computed in computeBBox(), they don't have to be recomputed during output)
- */
- public UVQ: number[] = null;
- /**
- * @return {W} The wrapper for the subscript
- */
- public get subChild(): W {
- return this.childNodes[(this.node as MmlMsubsup).sub];
- }
- /**
- * @return {W} The wrapper for the superscript
- */
- public get supChild(): W {
- return this.childNodes[(this.node as MmlMsubsup).sup];
- }
- /**
- * @override
- */
- public computeBBox(bbox: BBox, recompute: boolean = false) {
- const basebox = this.baseChild.getOuterBBox();
- const [subbox, supbox] = [this.subChild.getOuterBBox(), this.supChild.getOuterBBox()];
- bbox.empty();
- bbox.append(basebox);
- const w = this.getBaseWidth();
- const x = this.getAdjustedIc();
- const [u, v] = this.getUVQ();
- bbox.combine(subbox, w, v);
- bbox.combine(supbox, w + x, u);
- bbox.w += this.font.params.scriptspace;
- bbox.clean();
- this.setChildPWidths(recompute);
- }
- /**
- * Get the shift for the scripts and their separation (TeXBook Appendix G 18adef)
- *
- * @param {BBox} subbox The bounding box of the superscript
- * @param {BBox} supbox The bounding box of the subscript
- * @return {number[]} The vertical offsets for super and subscripts, and the space between them
- */
- public getUVQ(
- subbox: BBox = this.subChild.getOuterBBox(),
- supbox: BBox = this.supChild.getOuterBBox()
- ): number[] {
- const basebox = this.baseCore.getOuterBBox();
- if (this.UVQ) return this.UVQ;
- const tex = this.font.params;
- const t = 3 * tex.rule_thickness;
- const subscriptshift = this.length2em(this.node.attributes.get('subscriptshift'), tex.sub2);
- const drop = this.baseCharZero(basebox.d * this.baseScale + tex.sub_drop * subbox.rscale);
- //
- // u and v are the veritcal shifts of the scripts, initially set to minimum values and then adjusted
- //
- let [u, v] = [this.getU(), Math.max(drop, subscriptshift)];
- //
- // q is the space currently between the super- and subscripts.
- // If it is less than 3 rule thicknesses,
- // increase the subscript offset to make the space 3 rule thicknesses
- // If the bottom of the superscript is below 4/5 of the x-height
- // raise both the super- and subscripts by the difference
- // (make the bottom of the superscript be at 4/5 the x-height, and the
- // subscript 3 rule thickness below that).
- //
- let q = (u - supbox.d * supbox.rscale) - (subbox.h * subbox.rscale - v);
- if (q < t) {
- v += t - q;
- const p = (4 / 5) * tex.x_height - (u - supbox.d * supbox.rscale);
- if (p > 0) {
- u += p;
- v -= p;
- }
- }
- //
- // Make sure the shifts are at least the minimum amounts and
- // return the shifts and the space between the scripts
- //
- u = Math.max(this.length2em(this.node.attributes.get('superscriptshift'), u), u);
- v = Math.max(this.length2em(this.node.attributes.get('subscriptshift'), v), v);
- q = (u - supbox.d * supbox.rscale) - (subbox.h * subbox.rscale - v);
- this.UVQ = [u, -v, q];
- return this.UVQ;
- }
- };
- }
|