Wrapper.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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 __values = (this && this.__values) || function(o) {
  18. var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
  19. if (m) return m.call(o);
  20. if (o && typeof o.length === "number") return {
  21. next: function () {
  22. if (o && i >= o.length) o = void 0;
  23. return { value: o && o[i++], done: !o };
  24. }
  25. };
  26. throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
  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.SVGWrapper = void 0;
  46. var BBox_js_1 = require("../../util/BBox.js");
  47. var Wrapper_js_1 = require("../common/Wrapper.js");
  48. var svg_js_1 = require("../svg.js");
  49. var SVGWrapper = (function (_super) {
  50. __extends(SVGWrapper, _super);
  51. function SVGWrapper() {
  52. var _this = _super !== null && _super.apply(this, arguments) || this;
  53. _this.element = null;
  54. _this.dx = 0;
  55. return _this;
  56. }
  57. SVGWrapper.prototype.toSVG = function (parent) {
  58. this.addChildren(this.standardSVGnode(parent));
  59. };
  60. SVGWrapper.prototype.addChildren = function (parent) {
  61. var e_1, _a;
  62. var x = 0;
  63. try {
  64. for (var _b = __values(this.childNodes), _c = _b.next(); !_c.done; _c = _b.next()) {
  65. var child = _c.value;
  66. child.toSVG(parent);
  67. var bbox = child.getOuterBBox();
  68. if (child.element) {
  69. child.place(x + bbox.L * bbox.rscale, 0);
  70. }
  71. x += (bbox.L + bbox.w + bbox.R) * bbox.rscale;
  72. }
  73. }
  74. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  75. finally {
  76. try {
  77. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  78. }
  79. finally { if (e_1) throw e_1.error; }
  80. }
  81. };
  82. SVGWrapper.prototype.standardSVGnode = function (parent) {
  83. var svg = this.createSVGnode(parent);
  84. this.handleStyles();
  85. this.handleScale();
  86. this.handleBorder();
  87. this.handleColor();
  88. this.handleAttributes();
  89. return svg;
  90. };
  91. SVGWrapper.prototype.createSVGnode = function (parent) {
  92. this.element = this.svg('g', { 'data-mml-node': this.node.kind });
  93. var href = this.node.attributes.get('href');
  94. if (href) {
  95. parent = this.adaptor.append(parent, this.svg('a', { href: href }));
  96. var _a = this.getOuterBBox(), h = _a.h, d = _a.d, w = _a.w;
  97. this.adaptor.append(this.element, this.svg('rect', {
  98. 'data-hitbox': true, fill: 'none', stroke: 'none', 'pointer-events': 'all',
  99. width: this.fixed(w), height: this.fixed(h + d), y: this.fixed(-d)
  100. }));
  101. }
  102. this.adaptor.append(parent, this.element);
  103. return this.element;
  104. };
  105. SVGWrapper.prototype.handleStyles = function () {
  106. var _this = this;
  107. if (!this.styles)
  108. return;
  109. var styles = this.styles.cssText;
  110. if (styles) {
  111. this.adaptor.setAttribute(this.element, 'style', styles);
  112. }
  113. BBox_js_1.BBox.StyleAdjust.forEach(function (_a) {
  114. var _b = __read(_a, 3), name = _b[0], lr = _b[2];
  115. if (lr !== 0)
  116. return;
  117. var x = _this.styles.get(name);
  118. if (x) {
  119. _this.dx += _this.length2em(x, 1, _this.bbox.rscale);
  120. }
  121. });
  122. };
  123. SVGWrapper.prototype.handleScale = function () {
  124. if (this.bbox.rscale !== 1) {
  125. var scale = 'scale(' + this.fixed(this.bbox.rscale / 1000, 3) + ')';
  126. this.adaptor.setAttribute(this.element, 'transform', scale);
  127. }
  128. };
  129. SVGWrapper.prototype.handleColor = function () {
  130. var _a;
  131. var adaptor = this.adaptor;
  132. var attributes = this.node.attributes;
  133. var mathcolor = attributes.getExplicit('mathcolor');
  134. var color = attributes.getExplicit('color');
  135. var mathbackground = attributes.getExplicit('mathbackground');
  136. var background = attributes.getExplicit('background');
  137. var bgcolor = (((_a = this.styles) === null || _a === void 0 ? void 0 : _a.get('background-color')) || '');
  138. if (mathcolor || color) {
  139. adaptor.setAttribute(this.element, 'fill', mathcolor || color);
  140. adaptor.setAttribute(this.element, 'stroke', mathcolor || color);
  141. }
  142. if (mathbackground || background || bgcolor) {
  143. var _b = this.getOuterBBox(), h = _b.h, d = _b.d, w = _b.w;
  144. var rect = this.svg('rect', {
  145. fill: mathbackground || background || bgcolor,
  146. x: this.fixed(-this.dx), y: this.fixed(-d),
  147. width: this.fixed(w),
  148. height: this.fixed(h + d),
  149. 'data-bgcolor': true
  150. });
  151. var child = adaptor.firstChild(this.element);
  152. if (child) {
  153. adaptor.insert(rect, child);
  154. }
  155. else {
  156. adaptor.append(this.element, rect);
  157. }
  158. }
  159. };
  160. SVGWrapper.prototype.handleBorder = function () {
  161. var e_2, _a, e_3, _b;
  162. if (!this.styles)
  163. return;
  164. var width = Array(4).fill(0);
  165. var style = Array(4);
  166. var color = Array(4);
  167. try {
  168. for (var _c = __values([['Top', 0], ['Right', 1], ['Bottom', 2], ['Left', 3]]), _d = _c.next(); !_d.done; _d = _c.next()) {
  169. var _e = __read(_d.value, 2), name_1 = _e[0], i = _e[1];
  170. var key = 'border' + name_1;
  171. var w_1 = this.styles.get(key + 'Width');
  172. if (!w_1)
  173. continue;
  174. width[i] = Math.max(0, this.length2em(w_1, 1, this.bbox.rscale));
  175. style[i] = this.styles.get(key + 'Style') || 'solid';
  176. color[i] = this.styles.get(key + 'Color') || 'currentColor';
  177. }
  178. }
  179. catch (e_2_1) { e_2 = { error: e_2_1 }; }
  180. finally {
  181. try {
  182. if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
  183. }
  184. finally { if (e_2) throw e_2.error; }
  185. }
  186. var f = SVGWrapper.borderFuzz;
  187. var bbox = this.getOuterBBox();
  188. var _f = __read([bbox.h + f, bbox.d + f, bbox.w + f], 3), h = _f[0], d = _f[1], w = _f[2];
  189. var outerRT = [w, h];
  190. var outerLT = [-f, h];
  191. var outerRB = [w, -d];
  192. var outerLB = [-f, -d];
  193. var innerRT = [w - width[1], h - width[0]];
  194. var innerLT = [-f + width[3], h - width[0]];
  195. var innerRB = [w - width[1], -d + width[2]];
  196. var innerLB = [-f + width[3], -d + width[2]];
  197. var paths = [
  198. [outerLT, outerRT, innerRT, innerLT],
  199. [outerRB, outerRT, innerRT, innerRB],
  200. [outerLB, outerRB, innerRB, innerLB],
  201. [outerLB, outerLT, innerLT, innerLB]
  202. ];
  203. var adaptor = this.adaptor;
  204. var child = adaptor.firstChild(this.element);
  205. try {
  206. for (var _g = __values([0, 1, 2, 3]), _h = _g.next(); !_h.done; _h = _g.next()) {
  207. var i = _h.value;
  208. if (!width[i])
  209. continue;
  210. var path = paths[i];
  211. if (style[i] === 'dashed' || style[i] === 'dotted') {
  212. this.addBorderBroken(path, color[i], style[i], width[i], i);
  213. }
  214. else {
  215. this.addBorderSolid(path, color[i], child);
  216. }
  217. }
  218. }
  219. catch (e_3_1) { e_3 = { error: e_3_1 }; }
  220. finally {
  221. try {
  222. if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
  223. }
  224. finally { if (e_3) throw e_3.error; }
  225. }
  226. };
  227. SVGWrapper.prototype.addBorderSolid = function (path, color, child) {
  228. var _this = this;
  229. var border = this.svg('polygon', {
  230. points: path.map(function (_a) {
  231. var _b = __read(_a, 2), x = _b[0], y = _b[1];
  232. return "".concat(_this.fixed(x - _this.dx), ",").concat(_this.fixed(y));
  233. }).join(' '),
  234. stroke: 'none',
  235. fill: color
  236. });
  237. if (child) {
  238. this.adaptor.insert(border, child);
  239. }
  240. else {
  241. this.adaptor.append(this.element, border);
  242. }
  243. };
  244. SVGWrapper.prototype.addBorderBroken = function (path, color, style, t, i) {
  245. var dot = (style === 'dotted');
  246. var t2 = t / 2;
  247. var _a = __read([[t2, -t2, -t2, -t2], [-t2, t2, -t2, -t2], [t2, t2, -t2, t2], [t2, t2, t2, -t2]][i], 4), tx1 = _a[0], ty1 = _a[1], tx2 = _a[2], ty2 = _a[3];
  248. var _b = __read(path, 2), A = _b[0], B = _b[1];
  249. var x1 = A[0] + tx1 - this.dx, y1 = A[1] + ty1;
  250. var x2 = B[0] + tx2 - this.dx, y2 = B[1] + ty2;
  251. var W = Math.abs(i % 2 ? y2 - y1 : x2 - x1);
  252. var n = (dot ? Math.ceil(W / (2 * t)) : Math.ceil((W - t) / (4 * t)));
  253. var m = W / (4 * n + 1);
  254. var line = this.svg('line', {
  255. x1: this.fixed(x1), y1: this.fixed(y1),
  256. x2: this.fixed(x2), y2: this.fixed(y2),
  257. 'stroke-width': this.fixed(t), stroke: color, 'stroke-linecap': dot ? 'round' : 'square',
  258. 'stroke-dasharray': dot ? [1, this.fixed(W / n - .002)].join(' ') : [this.fixed(m), this.fixed(3 * m)].join(' ')
  259. });
  260. var adaptor = this.adaptor;
  261. var child = adaptor.firstChild(this.element);
  262. if (child) {
  263. adaptor.insert(line, child);
  264. }
  265. else {
  266. adaptor.append(this.element, line);
  267. }
  268. };
  269. SVGWrapper.prototype.handleAttributes = function () {
  270. var e_4, _a, e_5, _b;
  271. var attributes = this.node.attributes;
  272. var defaults = attributes.getAllDefaults();
  273. var skip = SVGWrapper.skipAttributes;
  274. try {
  275. for (var _c = __values(attributes.getExplicitNames()), _d = _c.next(); !_d.done; _d = _c.next()) {
  276. var name_2 = _d.value;
  277. if (skip[name_2] === false || (!(name_2 in defaults) && !skip[name_2] &&
  278. !this.adaptor.hasAttribute(this.element, name_2))) {
  279. this.adaptor.setAttribute(this.element, name_2, attributes.getExplicit(name_2));
  280. }
  281. }
  282. }
  283. catch (e_4_1) { e_4 = { error: e_4_1 }; }
  284. finally {
  285. try {
  286. if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
  287. }
  288. finally { if (e_4) throw e_4.error; }
  289. }
  290. if (attributes.get('class')) {
  291. var names = attributes.get('class').trim().split(/ +/);
  292. try {
  293. for (var names_1 = __values(names), names_1_1 = names_1.next(); !names_1_1.done; names_1_1 = names_1.next()) {
  294. var name_3 = names_1_1.value;
  295. this.adaptor.addClass(this.element, name_3);
  296. }
  297. }
  298. catch (e_5_1) { e_5 = { error: e_5_1 }; }
  299. finally {
  300. try {
  301. if (names_1_1 && !names_1_1.done && (_b = names_1.return)) _b.call(names_1);
  302. }
  303. finally { if (e_5) throw e_5.error; }
  304. }
  305. }
  306. };
  307. SVGWrapper.prototype.place = function (x, y, element) {
  308. if (element === void 0) { element = null; }
  309. x += this.dx;
  310. if (!(x || y))
  311. return;
  312. if (!element) {
  313. element = this.element;
  314. y = this.handleId(y);
  315. }
  316. var translate = "translate(".concat(this.fixed(x), ",").concat(this.fixed(y), ")");
  317. var transform = this.adaptor.getAttribute(element, 'transform') || '';
  318. this.adaptor.setAttribute(element, 'transform', translate + (transform ? ' ' + transform : ''));
  319. };
  320. SVGWrapper.prototype.handleId = function (y) {
  321. if (!this.node.attributes || !this.node.attributes.get('id')) {
  322. return y;
  323. }
  324. var adaptor = this.adaptor;
  325. var h = this.getBBox().h;
  326. var children = adaptor.childNodes(this.element);
  327. children.forEach(function (child) { return adaptor.remove(child); });
  328. var g = this.svg('g', { 'data-idbox': true, transform: "translate(0,".concat(this.fixed(-h), ")") }, children);
  329. adaptor.append(this.element, this.svg('text', { 'data-id-align': true }, [this.text('')]));
  330. adaptor.append(this.element, g);
  331. return y + h;
  332. };
  333. SVGWrapper.prototype.firstChild = function () {
  334. var adaptor = this.adaptor;
  335. var child = adaptor.firstChild(this.element);
  336. if (child && adaptor.kind(child) === 'text' && adaptor.getAttribute(child, 'data-id-align')) {
  337. child = adaptor.firstChild(adaptor.next(child));
  338. }
  339. if (child && adaptor.kind(child) === 'rect' && adaptor.getAttribute(child, 'data-hitbox')) {
  340. child = adaptor.next(child);
  341. }
  342. return child;
  343. };
  344. SVGWrapper.prototype.placeChar = function (n, x, y, parent, variant) {
  345. var e_6, _a;
  346. if (variant === void 0) { variant = null; }
  347. if (variant === null) {
  348. variant = this.variant;
  349. }
  350. var C = n.toString(16).toUpperCase();
  351. var _b = __read(this.getVariantChar(variant, n), 4), w = _b[2], data = _b[3];
  352. if ('p' in data) {
  353. var path = (data.p ? 'M' + data.p + 'Z' : '');
  354. this.place(x, y, this.adaptor.append(parent, this.charNode(variant, C, path)));
  355. }
  356. else if ('c' in data) {
  357. var g = this.adaptor.append(parent, this.svg('g', { 'data-c': C }));
  358. this.place(x, y, g);
  359. x = 0;
  360. try {
  361. for (var _c = __values(this.unicodeChars(data.c, variant)), _d = _c.next(); !_d.done; _d = _c.next()) {
  362. var n_1 = _d.value;
  363. x += this.placeChar(n_1, x, y, g, variant);
  364. }
  365. }
  366. catch (e_6_1) { e_6 = { error: e_6_1 }; }
  367. finally {
  368. try {
  369. if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
  370. }
  371. finally { if (e_6) throw e_6.error; }
  372. }
  373. }
  374. else if (data.unknown) {
  375. var char = String.fromCodePoint(n);
  376. var text = this.adaptor.append(parent, this.jax.unknownText(char, variant));
  377. this.place(x, y, text);
  378. return this.jax.measureTextNodeWithCache(text, char, variant).w;
  379. }
  380. return w;
  381. };
  382. SVGWrapper.prototype.charNode = function (variant, C, path) {
  383. var cache = this.jax.options.fontCache;
  384. return (cache !== 'none' ? this.useNode(variant, C, path) : this.pathNode(C, path));
  385. };
  386. SVGWrapper.prototype.pathNode = function (C, path) {
  387. return this.svg('path', { 'data-c': C, d: path });
  388. };
  389. SVGWrapper.prototype.useNode = function (variant, C, path) {
  390. var use = this.svg('use', { 'data-c': C });
  391. var id = '#' + this.jax.fontCache.cachePath(variant, C, path);
  392. this.adaptor.setAttribute(use, 'href', id, svg_js_1.XLINKNS);
  393. return use;
  394. };
  395. SVGWrapper.prototype.drawBBox = function () {
  396. var _a = this.getBBox(), w = _a.w, h = _a.h, d = _a.d;
  397. var box = this.svg('g', { style: {
  398. opacity: .25
  399. } }, [
  400. this.svg('rect', {
  401. fill: 'red',
  402. height: this.fixed(h),
  403. width: this.fixed(w)
  404. }),
  405. this.svg('rect', {
  406. fill: 'green',
  407. height: this.fixed(d),
  408. width: this.fixed(w),
  409. y: this.fixed(-d)
  410. })
  411. ]);
  412. var node = this.element || this.parent.element;
  413. this.adaptor.append(node, box);
  414. };
  415. SVGWrapper.prototype.html = function (type, def, content) {
  416. if (def === void 0) { def = {}; }
  417. if (content === void 0) { content = []; }
  418. return this.jax.html(type, def, content);
  419. };
  420. SVGWrapper.prototype.svg = function (type, def, content) {
  421. if (def === void 0) { def = {}; }
  422. if (content === void 0) { content = []; }
  423. return this.jax.svg(type, def, content);
  424. };
  425. SVGWrapper.prototype.text = function (text) {
  426. return this.jax.text(text);
  427. };
  428. SVGWrapper.prototype.fixed = function (x, n) {
  429. if (n === void 0) { n = 1; }
  430. return this.jax.fixed(x * 1000, n);
  431. };
  432. SVGWrapper.kind = 'unknown';
  433. SVGWrapper.borderFuzz = 0.005;
  434. return SVGWrapper;
  435. }(Wrapper_js_1.CommonWrapper));
  436. exports.SVGWrapper = SVGWrapper;
  437. //# sourceMappingURL=Wrapper.js.map