svg.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. "use strict";
  2. var __extends = (this && this.__extends) || (function () {
  3. var extendStatics = function (d, b) {
  4. extendStatics = Object.setPrototypeOf ||
  5. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  6. function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
  7. return extendStatics(d, b);
  8. };
  9. return function (d, b) {
  10. if (typeof b !== "function" && b !== null)
  11. throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
  12. extendStatics(d, b);
  13. function __() { this.constructor = d; }
  14. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  15. };
  16. })();
  17. var __assign = (this && this.__assign) || function () {
  18. __assign = Object.assign || function(t) {
  19. for (var s, i = 1, n = arguments.length; i < n; i++) {
  20. s = arguments[i];
  21. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  22. t[p] = s[p];
  23. }
  24. return t;
  25. };
  26. return __assign.apply(this, arguments);
  27. };
  28. var __read = (this && this.__read) || function (o, n) {
  29. var m = typeof Symbol === "function" && o[Symbol.iterator];
  30. if (!m) return o;
  31. var i = m.call(o), r, ar = [], e;
  32. try {
  33. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  34. }
  35. catch (error) { e = { error: error }; }
  36. finally {
  37. try {
  38. if (r && !r.done && (m = i["return"])) m.call(i);
  39. }
  40. finally { if (e) throw e.error; }
  41. }
  42. return ar;
  43. };
  44. Object.defineProperty(exports, "__esModule", { value: true });
  45. exports.SVG = exports.XLINKNS = exports.SVGNS = void 0;
  46. var OutputJax_js_1 = require("./common/OutputJax.js");
  47. var WrapperFactory_js_1 = require("./svg/WrapperFactory.js");
  48. var tex_js_1 = require("./svg/fonts/tex.js");
  49. var FontCache_js_1 = require("./svg/FontCache.js");
  50. var string_js_1 = require("../util/string.js");
  51. var lengths_js_1 = require("../util/lengths.js");
  52. exports.SVGNS = 'http://www.w3.org/2000/svg';
  53. exports.XLINKNS = 'http://www.w3.org/1999/xlink';
  54. var SVG = (function (_super) {
  55. __extends(SVG, _super);
  56. function SVG(options) {
  57. if (options === void 0) { options = null; }
  58. var _this = _super.call(this, options, WrapperFactory_js_1.SVGWrapperFactory, tex_js_1.TeXFont) || this;
  59. _this.minwidth = 0;
  60. _this.shift = 0;
  61. _this.container = null;
  62. _this.svgStyles = null;
  63. _this.fontCache = new FontCache_js_1.FontCache(_this);
  64. return _this;
  65. }
  66. SVG.prototype.initialize = function () {
  67. if (this.options.fontCache === 'global') {
  68. this.fontCache.clearCache();
  69. }
  70. };
  71. SVG.prototype.clearFontCache = function () {
  72. this.fontCache.clearCache();
  73. };
  74. SVG.prototype.reset = function () {
  75. this.clearFontCache();
  76. };
  77. SVG.prototype.setScale = function (node) {
  78. if (this.options.scale !== 1) {
  79. this.adaptor.setStyle(node, 'fontSize', (0, lengths_js_1.percent)(this.options.scale));
  80. }
  81. };
  82. SVG.prototype.escaped = function (math, html) {
  83. this.setDocument(html);
  84. return this.html('span', {}, [this.text(math.math)]);
  85. };
  86. SVG.prototype.styleSheet = function (html) {
  87. if (this.svgStyles) {
  88. return this.svgStyles;
  89. }
  90. var sheet = this.svgStyles = _super.prototype.styleSheet.call(this, html);
  91. this.adaptor.setAttribute(sheet, 'id', SVG.STYLESHEETID);
  92. return sheet;
  93. };
  94. SVG.prototype.pageElements = function (html) {
  95. if (this.options.fontCache === 'global' && !this.findCache(html)) {
  96. return this.svg('svg', { id: SVG.FONTCACHEID, style: { display: 'none' } }, [this.fontCache.getCache()]);
  97. }
  98. return null;
  99. };
  100. SVG.prototype.findCache = function (html) {
  101. var adaptor = this.adaptor;
  102. var svgs = adaptor.tags(adaptor.body(html.document), 'svg');
  103. for (var i = svgs.length - 1; i >= 0; i--) {
  104. if (this.adaptor.getAttribute(svgs[i], 'id') === SVG.FONTCACHEID) {
  105. return true;
  106. }
  107. }
  108. return false;
  109. };
  110. SVG.prototype.processMath = function (math, parent) {
  111. var container = this.container;
  112. this.container = parent;
  113. var wrapper = this.factory.wrap(math);
  114. var _a = __read(this.createRoot(wrapper), 2), svg = _a[0], g = _a[1];
  115. this.typesetSVG(wrapper, svg, g);
  116. this.container = container;
  117. };
  118. SVG.prototype.createRoot = function (wrapper) {
  119. var _a = wrapper.getOuterBBox(), w = _a.w, h = _a.h, d = _a.d, pwidth = _a.pwidth;
  120. var px = wrapper.metrics.em / 1000;
  121. var W = Math.max(w, px);
  122. var H = Math.max(h + d, px);
  123. var g = this.svg('g', {
  124. stroke: 'currentColor', fill: 'currentColor',
  125. 'stroke-width': 0, transform: 'scale(1,-1)'
  126. });
  127. var adaptor = this.adaptor;
  128. var svg = adaptor.append(this.container, this.svg('svg', {
  129. xmlns: exports.SVGNS,
  130. width: this.ex(W), height: this.ex(H),
  131. role: 'img', focusable: false,
  132. style: { 'vertical-align': this.ex(-d) },
  133. viewBox: [0, this.fixed(-h * 1000, 1), this.fixed(W * 1000, 1), this.fixed(H * 1000, 1)].join(' ')
  134. }, [g]));
  135. if (W === .001) {
  136. adaptor.setAttribute(svg, 'preserveAspectRatio', 'xMidYMid slice');
  137. if (w < 0) {
  138. adaptor.setStyle(this.container, 'margin-right', this.ex(w));
  139. }
  140. }
  141. if (pwidth) {
  142. adaptor.setStyle(svg, 'min-width', this.ex(W));
  143. adaptor.setAttribute(svg, 'width', pwidth);
  144. adaptor.removeAttribute(svg, 'viewBox');
  145. var scale = this.fixed(wrapper.metrics.ex / (this.font.params.x_height * 1000), 6);
  146. adaptor.setAttribute(g, 'transform', "scale(".concat(scale, ",-").concat(scale, ") translate(0, ").concat(this.fixed(-h * 1000, 1), ")"));
  147. }
  148. if (this.options.fontCache !== 'none') {
  149. adaptor.setAttribute(svg, 'xmlns:xlink', exports.XLINKNS);
  150. }
  151. return [svg, g];
  152. };
  153. SVG.prototype.typesetSVG = function (wrapper, svg, g) {
  154. var adaptor = this.adaptor;
  155. this.minwidth = this.shift = 0;
  156. if (this.options.fontCache === 'local') {
  157. this.fontCache.clearCache();
  158. this.fontCache.useLocalID(this.options.localID);
  159. adaptor.insert(this.fontCache.getCache(), g);
  160. }
  161. wrapper.toSVG(g);
  162. this.fontCache.clearLocalID();
  163. if (this.minwidth) {
  164. adaptor.setStyle(svg, 'minWidth', this.ex(this.minwidth));
  165. adaptor.setStyle(this.container, 'minWidth', this.ex(this.minwidth));
  166. }
  167. else if (this.shift) {
  168. var align = adaptor.getAttribute(this.container, 'justify') || 'center';
  169. this.setIndent(svg, align, this.shift);
  170. }
  171. };
  172. SVG.prototype.setIndent = function (svg, align, shift) {
  173. if (align === 'center' || align === 'left') {
  174. this.adaptor.setStyle(svg, 'margin-left', this.ex(shift));
  175. }
  176. if (align === 'center' || align === 'right') {
  177. this.adaptor.setStyle(svg, 'margin-right', this.ex(-shift));
  178. }
  179. };
  180. SVG.prototype.ex = function (m) {
  181. m /= this.font.params.x_height;
  182. return (Math.abs(m) < .001 ? '0' : m.toFixed(3).replace(/\.?0+$/, '') + 'ex');
  183. };
  184. SVG.prototype.svg = function (kind, properties, children) {
  185. if (properties === void 0) { properties = {}; }
  186. if (children === void 0) { children = []; }
  187. return this.html(kind, properties, children, exports.SVGNS);
  188. };
  189. SVG.prototype.unknownText = function (text, variant) {
  190. var metrics = this.math.metrics;
  191. var scale = this.font.params.x_height / metrics.ex * metrics.em * 1000;
  192. var svg = this.svg('text', {
  193. 'data-variant': variant,
  194. transform: 'scale(1,-1)', 'font-size': this.fixed(scale, 1) + 'px'
  195. }, [this.text(text)]);
  196. var adaptor = this.adaptor;
  197. if (variant !== '-explicitFont') {
  198. var c = (0, string_js_1.unicodeChars)(text);
  199. if (c.length !== 1 || c[0] < 0x1D400 || c[0] > 0x1D7FF) {
  200. var _a = __read(this.font.getCssFont(variant), 3), family = _a[0], italic = _a[1], bold = _a[2];
  201. adaptor.setAttribute(svg, 'font-family', family);
  202. if (italic) {
  203. adaptor.setAttribute(svg, 'font-style', 'italic');
  204. }
  205. if (bold) {
  206. adaptor.setAttribute(svg, 'font-weight', 'bold');
  207. }
  208. }
  209. }
  210. return svg;
  211. };
  212. SVG.prototype.measureTextNode = function (text) {
  213. var adaptor = this.adaptor;
  214. text = adaptor.clone(text);
  215. adaptor.removeAttribute(text, 'transform');
  216. var ex = this.fixed(this.font.params.x_height * 1000, 1);
  217. var svg = this.svg('svg', {
  218. position: 'absolute', visibility: 'hidden',
  219. width: '1ex', height: '1ex',
  220. viewBox: [0, 0, ex, ex].join(' ')
  221. }, [text]);
  222. adaptor.append(adaptor.body(adaptor.document), svg);
  223. var w = adaptor.nodeSize(text, 1000, true)[0];
  224. adaptor.remove(svg);
  225. return { w: w, h: .75, d: .2 };
  226. };
  227. SVG.NAME = 'SVG';
  228. SVG.OPTIONS = __assign(__assign({}, OutputJax_js_1.CommonOutputJax.OPTIONS), { internalSpeechTitles: true, titleID: 0, fontCache: 'local', localID: null });
  229. SVG.commonStyles = {
  230. 'mjx-container[jax="SVG"]': {
  231. direction: 'ltr'
  232. },
  233. 'mjx-container[jax="SVG"] > svg': {
  234. overflow: 'visible',
  235. 'min-height': '1px',
  236. 'min-width': '1px'
  237. },
  238. 'mjx-container[jax="SVG"] > svg a': {
  239. fill: 'blue', stroke: 'blue'
  240. }
  241. };
  242. SVG.FONTCACHEID = 'MJX-SVG-global-cache';
  243. SVG.STYLESHEETID = 'MJX-SVG-styles';
  244. return SVG;
  245. }(OutputJax_js_1.CommonOutputJax));
  246. exports.SVG = SVG;
  247. //# sourceMappingURL=svg.js.map