mpadded.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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 CommonMpadded wrapper mixin for the MmlMpadded object
  19. *
  20. * @author dpvc@mathjax.org (Davide Cervone)
  21. */
  22. import {AnyWrapper, WrapperConstructor, Constructor} from '../Wrapper.js';
  23. import {BBox} from '../../../util/BBox.js';
  24. import {Property} from '../../../core/Tree/Node.js';
  25. /*****************************************************************/
  26. /**
  27. * The CommonMpadded interface
  28. */
  29. export interface CommonMpadded extends AnyWrapper {
  30. /**
  31. * Get the content bounding box, and the change in size and offsets
  32. * as specified by the parameters
  33. *
  34. * @return {number[]} The original height, depth, width, the changes in height, depth,
  35. * and width, and the horizontal and vertical offsets of the content
  36. */
  37. getDimens(): number[];
  38. /**
  39. * Get a particular dimension, which can be relative to any of the BBox dimensions,
  40. * and can be an offset from the default size of the given dimension.
  41. *
  42. * @param {Property} length The value to be converted to a length in ems
  43. * @param {BBox} bbox The bbox of the mpadded content
  44. * @param {string=} d The default dimension to use for relative sizes ('w', 'h', or 'd')
  45. * @param {number=} m The minimum value allowed for the dimension
  46. * @return {number} The final dimension in ems
  47. */
  48. dimen(length: Property, bbox: BBox, d?: string, m?: number): number;
  49. }
  50. /**
  51. * Shorthand for the CommonMpadded constructor
  52. */
  53. export type MpaddedConstructor = Constructor<CommonMpadded>;
  54. /*****************************************************************/
  55. /**
  56. * The CommomMpadded wrapper for the MmlMpadded object
  57. *
  58. * @template T The Wrapper class constructor type
  59. */
  60. export function CommonMpaddedMixin<T extends WrapperConstructor>(Base: T): MpaddedConstructor & T {
  61. return class extends Base {
  62. /**
  63. * Get the content bounding box, and the change in size and offsets
  64. * as specified by the parameters
  65. *
  66. * @return {number[]} The original height, depth, width, the changes in height, depth,
  67. * and width, and the horizontal and vertical offsets of the content
  68. */
  69. public getDimens(): number[] {
  70. const values = this.node.attributes.getList('width', 'height', 'depth', 'lspace', 'voffset');
  71. const bbox = this.childNodes[0].getBBox(); // get unmodified bbox of children
  72. let {w, h, d} = bbox;
  73. let W = w, H = h, D = d, x = 0, y = 0, dx = 0;
  74. if (values.width !== '') w = this.dimen(values.width, bbox, 'w', 0);
  75. if (values.height !== '') h = this.dimen(values.height, bbox, 'h', 0);
  76. if (values.depth !== '') d = this.dimen(values.depth, bbox, 'd', 0);
  77. if (values.voffset !== '') y = this.dimen(values.voffset, bbox);
  78. if (values.lspace !== '') x = this.dimen(values.lspace, bbox);
  79. const align = this.node.attributes.get('data-align') as string;
  80. if (align) {
  81. dx = this.getAlignX(w, bbox, align);
  82. }
  83. return [H, D, W, h - H, d - D, w - W, x, y, dx];
  84. }
  85. /**
  86. * Get a particular dimension, which can be relative to any of the BBox dimensions,
  87. * and can be an offset from the default size of the given dimension.
  88. *
  89. * @param {Property} length The value to be converted to a length in ems
  90. * @param {BBox} bbox The bbox of the mpadded content
  91. * @param {string} d The default dimension to use for relative sizes ('w', 'h', or 'd')
  92. * @param {number} m The minimum value allowed for the dimension
  93. * @return {number} The final dimension in ems
  94. */
  95. public dimen(length: Property, bbox: BBox, d: string = '', m: number = null): number {
  96. length = String(length);
  97. const match = length.match(/width|height|depth/);
  98. const size = (match ? bbox[match[0].charAt(0) as (keyof BBox)] :
  99. (d ? bbox[d as (keyof BBox)] : 0)) as number;
  100. let dimen = (this.length2em(length, size) || 0);
  101. if (length.match(/^[-+]/) && d) {
  102. dimen += size;
  103. }
  104. if (m != null) {
  105. dimen = Math.max(m, dimen);
  106. }
  107. return dimen;
  108. }
  109. /**
  110. * @override
  111. */
  112. public computeBBox(bbox: BBox, recompute: boolean = false) {
  113. const [H, D, W, dh, dd, dw] = this.getDimens();
  114. bbox.w = W + dw;
  115. bbox.h = H + dh;
  116. bbox.d = D + dd;
  117. this.setChildPWidths(recompute, bbox.w);
  118. }
  119. /**
  120. * @override
  121. */
  122. public getWrapWidth(_i: number) {
  123. return this.getBBox().w;
  124. }
  125. /**
  126. * @override
  127. */
  128. public getChildAlign(_i: number) {
  129. return this.node.attributes.get('data-align') as string || 'left';
  130. }
  131. };
  132. }