index.umd.js 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@antv/g-lite')) :
  3. typeof define === 'function' && define.amd ? define(['exports', '@antv/g-lite'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.G = global.G || {}, global.G.CanvasRenderer = {}), global.window.G));
  5. }(this, (function (exports, gLite) { 'use strict';
  6. function _extends() {
  7. _extends = Object.assign ? Object.assign.bind() : function (target) {
  8. for (var i = 1; i < arguments.length; i++) {
  9. var source = arguments[i];
  10. for (var key in source) {
  11. if (Object.prototype.hasOwnProperty.call(source, key)) {
  12. target[key] = source[key];
  13. }
  14. }
  15. }
  16. return target;
  17. };
  18. return _extends.apply(this, arguments);
  19. }
  20. function _inheritsLoose(subClass, superClass) {
  21. subClass.prototype = Object.create(superClass.prototype);
  22. subClass.prototype.constructor = subClass;
  23. _setPrototypeOf(subClass, superClass);
  24. }
  25. function _setPrototypeOf(o, p) {
  26. _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
  27. o.__proto__ = p;
  28. return o;
  29. };
  30. return _setPrototypeOf(o, p);
  31. }
  32. /**
  33. * Common utilities
  34. * @module glMatrix
  35. */
  36. var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
  37. if (!Math.hypot) Math.hypot = function () {
  38. var y = 0,
  39. i = arguments.length;
  40. while (i--) {
  41. y += arguments[i] * arguments[i];
  42. }
  43. return Math.sqrt(y);
  44. };
  45. /**
  46. * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.
  47. * @module mat4
  48. */
  49. /**
  50. * Creates a new identity mat4
  51. *
  52. * @returns {mat4} a new 4x4 matrix
  53. */
  54. function create() {
  55. var out = new ARRAY_TYPE(16);
  56. if (ARRAY_TYPE != Float32Array) {
  57. out[1] = 0;
  58. out[2] = 0;
  59. out[3] = 0;
  60. out[4] = 0;
  61. out[6] = 0;
  62. out[7] = 0;
  63. out[8] = 0;
  64. out[9] = 0;
  65. out[11] = 0;
  66. out[12] = 0;
  67. out[13] = 0;
  68. out[14] = 0;
  69. }
  70. out[0] = 1;
  71. out[5] = 1;
  72. out[10] = 1;
  73. out[15] = 1;
  74. return out;
  75. }
  76. /**
  77. * Copy the values from one mat4 to another
  78. *
  79. * @param {mat4} out the receiving matrix
  80. * @param {ReadonlyMat4} a the source matrix
  81. * @returns {mat4} out
  82. */
  83. function copy(out, a) {
  84. out[0] = a[0];
  85. out[1] = a[1];
  86. out[2] = a[2];
  87. out[3] = a[3];
  88. out[4] = a[4];
  89. out[5] = a[5];
  90. out[6] = a[6];
  91. out[7] = a[7];
  92. out[8] = a[8];
  93. out[9] = a[9];
  94. out[10] = a[10];
  95. out[11] = a[11];
  96. out[12] = a[12];
  97. out[13] = a[13];
  98. out[14] = a[14];
  99. out[15] = a[15];
  100. return out;
  101. }
  102. /**
  103. * Multiplies two mat4s
  104. *
  105. * @param {mat4} out the receiving matrix
  106. * @param {ReadonlyMat4} a the first operand
  107. * @param {ReadonlyMat4} b the second operand
  108. * @returns {mat4} out
  109. */
  110. function multiply(out, a, b) {
  111. var a00 = a[0],
  112. a01 = a[1],
  113. a02 = a[2],
  114. a03 = a[3];
  115. var a10 = a[4],
  116. a11 = a[5],
  117. a12 = a[6],
  118. a13 = a[7];
  119. var a20 = a[8],
  120. a21 = a[9],
  121. a22 = a[10],
  122. a23 = a[11];
  123. var a30 = a[12],
  124. a31 = a[13],
  125. a32 = a[14],
  126. a33 = a[15]; // Cache only the current line of the second matrix
  127. var b0 = b[0],
  128. b1 = b[1],
  129. b2 = b[2],
  130. b3 = b[3];
  131. out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  132. out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  133. out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  134. out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  135. b0 = b[4];
  136. b1 = b[5];
  137. b2 = b[6];
  138. b3 = b[7];
  139. out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  140. out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  141. out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  142. out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  143. b0 = b[8];
  144. b1 = b[9];
  145. b2 = b[10];
  146. b3 = b[11];
  147. out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  148. out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  149. out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  150. out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  151. b0 = b[12];
  152. b1 = b[13];
  153. b2 = b[14];
  154. b3 = b[15];
  155. out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  156. out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  157. out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  158. out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  159. return out;
  160. }
  161. /**
  162. * Translate a mat4 by the given vector
  163. *
  164. * @param {mat4} out the receiving matrix
  165. * @param {ReadonlyMat4} a the matrix to translate
  166. * @param {ReadonlyVec3} v vector to translate by
  167. * @returns {mat4} out
  168. */
  169. function translate(out, a, v) {
  170. var x = v[0],
  171. y = v[1],
  172. z = v[2];
  173. var a00, a01, a02, a03;
  174. var a10, a11, a12, a13;
  175. var a20, a21, a22, a23;
  176. if (a === out) {
  177. out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
  178. out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
  179. out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
  180. out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
  181. } else {
  182. a00 = a[0];
  183. a01 = a[1];
  184. a02 = a[2];
  185. a03 = a[3];
  186. a10 = a[4];
  187. a11 = a[5];
  188. a12 = a[6];
  189. a13 = a[7];
  190. a20 = a[8];
  191. a21 = a[9];
  192. a22 = a[10];
  193. a23 = a[11];
  194. out[0] = a00;
  195. out[1] = a01;
  196. out[2] = a02;
  197. out[3] = a03;
  198. out[4] = a10;
  199. out[5] = a11;
  200. out[6] = a12;
  201. out[7] = a13;
  202. out[8] = a20;
  203. out[9] = a21;
  204. out[10] = a22;
  205. out[11] = a23;
  206. out[12] = a00 * x + a10 * y + a20 * z + a[12];
  207. out[13] = a01 * x + a11 * y + a21 * z + a[13];
  208. out[14] = a02 * x + a12 * y + a22 * z + a[14];
  209. out[15] = a03 * x + a13 * y + a23 * z + a[15];
  210. }
  211. return out;
  212. }
  213. /**
  214. * Creates a matrix from a vector scaling
  215. * This is equivalent to (but much faster than):
  216. *
  217. * mat4.identity(dest);
  218. * mat4.scale(dest, dest, vec);
  219. *
  220. * @param {mat4} out mat4 receiving operation result
  221. * @param {ReadonlyVec3} v Scaling vector
  222. * @returns {mat4} out
  223. */
  224. function fromScaling(out, v) {
  225. out[0] = v[0];
  226. out[1] = 0;
  227. out[2] = 0;
  228. out[3] = 0;
  229. out[4] = 0;
  230. out[5] = v[1];
  231. out[6] = 0;
  232. out[7] = 0;
  233. out[8] = 0;
  234. out[9] = 0;
  235. out[10] = v[2];
  236. out[11] = 0;
  237. out[12] = 0;
  238. out[13] = 0;
  239. out[14] = 0;
  240. out[15] = 1;
  241. return out;
  242. }
  243. /**
  244. * 3 Dimensional Vector
  245. * @module vec3
  246. */
  247. /**
  248. * Creates a new, empty vec3
  249. *
  250. * @returns {vec3} a new 3D vector
  251. */
  252. function create$1() {
  253. var out = new ARRAY_TYPE(3);
  254. if (ARRAY_TYPE != Float32Array) {
  255. out[0] = 0;
  256. out[1] = 0;
  257. out[2] = 0;
  258. }
  259. return out;
  260. }
  261. /**
  262. * Transforms the vec3 with a mat4.
  263. * 4th vector component is implicitly '1'
  264. *
  265. * @param {vec3} out the receiving vector
  266. * @param {ReadonlyVec3} a the vector to transform
  267. * @param {ReadonlyMat4} m matrix to transform with
  268. * @returns {vec3} out
  269. */
  270. function transformMat4(out, a, m) {
  271. var x = a[0],
  272. y = a[1],
  273. z = a[2];
  274. var w = m[3] * x + m[7] * y + m[11] * z + m[15];
  275. w = w || 1.0;
  276. out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
  277. out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
  278. out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
  279. return out;
  280. }
  281. /**
  282. * Perform some operation over an array of vec3s.
  283. *
  284. * @param {Array} a the array of vectors to iterate over
  285. * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
  286. * @param {Number} offset Number of elements to skip at the beginning of the array
  287. * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
  288. * @param {Function} fn Function to call for each vector in the array
  289. * @param {Object} [arg] additional argument to pass to fn
  290. * @returns {Array} a
  291. * @function
  292. */
  293. var forEach = function () {
  294. var vec = create$1();
  295. return function (a, stride, offset, count, fn, arg) {
  296. var i, l;
  297. if (!stride) {
  298. stride = 3;
  299. }
  300. if (!offset) {
  301. offset = 0;
  302. }
  303. if (count) {
  304. l = Math.min(count * stride + offset, a.length);
  305. } else {
  306. l = a.length;
  307. }
  308. for (i = offset; i < l; i += stride) {
  309. vec[0] = a[i];
  310. vec[1] = a[i + 1];
  311. vec[2] = a[i + 2];
  312. fn(vec, vec, arg);
  313. a[i] = vec[0];
  314. a[i + 1] = vec[1];
  315. a[i + 2] = vec[2];
  316. }
  317. return a;
  318. };
  319. }();
  320. // isFinite,
  321. var isNil = function (value) {
  322. /**
  323. * isNil(null) => true
  324. * isNil() => true
  325. */
  326. return value === null || value === undefined;
  327. };
  328. var toString = {}.toString;
  329. var isType = function (value, type) { return toString.call(value) === '[object ' + type + ']'; };
  330. var isString = (function (str) {
  331. return isType(str, 'String');
  332. });
  333. /**
  334. * support 2 modes in rendering:
  335. * * immediate
  336. * * delayed: render at the end of frame with dirty-rectangle
  337. */
  338. var CanvasRendererPlugin = /*#__PURE__*/function () {
  339. function CanvasRendererPlugin(canvasRendererPluginOptions) {
  340. this.canvasRendererPluginOptions = void 0;
  341. this.context = void 0;
  342. this.pathGeneratorFactory = void 0;
  343. /**
  344. * RBush used in dirty rectangle rendering
  345. */
  346. this.rBush = void 0;
  347. this.removedRBushNodeAABBs = [];
  348. this.renderQueue = [];
  349. /**
  350. * This stack is only used by clipPath for now.
  351. */
  352. this.restoreStack = [];
  353. this.clearFullScreen = false;
  354. /**
  355. * view projection matrix
  356. */
  357. this.vpMatrix = create();
  358. this.dprMatrix = create();
  359. this.tmpMat4 = create();
  360. this.vec3a = create$1();
  361. this.vec3b = create$1();
  362. this.vec3c = create$1();
  363. this.vec3d = create$1();
  364. this.canvasRendererPluginOptions = canvasRendererPluginOptions;
  365. }
  366. var _proto = CanvasRendererPlugin.prototype;
  367. _proto.apply = function apply(context, runtime) {
  368. var _this = this;
  369. this.context = context;
  370. var config = context.config,
  371. camera = context.camera,
  372. renderingService = context.renderingService,
  373. renderingContext = context.renderingContext,
  374. rBushRoot = context.rBushRoot,
  375. pathGeneratorFactory = context.pathGeneratorFactory;
  376. this.rBush = rBushRoot;
  377. this.pathGeneratorFactory = pathGeneratorFactory;
  378. var contextService = context.contextService;
  379. var canvas = renderingContext.root.ownerDocument.defaultView;
  380. var handleUnmounted = function handleUnmounted(e) {
  381. var object = e.target;
  382. // remove r-bush node
  383. // @ts-ignore
  384. var rBushNode = object.rBushNode;
  385. if (rBushNode.aabb) {
  386. // save removed aabbs for dirty-rectangle rendering later
  387. _this.removedRBushNodeAABBs.push(rBushNode.aabb);
  388. }
  389. };
  390. var handleCulled = function handleCulled(e) {
  391. var object = e.target;
  392. // @ts-ignore
  393. var rBushNode = object.rBushNode;
  394. if (rBushNode.aabb) {
  395. // save removed aabbs for dirty-rectangle rendering later
  396. _this.removedRBushNodeAABBs.push(rBushNode.aabb);
  397. }
  398. };
  399. renderingService.hooks.init.tap(CanvasRendererPlugin.tag, function () {
  400. canvas.addEventListener(gLite.ElementEvent.UNMOUNTED, handleUnmounted);
  401. canvas.addEventListener(gLite.ElementEvent.CULLED, handleCulled);
  402. // clear fullscreen
  403. var dpr = contextService.getDPR();
  404. var width = config.width,
  405. height = config.height;
  406. var context = contextService.getContext();
  407. _this.clearRect(context, 0, 0, width * dpr, height * dpr, config.background);
  408. });
  409. renderingService.hooks.destroy.tap(CanvasRendererPlugin.tag, function () {
  410. canvas.removeEventListener(gLite.ElementEvent.UNMOUNTED, handleUnmounted);
  411. canvas.removeEventListener(gLite.ElementEvent.CULLED, handleCulled);
  412. // this.renderQueue = [];
  413. // this.removedRBushNodeAABBs = [];
  414. // this.restoreStack = [];
  415. });
  416. renderingService.hooks.beginFrame.tap(CanvasRendererPlugin.tag, function () {
  417. var context = contextService.getContext();
  418. var dpr = contextService.getDPR();
  419. var width = config.width,
  420. height = config.height;
  421. var _this$canvasRendererP = _this.canvasRendererPluginOptions,
  422. dirtyObjectNumThreshold = _this$canvasRendererP.dirtyObjectNumThreshold,
  423. dirtyObjectRatioThreshold = _this$canvasRendererP.dirtyObjectRatioThreshold;
  424. // some heuristic conditions such as 80% object changed
  425. var _renderingService$get = renderingService.getStats(),
  426. total = _renderingService$get.total,
  427. rendered = _renderingService$get.rendered;
  428. var ratio = rendered / total;
  429. _this.clearFullScreen = renderingService.disableDirtyRectangleRendering() || rendered > dirtyObjectNumThreshold && ratio > dirtyObjectRatioThreshold;
  430. if (context) {
  431. context.resetTransform ? context.resetTransform() : context.setTransform(1, 0, 0, 1, 0, 0);
  432. if (_this.clearFullScreen) {
  433. _this.clearRect(context, 0, 0, width * dpr, height * dpr, config.background);
  434. }
  435. }
  436. });
  437. var renderByZIndex = function renderByZIndex(object, context) {
  438. if (object.isVisible() && !object.isCulled()) {
  439. _this.renderDisplayObject(object, context, _this.context, _this.restoreStack, runtime);
  440. // if (object.renderable.) {
  441. // if we did a full screen rendering last frame
  442. _this.saveDirtyAABB(object);
  443. // }
  444. }
  445. var sorted = object.sortable.sorted || object.childNodes;
  446. // should account for z-index
  447. sorted.forEach(function (child) {
  448. renderByZIndex(child, context);
  449. });
  450. };
  451. // render at the end of frame
  452. renderingService.hooks.endFrame.tap(CanvasRendererPlugin.tag, function () {
  453. var context = contextService.getContext();
  454. // clear & clip dirty rectangle
  455. var dpr = contextService.getDPR();
  456. fromScaling(_this.dprMatrix, [dpr, dpr, 1]);
  457. multiply(_this.vpMatrix, _this.dprMatrix, camera.getOrthoMatrix());
  458. // if (this.clearFullScreen) {
  459. if (_this.clearFullScreen) {
  460. // console.log('canvas renderer fcp...');
  461. renderByZIndex(renderingContext.root, context);
  462. } else {
  463. // console.log('canvas renderer next...');
  464. // merge removed AABB
  465. var dirtyRenderBounds = _this.safeMergeAABB.apply(_this, [_this.mergeDirtyAABBs(_this.renderQueue)].concat(_this.removedRBushNodeAABBs.map(function (_ref) {
  466. var minX = _ref.minX,
  467. minY = _ref.minY,
  468. maxX = _ref.maxX,
  469. maxY = _ref.maxY;
  470. var aabb = new gLite.AABB();
  471. aabb.setMinMax(
  472. // vec3.fromValues(minX, minY, 0),
  473. // vec3.fromValues(maxX, maxY, 0),
  474. [minX, minY, 0], [maxX, maxY, 0]);
  475. return aabb;
  476. })));
  477. _this.removedRBushNodeAABBs = [];
  478. if (gLite.AABB.isEmpty(dirtyRenderBounds)) {
  479. _this.renderQueue = [];
  480. return;
  481. }
  482. var dirtyRect = _this.convertAABB2Rect(dirtyRenderBounds);
  483. var x = dirtyRect.x,
  484. y = dirtyRect.y,
  485. width = dirtyRect.width,
  486. height = dirtyRect.height;
  487. var tl = transformMat4(_this.vec3a, [x, y, 0], _this.vpMatrix);
  488. var tr = transformMat4(_this.vec3b, [x + width, y, 0], _this.vpMatrix);
  489. var bl = transformMat4(_this.vec3c, [x, y + height, 0], _this.vpMatrix);
  490. var br = transformMat4(_this.vec3d, [x + width, y + height, 0], _this.vpMatrix);
  491. var minx = Math.min(tl[0], tr[0], br[0], bl[0]);
  492. var miny = Math.min(tl[1], tr[1], br[1], bl[1]);
  493. var maxx = Math.max(tl[0], tr[0], br[0], bl[0]);
  494. var maxy = Math.max(tl[1], tr[1], br[1], bl[1]);
  495. var ix = Math.floor(minx);
  496. var iy = Math.floor(miny);
  497. var iwidth = Math.ceil(maxx - minx);
  498. var iheight = Math.ceil(maxy - miny);
  499. context.save();
  500. _this.clearRect(context, ix, iy, iwidth, iheight, config.background);
  501. context.beginPath();
  502. context.rect(ix, iy, iwidth, iheight);
  503. context.clip();
  504. // @see https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations
  505. context.setTransform(_this.vpMatrix[0], _this.vpMatrix[1], _this.vpMatrix[4], _this.vpMatrix[5], _this.vpMatrix[12], _this.vpMatrix[13]);
  506. // draw dirty rectangle
  507. var _config$renderer$getC = config.renderer.getConfig(),
  508. enableDirtyRectangleRenderingDebug = _config$renderer$getC.enableDirtyRectangleRenderingDebug;
  509. if (enableDirtyRectangleRenderingDebug) {
  510. canvas.dispatchEvent(new gLite.CustomEvent(gLite.CanvasEvent.DIRTY_RECTANGLE, {
  511. dirtyRect: {
  512. x: ix,
  513. y: iy,
  514. width: iwidth,
  515. height: iheight
  516. }
  517. }));
  518. }
  519. // search objects intersect with dirty rectangle
  520. var dirtyObjects = _this.searchDirtyObjects(dirtyRenderBounds);
  521. // do rendering
  522. dirtyObjects
  523. // sort by z-index
  524. .sort(function (a, b) {
  525. return a.sortable.renderOrder - b.sortable.renderOrder;
  526. }).forEach(function (object) {
  527. // culled object should not be rendered
  528. if (object && object.isVisible() && !object.isCulled()) {
  529. _this.renderDisplayObject(object, context, _this.context, _this.restoreStack, runtime);
  530. }
  531. });
  532. context.restore();
  533. // save dirty AABBs in last frame
  534. _this.renderQueue.forEach(function (object) {
  535. _this.saveDirtyAABB(object);
  536. });
  537. // clear queue
  538. _this.renderQueue = [];
  539. }
  540. // pop restore stack, eg. root -> parent -> child
  541. _this.restoreStack.forEach(function () {
  542. context.restore();
  543. });
  544. // clear restore stack
  545. _this.restoreStack = [];
  546. });
  547. renderingService.hooks.render.tap(CanvasRendererPlugin.tag, function (object) {
  548. if (!_this.clearFullScreen) {
  549. // render at the end of frame
  550. _this.renderQueue.push(object);
  551. }
  552. });
  553. };
  554. _proto.clearRect = function clearRect(context, x, y, width, height, background) {
  555. // clearRect is faster than fillRect @see https://stackoverflow.com/a/30830253
  556. context.clearRect(x, y, width, height);
  557. if (background) {
  558. context.fillStyle = background;
  559. context.fillRect(x, y, width, height);
  560. }
  561. };
  562. _proto.renderDisplayObject = function renderDisplayObject(object, context, canvasContext, restoreStack, runtime) {
  563. var nodeName = object.nodeName;
  564. // console.log('canvas render:', object);
  565. // restore to its ancestor
  566. var parent = restoreStack[restoreStack.length - 1];
  567. if (parent && !(object.compareDocumentPosition(parent) & Node.DOCUMENT_POSITION_CONTAINS)) {
  568. context.restore();
  569. restoreStack.pop();
  570. }
  571. // @ts-ignore
  572. var styleRenderer = this.context.styleRendererFactory[nodeName];
  573. var generatePath = this.pathGeneratorFactory[nodeName];
  574. // clip path
  575. var clipPath = object.parsedStyle.clipPath;
  576. if (clipPath) {
  577. this.applyWorldTransform(context, clipPath);
  578. // generate path in local space
  579. var _generatePath = this.pathGeneratorFactory[clipPath.nodeName];
  580. if (_generatePath) {
  581. context.save();
  582. // save clip
  583. restoreStack.push(object);
  584. context.beginPath();
  585. _generatePath(context, clipPath.parsedStyle);
  586. context.closePath();
  587. context.clip();
  588. }
  589. }
  590. // fill & stroke
  591. if (styleRenderer) {
  592. this.applyWorldTransform(context, object);
  593. context.save();
  594. // apply attributes to context
  595. this.applyAttributesToContext(context, object);
  596. }
  597. if (generatePath) {
  598. context.beginPath();
  599. generatePath(context, object.parsedStyle);
  600. if (object.nodeName !== gLite.Shape.LINE && object.nodeName !== gLite.Shape.PATH && object.nodeName !== gLite.Shape.POLYLINE) {
  601. context.closePath();
  602. }
  603. }
  604. // fill & stroke
  605. if (styleRenderer) {
  606. styleRenderer.render(context, object.parsedStyle, object, canvasContext, this, runtime);
  607. // restore applied attributes, eg. shadowBlur shadowColor...
  608. context.restore();
  609. }
  610. // finish rendering, clear dirty flag
  611. object.renderable.dirty = false;
  612. };
  613. _proto.convertAABB2Rect = function convertAABB2Rect(aabb) {
  614. var min = aabb.getMin();
  615. var max = aabb.getMax();
  616. // expand the rectangle a bit to avoid artifacts
  617. // @see https://www.yuque.com/antv/ou292n/bi8nix#ExvCu
  618. var minX = Math.floor(min[0]);
  619. var minY = Math.floor(min[1]);
  620. var maxX = Math.ceil(max[0]);
  621. var maxY = Math.ceil(max[1]);
  622. var width = maxX - minX;
  623. var height = maxY - minY;
  624. return {
  625. x: minX,
  626. y: minY,
  627. width: width,
  628. height: height
  629. };
  630. }
  631. /**
  632. * TODO: merge dirty rectangles with some strategies.
  633. * For now, we just simply merge all the rectangles into one.
  634. * @see https://idom.me/articles/841.html
  635. */;
  636. _proto.mergeDirtyAABBs = function mergeDirtyAABBs(dirtyObjects) {
  637. // merge into a big AABB
  638. // TODO: skip descendant if ancestor is caculated, but compareNodePosition is really slow
  639. var aabb = new gLite.AABB();
  640. dirtyObjects.forEach(function (object) {
  641. var renderBounds = object.getRenderBounds();
  642. aabb.add(renderBounds);
  643. var dirtyRenderBounds = object.renderable.dirtyRenderBounds;
  644. if (dirtyRenderBounds) {
  645. aabb.add(dirtyRenderBounds);
  646. }
  647. });
  648. return aabb;
  649. };
  650. _proto.searchDirtyObjects = function searchDirtyObjects(dirtyRectangle) {
  651. // search in r-tree, get all affected nodes
  652. var _dirtyRectangle$getMi = dirtyRectangle.getMin(),
  653. minX = _dirtyRectangle$getMi[0],
  654. minY = _dirtyRectangle$getMi[1];
  655. var _dirtyRectangle$getMa = dirtyRectangle.getMax(),
  656. maxX = _dirtyRectangle$getMa[0],
  657. maxY = _dirtyRectangle$getMa[1];
  658. var rBushNodes = this.rBush.search({
  659. minX: minX,
  660. minY: minY,
  661. maxX: maxX,
  662. maxY: maxY
  663. });
  664. return rBushNodes.map(function (_ref2) {
  665. var displayObject = _ref2.displayObject;
  666. return displayObject;
  667. });
  668. };
  669. _proto.saveDirtyAABB = function saveDirtyAABB(object) {
  670. var renderable = object.renderable;
  671. if (!renderable.dirtyRenderBounds) {
  672. renderable.dirtyRenderBounds = new gLite.AABB();
  673. }
  674. var renderBounds = object.getRenderBounds();
  675. if (renderBounds) {
  676. // save last dirty aabb
  677. renderable.dirtyRenderBounds.update(renderBounds.center, renderBounds.halfExtents);
  678. }
  679. }
  680. /**
  681. * TODO: batch the same global attributes
  682. */;
  683. _proto.applyAttributesToContext = function applyAttributesToContext(context, object) {
  684. var _object$parsedStyle = object.parsedStyle,
  685. stroke = _object$parsedStyle.stroke,
  686. fill = _object$parsedStyle.fill,
  687. opacity = _object$parsedStyle.opacity,
  688. lineDash = _object$parsedStyle.lineDash,
  689. lineDashOffset = _object$parsedStyle.lineDashOffset;
  690. // @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/setLineDash
  691. if (lineDash) {
  692. context.setLineDash(lineDash);
  693. }
  694. // @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
  695. if (!isNil(lineDashOffset)) {
  696. context.lineDashOffset = lineDashOffset;
  697. }
  698. if (!isNil(opacity)) {
  699. context.globalAlpha *= opacity;
  700. }
  701. if (!isNil(stroke) && !Array.isArray(stroke) && !stroke.isNone) {
  702. context.strokeStyle = object.attributes.stroke;
  703. }
  704. if (!isNil(fill) && !Array.isArray(fill) && !fill.isNone) {
  705. context.fillStyle = object.attributes.fill;
  706. }
  707. };
  708. _proto.applyWorldTransform = function applyWorldTransform(context, object, matrix) {
  709. var tx = 0;
  710. var ty = 0;
  711. var _ref3 = object.parsedStyle || {},
  712. anchor = _ref3.anchor;
  713. var anchorX = anchor && anchor[0] || 0;
  714. var anchorY = anchor && anchor[1] || 0;
  715. if (anchorX !== 0 || anchorY !== 0) {
  716. // const bounds = object.getGeometryBounds();
  717. var bounds = object.geometry.contentBounds;
  718. var width = bounds && bounds.halfExtents[0] * 2 || 0;
  719. var height = bounds && bounds.halfExtents[1] * 2 || 0;
  720. tx = -(anchorX * width);
  721. ty = -(anchorY * height);
  722. }
  723. // apply clip shape's RTS
  724. if (matrix) {
  725. copy(this.tmpMat4, object.getLocalTransform());
  726. this.vec3a[0] = tx;
  727. this.vec3a[1] = ty;
  728. this.vec3a[2] = 0;
  729. translate(this.tmpMat4, this.tmpMat4, this.vec3a);
  730. multiply(this.tmpMat4, matrix, this.tmpMat4);
  731. multiply(this.tmpMat4, this.vpMatrix, this.tmpMat4);
  732. } else {
  733. // apply RTS transformation in world space
  734. copy(this.tmpMat4, object.getWorldTransform());
  735. this.vec3a[0] = tx;
  736. this.vec3a[1] = ty;
  737. this.vec3a[2] = 0;
  738. translate(this.tmpMat4, this.tmpMat4, this.vec3a);
  739. multiply(this.tmpMat4, this.vpMatrix, this.tmpMat4);
  740. }
  741. // @see https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations
  742. context.setTransform(this.tmpMat4[0], this.tmpMat4[1], this.tmpMat4[4], this.tmpMat4[5], this.tmpMat4[12], this.tmpMat4[13]);
  743. };
  744. _proto.safeMergeAABB = function safeMergeAABB() {
  745. var merged = new gLite.AABB();
  746. for (var _len = arguments.length, aabbs = new Array(_len), _key = 0; _key < _len; _key++) {
  747. aabbs[_key] = arguments[_key];
  748. }
  749. aabbs.forEach(function (aabb) {
  750. merged.add(aabb);
  751. });
  752. return merged;
  753. };
  754. return CanvasRendererPlugin;
  755. }();
  756. CanvasRendererPlugin.tag = 'CanvasRenderer';
  757. var DefaultRenderer = /*#__PURE__*/function () {
  758. function DefaultRenderer(imagePool) {
  759. this.imagePool = void 0;
  760. this.imagePool = imagePool;
  761. }
  762. var _proto = DefaultRenderer.prototype;
  763. _proto.render = function render(context, parsedStyle, object, canvasContext, plugin, runtime) {
  764. var fill = parsedStyle.fill,
  765. fillRule = parsedStyle.fillRule,
  766. opacity = parsedStyle.opacity,
  767. fillOpacity = parsedStyle.fillOpacity,
  768. stroke = parsedStyle.stroke,
  769. strokeOpacity = parsedStyle.strokeOpacity,
  770. lineWidth = parsedStyle.lineWidth,
  771. lineCap = parsedStyle.lineCap,
  772. lineJoin = parsedStyle.lineJoin,
  773. shadowType = parsedStyle.shadowType,
  774. shadowColor = parsedStyle.shadowColor,
  775. shadowBlur = parsedStyle.shadowBlur,
  776. filter = parsedStyle.filter,
  777. miterLimit = parsedStyle.miterLimit;
  778. var hasFill = !isNil(fill) && !fill.isNone;
  779. var hasStroke = !isNil(stroke) && !stroke.isNone && lineWidth > 0;
  780. var isFillTransparent = fill.alpha === 0;
  781. var hasFilter = !!(filter && filter.length);
  782. var hasShadow = !isNil(shadowColor) && shadowBlur > 0;
  783. var nodeName = object.nodeName;
  784. var isInnerShadow = shadowType === 'inner';
  785. var shouldDrawShadowWithStroke = hasStroke && hasShadow && (nodeName === gLite.Shape.PATH || nodeName === gLite.Shape.LINE || nodeName === gLite.Shape.POLYLINE || isFillTransparent || isInnerShadow);
  786. if (hasFill) {
  787. context.globalAlpha = opacity * fillOpacity;
  788. if (!shouldDrawShadowWithStroke) {
  789. setShadowAndFilter(object, context, hasShadow);
  790. }
  791. this.fill(context, object, fill, fillRule, canvasContext, plugin, runtime);
  792. if (!shouldDrawShadowWithStroke) {
  793. this.clearShadowAndFilter(context, hasFilter, hasShadow);
  794. }
  795. }
  796. if (hasStroke) {
  797. context.globalAlpha = opacity * strokeOpacity;
  798. context.lineWidth = lineWidth;
  799. if (!isNil(miterLimit)) {
  800. context.miterLimit = miterLimit;
  801. }
  802. if (!isNil(lineCap)) {
  803. context.lineCap = lineCap;
  804. }
  805. if (!isNil(lineJoin)) {
  806. context.lineJoin = lineJoin;
  807. }
  808. if (shouldDrawShadowWithStroke) {
  809. if (isInnerShadow) {
  810. context.globalCompositeOperation = 'source-atop';
  811. }
  812. setShadowAndFilter(object, context, true);
  813. if (isInnerShadow) {
  814. this.stroke(context, object, stroke, canvasContext, plugin, runtime);
  815. context.globalCompositeOperation = 'source-over';
  816. this.clearShadowAndFilter(context, hasFilter, true);
  817. }
  818. }
  819. this.stroke(context, object, stroke, canvasContext, plugin, runtime);
  820. }
  821. };
  822. _proto.clearShadowAndFilter = function clearShadowAndFilter(context, hasFilter, hasShadow) {
  823. if (hasShadow) {
  824. context.shadowColor = 'transparent';
  825. context.shadowBlur = 0;
  826. }
  827. if (hasFilter) {
  828. // save drop-shadow filter
  829. var oldFilter = context.filter;
  830. if (!isNil(oldFilter) && oldFilter.indexOf('drop-shadow') > -1) {
  831. context.filter = oldFilter.replace(/drop-shadow\([^)]*\)/, '').trim() || 'none';
  832. }
  833. }
  834. };
  835. _proto.fill = function fill(context, object, _fill, fillRule, canvasContext, plugin, runtime) {
  836. var _this = this;
  837. if (Array.isArray(_fill)) {
  838. _fill.forEach(function (gradient) {
  839. context.fillStyle = _this.getColor(gradient, object, context);
  840. fillRule ? context.fill(fillRule) : context.fill();
  841. });
  842. } else {
  843. if (gLite.isPattern(_fill)) {
  844. context.fillStyle = this.getPattern(_fill, object, context, canvasContext, plugin, runtime);
  845. }
  846. fillRule ? context.fill(fillRule) : context.fill();
  847. }
  848. };
  849. _proto.stroke = function stroke(context, object, _stroke, canvasContext, plugin, runtime) {
  850. var _this2 = this;
  851. if (Array.isArray(_stroke)) {
  852. _stroke.forEach(function (gradient) {
  853. context.strokeStyle = _this2.getColor(gradient, object, context);
  854. context.stroke();
  855. });
  856. } else {
  857. if (gLite.isPattern(_stroke)) {
  858. context.strokeStyle = this.getPattern(_stroke, object, context, canvasContext, plugin, runtime);
  859. }
  860. context.stroke();
  861. }
  862. };
  863. _proto.getPattern = function getPattern(pattern, object, context, canvasContext, plugin, runtime) {
  864. var $offscreenCanvas;
  865. var dpr;
  866. if (pattern.image.nodeName === 'rect') {
  867. var _pattern$image$parsed = pattern.image.parsedStyle,
  868. width = _pattern$image$parsed.width,
  869. height = _pattern$image$parsed.height;
  870. dpr = canvasContext.contextService.getDPR();
  871. var offscreenCanvas = canvasContext.config.offscreenCanvas;
  872. $offscreenCanvas = runtime.offscreenCanvas.getOrCreateCanvas(offscreenCanvas);
  873. $offscreenCanvas.width = width * dpr;
  874. $offscreenCanvas.height = height * dpr;
  875. var offscreenCanvasContext = runtime.offscreenCanvas.getOrCreateContext(offscreenCanvas);
  876. var restoreStack = [];
  877. // offscreenCanvasContext.scale(1 / dpr, 1 / dpr);
  878. pattern.image.forEach(function (object) {
  879. plugin.renderDisplayObject(object, offscreenCanvasContext, canvasContext, restoreStack, runtime);
  880. });
  881. restoreStack.forEach(function () {
  882. offscreenCanvasContext.restore();
  883. });
  884. }
  885. var canvasPattern = this.imagePool.getOrCreatePatternSync(pattern, context, $offscreenCanvas, dpr, function () {
  886. // set dirty rectangle flag
  887. object.renderable.dirty = true;
  888. canvasContext.renderingService.dirtify();
  889. });
  890. return canvasPattern;
  891. };
  892. _proto.getColor = function getColor(parsedColor, object, context) {
  893. var color;
  894. if (parsedColor.type === gLite.GradientType.LinearGradient || parsedColor.type === gLite.GradientType.RadialGradient) {
  895. var bounds = object.getGeometryBounds();
  896. var width = bounds && bounds.halfExtents[0] * 2 || 1;
  897. var height = bounds && bounds.halfExtents[1] * 2 || 1;
  898. color = this.imagePool.getOrCreateGradient(_extends({
  899. type: parsedColor.type
  900. }, parsedColor.value, {
  901. width: width,
  902. height: height
  903. }), context);
  904. }
  905. return color;
  906. };
  907. return DefaultRenderer;
  908. }();
  909. /**
  910. * apply before fill and stroke but only once
  911. */
  912. function setShadowAndFilter(object, context, hasShadow) {
  913. var _object$parsedStyle = object.parsedStyle,
  914. filter = _object$parsedStyle.filter,
  915. shadowColor = _object$parsedStyle.shadowColor,
  916. shadowBlur = _object$parsedStyle.shadowBlur,
  917. shadowOffsetX = _object$parsedStyle.shadowOffsetX,
  918. shadowOffsetY = _object$parsedStyle.shadowOffsetY;
  919. if (filter && filter.length) {
  920. // use raw filter string
  921. context.filter = object.style.filter;
  922. }
  923. if (hasShadow) {
  924. context.shadowColor = shadowColor.toString();
  925. context.shadowBlur = shadowBlur || 0;
  926. context.shadowOffsetX = shadowOffsetX || 0;
  927. context.shadowOffsetY = shadowOffsetY || 0;
  928. }
  929. }
  930. var ImageRenderer = /*#__PURE__*/function () {
  931. function ImageRenderer(imagePool) {
  932. this.imagePool = void 0;
  933. this.imagePool = imagePool;
  934. }
  935. var _proto = ImageRenderer.prototype;
  936. _proto.render = function render(context, parsedStyle, object) {
  937. var width = parsedStyle.width,
  938. height = parsedStyle.height,
  939. img = parsedStyle.img,
  940. shadowColor = parsedStyle.shadowColor,
  941. shadowBlur = parsedStyle.shadowBlur;
  942. var image;
  943. var iw = width;
  944. var ih = height;
  945. if (isString(img)) {
  946. // image has been loaded in `mounted` hook
  947. image = this.imagePool.getImageSync(img);
  948. } else {
  949. iw || (iw = img.width);
  950. ih || (ih = img.height);
  951. image = img;
  952. }
  953. if (image) {
  954. var hasShadow = !isNil(shadowColor) && shadowBlur > 0;
  955. setShadowAndFilter(object, context, hasShadow);
  956. // node-canvas will throw the following err:
  957. // Error: Image given has not completed loading
  958. try {
  959. context.drawImage(image, 0, 0, iw, ih);
  960. } catch (e) {}
  961. }
  962. };
  963. return ImageRenderer;
  964. }();
  965. var TextRenderer = /*#__PURE__*/function () {
  966. function TextRenderer() {}
  967. var _proto = TextRenderer.prototype;
  968. _proto.render = function render(context, parsedStyle, object) {
  969. var lineWidth = parsedStyle.lineWidth,
  970. textAlign = parsedStyle.textAlign,
  971. textBaseline = parsedStyle.textBaseline,
  972. lineJoin = parsedStyle.lineJoin,
  973. miterLimit = parsedStyle.miterLimit,
  974. letterSpacing = parsedStyle.letterSpacing,
  975. stroke = parsedStyle.stroke,
  976. fill = parsedStyle.fill,
  977. fillOpacity = parsedStyle.fillOpacity,
  978. strokeOpacity = parsedStyle.strokeOpacity,
  979. opacity = parsedStyle.opacity,
  980. metrics = parsedStyle.metrics,
  981. dx = parsedStyle.dx,
  982. dy = parsedStyle.dy,
  983. shadowColor = parsedStyle.shadowColor,
  984. shadowBlur = parsedStyle.shadowBlur;
  985. var font = metrics.font,
  986. lines = metrics.lines,
  987. height = metrics.height,
  988. lineHeight = metrics.lineHeight,
  989. lineMetrics = metrics.lineMetrics;
  990. context.font = font;
  991. context.lineWidth = lineWidth;
  992. context.textAlign = textAlign === 'middle' ? 'center' : textAlign;
  993. var formattedTextBaseline = textBaseline;
  994. if (
  995. // formattedTextBaseline === 'bottom' ||
  996. !gLite.runtime.enableCSSParsing && formattedTextBaseline === 'alphabetic') {
  997. formattedTextBaseline = 'bottom';
  998. }
  999. context.lineJoin = lineJoin;
  1000. if (!isNil(miterLimit)) {
  1001. context.miterLimit = miterLimit;
  1002. }
  1003. var linePositionY = 0;
  1004. // handle vertical text baseline
  1005. if (textBaseline === 'middle') {
  1006. linePositionY = -height / 2 - lineHeight / 2;
  1007. } else if (textBaseline === 'bottom' || textBaseline === 'alphabetic' || textBaseline === 'ideographic') {
  1008. linePositionY = -height;
  1009. } else if (textBaseline === 'top' || textBaseline === 'hanging') {
  1010. linePositionY = -lineHeight;
  1011. }
  1012. // account for dx & dy
  1013. var offsetX = dx || 0;
  1014. linePositionY += dy || 0;
  1015. if (lines.length === 1) {
  1016. if (formattedTextBaseline === 'bottom') {
  1017. formattedTextBaseline = 'middle';
  1018. linePositionY -= 0.5 * height;
  1019. } else if (formattedTextBaseline === 'top') {
  1020. formattedTextBaseline = 'middle';
  1021. linePositionY += 0.5 * height;
  1022. }
  1023. }
  1024. context.textBaseline = formattedTextBaseline;
  1025. var hasShadow = !isNil(shadowColor) && shadowBlur > 0;
  1026. setShadowAndFilter(object, context, hasShadow);
  1027. // draw lines line by line
  1028. for (var i = 0; i < lines.length; i++) {
  1029. var linePositionX = lineWidth / 2 + offsetX;
  1030. linePositionY += lineHeight;
  1031. // no need to re-position X, cause we already set text align
  1032. // @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
  1033. if (!isNil(stroke) && !stroke.isNone && lineWidth) {
  1034. this.drawLetterSpacing(context, lines[i], lineMetrics[i], textAlign, linePositionX, linePositionY, letterSpacing, fillOpacity, strokeOpacity, opacity, true);
  1035. }
  1036. if (!isNil(fill)) {
  1037. this.drawLetterSpacing(context, lines[i], lineMetrics[i], textAlign, linePositionX, linePositionY, letterSpacing, fillOpacity, strokeOpacity, opacity);
  1038. }
  1039. }
  1040. };
  1041. _proto.drawLetterSpacing = function drawLetterSpacing(context, text, lineMetrics, textAlign, x, y, letterSpacing, fillOpacity, strokeOpacity, opacity, isStroke) {
  1042. if (isStroke === void 0) {
  1043. isStroke = false;
  1044. }
  1045. // letterSpacing of 0 means normal, render all texts directly
  1046. if (letterSpacing === 0) {
  1047. if (isStroke) {
  1048. this.strokeText(context, text, x, y, strokeOpacity);
  1049. } else {
  1050. this.fillText(context, text, x, y, fillOpacity, opacity);
  1051. }
  1052. return;
  1053. }
  1054. // draw text using left align
  1055. var currentTextAlign = context.textAlign;
  1056. context.textAlign = 'left';
  1057. var currentPosition = x;
  1058. if (textAlign === 'center' || textAlign === 'middle') {
  1059. currentPosition = x - lineMetrics.width / 2;
  1060. } else if (textAlign === 'right' || textAlign === 'end') {
  1061. currentPosition = x - lineMetrics.width;
  1062. }
  1063. var stringArray = Array.from(text);
  1064. var previousWidth = context.measureText(text).width;
  1065. var currentWidth = 0;
  1066. for (var i = 0; i < stringArray.length; ++i) {
  1067. var currentChar = stringArray[i];
  1068. if (isStroke) {
  1069. this.strokeText(context, currentChar, currentPosition, y, strokeOpacity);
  1070. } else {
  1071. this.fillText(context, currentChar, currentPosition, y, fillOpacity, opacity);
  1072. }
  1073. currentWidth = context.measureText(text.substring(i + 1)).width;
  1074. currentPosition += previousWidth - currentWidth + letterSpacing;
  1075. previousWidth = currentWidth;
  1076. }
  1077. context.textAlign = currentTextAlign;
  1078. };
  1079. _proto.fillText = function fillText(context, text, x, y, fillOpacity, opacity) {
  1080. var currentGlobalAlpha;
  1081. var applyOpacity = !isNil(fillOpacity) && fillOpacity !== 1;
  1082. if (applyOpacity) {
  1083. currentGlobalAlpha = context.globalAlpha;
  1084. context.globalAlpha = fillOpacity * opacity;
  1085. }
  1086. context.fillText(text, x, y);
  1087. if (applyOpacity) {
  1088. context.globalAlpha = currentGlobalAlpha;
  1089. }
  1090. };
  1091. _proto.strokeText = function strokeText(context, text, x, y, strokeOpacity) {
  1092. var currentGlobalAlpha;
  1093. var applyOpacity = !isNil(strokeOpacity) && strokeOpacity !== 1;
  1094. if (applyOpacity) {
  1095. currentGlobalAlpha = context.globalAlpha;
  1096. context.globalAlpha = strokeOpacity;
  1097. }
  1098. context.strokeText(text, x, y);
  1099. if (applyOpacity) {
  1100. context.globalAlpha = currentGlobalAlpha;
  1101. }
  1102. };
  1103. return TextRenderer;
  1104. }();
  1105. var RectRenderer = /*#__PURE__*/function (_DefaultRenderer) {
  1106. _inheritsLoose(RectRenderer, _DefaultRenderer);
  1107. function RectRenderer() {
  1108. return _DefaultRenderer.apply(this, arguments) || this;
  1109. }
  1110. return RectRenderer;
  1111. }(DefaultRenderer);
  1112. var CircleRenderer = /*#__PURE__*/function (_DefaultRenderer) {
  1113. _inheritsLoose(CircleRenderer, _DefaultRenderer);
  1114. function CircleRenderer() {
  1115. return _DefaultRenderer.apply(this, arguments) || this;
  1116. }
  1117. return CircleRenderer;
  1118. }(DefaultRenderer);
  1119. var EllipseRenderer = /*#__PURE__*/function (_DefaultRenderer) {
  1120. _inheritsLoose(EllipseRenderer, _DefaultRenderer);
  1121. function EllipseRenderer() {
  1122. return _DefaultRenderer.apply(this, arguments) || this;
  1123. }
  1124. return EllipseRenderer;
  1125. }(DefaultRenderer);
  1126. var LineRenderer = /*#__PURE__*/function (_DefaultRenderer) {
  1127. _inheritsLoose(LineRenderer, _DefaultRenderer);
  1128. function LineRenderer() {
  1129. return _DefaultRenderer.apply(this, arguments) || this;
  1130. }
  1131. return LineRenderer;
  1132. }(DefaultRenderer);
  1133. var PolylineRenderer = /*#__PURE__*/function (_DefaultRenderer) {
  1134. _inheritsLoose(PolylineRenderer, _DefaultRenderer);
  1135. function PolylineRenderer() {
  1136. return _DefaultRenderer.apply(this, arguments) || this;
  1137. }
  1138. return PolylineRenderer;
  1139. }(DefaultRenderer);
  1140. var PolygonRenderer = /*#__PURE__*/function (_DefaultRenderer) {
  1141. _inheritsLoose(PolygonRenderer, _DefaultRenderer);
  1142. function PolygonRenderer() {
  1143. return _DefaultRenderer.apply(this, arguments) || this;
  1144. }
  1145. return PolygonRenderer;
  1146. }(DefaultRenderer);
  1147. var PathRenderer = /*#__PURE__*/function (_DefaultRenderer) {
  1148. _inheritsLoose(PathRenderer, _DefaultRenderer);
  1149. function PathRenderer() {
  1150. return _DefaultRenderer.apply(this, arguments) || this;
  1151. }
  1152. return PathRenderer;
  1153. }(DefaultRenderer);
  1154. var Plugin = /*#__PURE__*/function (_AbstractRendererPlug) {
  1155. _inheritsLoose(Plugin, _AbstractRendererPlug);
  1156. function Plugin(options) {
  1157. var _this;
  1158. if (options === void 0) {
  1159. options = {};
  1160. }
  1161. _this = _AbstractRendererPlug.call(this) || this;
  1162. _this.options = void 0;
  1163. _this.name = 'canvas-renderer';
  1164. _this.options = options;
  1165. return _this;
  1166. }
  1167. var _proto = Plugin.prototype;
  1168. _proto.init = function init() {
  1169. var _defaultStyleRenderer;
  1170. var canvasRendererPluginOptions = _extends({
  1171. dirtyObjectNumThreshold: 500,
  1172. dirtyObjectRatioThreshold: 0.8
  1173. }, this.options);
  1174. // @ts-ignore
  1175. var imagePool = this.context.imagePool;
  1176. var defaultRenderer = new DefaultRenderer(imagePool);
  1177. var defaultStyleRendererFactory = (_defaultStyleRenderer = {}, _defaultStyleRenderer[gLite.Shape.CIRCLE] = defaultRenderer, _defaultStyleRenderer[gLite.Shape.ELLIPSE] = defaultRenderer, _defaultStyleRenderer[gLite.Shape.RECT] = defaultRenderer, _defaultStyleRenderer[gLite.Shape.IMAGE] = new ImageRenderer(imagePool), _defaultStyleRenderer[gLite.Shape.TEXT] = new TextRenderer(), _defaultStyleRenderer[gLite.Shape.LINE] = defaultRenderer, _defaultStyleRenderer[gLite.Shape.POLYLINE] = defaultRenderer, _defaultStyleRenderer[gLite.Shape.POLYGON] = defaultRenderer, _defaultStyleRenderer[gLite.Shape.PATH] = defaultRenderer, _defaultStyleRenderer[gLite.Shape.GROUP] = undefined, _defaultStyleRenderer[gLite.Shape.HTML] = undefined, _defaultStyleRenderer[gLite.Shape.MESH] = undefined, _defaultStyleRenderer);
  1178. this.context.defaultStyleRendererFactory = defaultStyleRendererFactory;
  1179. this.context.styleRendererFactory = defaultStyleRendererFactory;
  1180. this.addRenderingPlugin(new CanvasRendererPlugin(canvasRendererPluginOptions));
  1181. };
  1182. _proto.destroy = function destroy() {
  1183. this.removeAllRenderingPlugins();
  1184. delete this.context.defaultStyleRendererFactory;
  1185. delete this.context.styleRendererFactory;
  1186. };
  1187. return Plugin;
  1188. }(gLite.AbstractRendererPlugin);
  1189. exports.CircleRenderer = CircleRenderer;
  1190. exports.EllipseRenderer = EllipseRenderer;
  1191. exports.ImageRenderer = ImageRenderer;
  1192. exports.LineRenderer = LineRenderer;
  1193. exports.PathRenderer = PathRenderer;
  1194. exports.Plugin = Plugin;
  1195. exports.PolygonRenderer = PolygonRenderer;
  1196. exports.PolylineRenderer = PolylineRenderer;
  1197. exports.RectRenderer = RectRenderer;
  1198. exports.TextRenderer = TextRenderer;
  1199. Object.defineProperty(exports, '__esModule', { value: true });
  1200. })));