msqrt.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*************************************************************
  2. *
  3. * Copyright (c) 2017-2022 The MathJax Consortium
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. * @fileoverview Implements the CommonMsqrt wrapper for the MmlMsqrt object
  19. *
  20. * @author dpvc@mathjax.org (Davide Cervone)
  21. */
  22. import {AnyWrapper, WrapperConstructor, Constructor} from '../Wrapper.js';
  23. import {CommonMo} from './mo.js';
  24. import {BBox} from '../../../util/BBox.js';
  25. import {DIRECTION} from '../FontData.js';
  26. /*****************************************************************/
  27. /**
  28. * The CommonMsqrt interface
  29. */
  30. export interface CommonMsqrt extends AnyWrapper {
  31. /**
  32. * The index of the base of the root in childNodes
  33. */
  34. readonly base: number;
  35. /**
  36. * The index of the surd in childNodes
  37. */
  38. readonly surd: number;
  39. /**
  40. * The index of the root in childNodes (or null if none)
  41. */
  42. readonly root: number;
  43. /**
  44. * The requested height of the stretched surd character
  45. */
  46. surdH: number;
  47. /**
  48. * Combine the bounding box of the root (overridden in mroot)
  49. *
  50. * @param {BBox} bbox The bounding box so far
  51. * @param {BBox} sbox The bounding box of the surd
  52. * @param {number} H The height of the root as a whole
  53. */
  54. combineRootBBox(bbox: BBox, sbox: BBox, H: number): void;
  55. /**
  56. * @param {BBox} sbox The bounding box for the surd character
  57. * @return {number[]} The p, q, and x values for the TeX layout computations
  58. */
  59. getPQ(sbox: BBox): number[];
  60. /**
  61. * @param {BBox} sbox The bounding box of the surd
  62. * @param {number} H The height of the root as a whole
  63. * @return {number[]} The x offset of the surd, and the height, x offset, and scale of the root
  64. */
  65. getRootDimens(sbox: BBox, H: Number): number[];
  66. }
  67. /**
  68. * Shorthand for the CommonMsqrt constructor
  69. */
  70. export type MsqrtConstructor = Constructor<CommonMsqrt>;
  71. /*****************************************************************/
  72. /**
  73. * The CommonMsqrt wrapper mixin for the MmlMsqrt object
  74. *
  75. * @template T The Wrapper class constructor type
  76. */
  77. export function CommonMsqrtMixin<T extends WrapperConstructor>(Base: T): MsqrtConstructor & T {
  78. return class extends Base {
  79. /**
  80. * @return {number} The index of the base of the root in childNodes
  81. */
  82. get base(): number {
  83. return 0;
  84. }
  85. /**
  86. * @return {number} The index of the surd in childNodes
  87. */
  88. get surd(): number {
  89. return 1;
  90. }
  91. /**
  92. * @return {number} The index of the root in childNodes (or null if none)
  93. */
  94. get root(): number {
  95. return null;
  96. }
  97. /**
  98. * The requested height of the stretched surd character
  99. */
  100. public surdH: number;
  101. /**
  102. * Add the surd character so we can display it later
  103. *
  104. * @override
  105. */
  106. constructor(...args: any[]) {
  107. super(...args);
  108. const surd = this.createMo('\u221A');
  109. surd.canStretch(DIRECTION.Vertical);
  110. const {h, d} = this.childNodes[this.base].getOuterBBox();
  111. const t = this.font.params.rule_thickness;
  112. const p = (this.node.attributes.get('displaystyle') ? this.font.params.x_height : t);
  113. this.surdH = h + d + 2 * t + p / 4;
  114. (surd as CommonMo).getStretchedVariant([this.surdH - d, d], true);
  115. }
  116. /**
  117. * @override
  118. */
  119. public createMo(text: string) {
  120. const node = super.createMo(text);
  121. this.childNodes.push(node);
  122. return node;
  123. }
  124. /**
  125. * @override
  126. */
  127. public computeBBox(bbox: BBox, recompute: boolean = false) {
  128. const surdbox = this.childNodes[this.surd].getBBox();
  129. const basebox = new BBox(this.childNodes[this.base].getOuterBBox());
  130. const q = this.getPQ(surdbox)[1];
  131. const t = this.font.params.rule_thickness;
  132. const H = basebox.h + q + t;
  133. const [x] = this.getRootDimens(surdbox, H);
  134. bbox.h = H + t;
  135. this.combineRootBBox(bbox, surdbox, H);
  136. bbox.combine(surdbox, x, H - surdbox.h);
  137. bbox.combine(basebox, x + surdbox.w, 0);
  138. bbox.clean();
  139. this.setChildPWidths(recompute);
  140. }
  141. /**
  142. * Combine the bounding box of the root (overridden in mroot)
  143. *
  144. * @param {BBox} bbox The bounding box so far
  145. * @param {BBox} sbox The bounding box of the surd
  146. * @param {number} H The height of the root as a whole
  147. */
  148. public combineRootBBox(_bbox: BBox, _sbox: BBox, _H: number) {
  149. }
  150. /**
  151. * @param {BBox} sbox The bounding box for the surd character
  152. * @return {[number, number]} The p, q, and x values for the TeX layout computations
  153. */
  154. public getPQ(sbox: BBox): [number, number] {
  155. const t = this.font.params.rule_thickness;
  156. const p = (this.node.attributes.get('displaystyle') ? this.font.params.x_height : t);
  157. const q = (sbox.h + sbox.d > this.surdH ?
  158. ((sbox.h + sbox.d) - (this.surdH - 2 * t - p / 2)) / 2 :
  159. t + p / 4);
  160. return [p, q];
  161. }
  162. /**
  163. * @param {BBox} sbox The bounding box of the surd
  164. * @param {number} H The height of the root as a whole
  165. * @return {[number, number, number, number]} The x offset of the surd, and
  166. * the height, x offset, and scale of the root
  167. */
  168. public getRootDimens(_sbox: BBox, _H: number): [number, number, number, number] {
  169. return [0, 0, 0, 0];
  170. }
  171. };
  172. }