PathProxy.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. import * as vec2 from './vector.js';
  2. import BoundingRect from './BoundingRect.js';
  3. import { devicePixelRatio as dpr } from '../config.js';
  4. import { fromLine, fromCubic, fromQuadratic, fromArc } from './bbox.js';
  5. import { cubicLength, cubicSubdivide, quadraticLength, quadraticSubdivide } from './curve.js';
  6. var CMD = {
  7. M: 1,
  8. L: 2,
  9. C: 3,
  10. Q: 4,
  11. A: 5,
  12. Z: 6,
  13. R: 7
  14. };
  15. var tmpOutX = [];
  16. var tmpOutY = [];
  17. var min = [];
  18. var max = [];
  19. var min2 = [];
  20. var max2 = [];
  21. var mathMin = Math.min;
  22. var mathMax = Math.max;
  23. var mathCos = Math.cos;
  24. var mathSin = Math.sin;
  25. var mathAbs = Math.abs;
  26. var PI = Math.PI;
  27. var PI2 = PI * 2;
  28. var hasTypedArray = typeof Float32Array !== 'undefined';
  29. var tmpAngles = [];
  30. function modPI2(radian) {
  31. var n = Math.round(radian / PI * 1e8) / 1e8;
  32. return (n % 2) * PI;
  33. }
  34. export function normalizeArcAngles(angles, anticlockwise) {
  35. var newStartAngle = modPI2(angles[0]);
  36. if (newStartAngle < 0) {
  37. newStartAngle += PI2;
  38. }
  39. var delta = newStartAngle - angles[0];
  40. var newEndAngle = angles[1];
  41. newEndAngle += delta;
  42. if (!anticlockwise && newEndAngle - newStartAngle >= PI2) {
  43. newEndAngle = newStartAngle + PI2;
  44. }
  45. else if (anticlockwise && newStartAngle - newEndAngle >= PI2) {
  46. newEndAngle = newStartAngle - PI2;
  47. }
  48. else if (!anticlockwise && newStartAngle > newEndAngle) {
  49. newEndAngle = newStartAngle + (PI2 - modPI2(newStartAngle - newEndAngle));
  50. }
  51. else if (anticlockwise && newStartAngle < newEndAngle) {
  52. newEndAngle = newStartAngle - (PI2 - modPI2(newEndAngle - newStartAngle));
  53. }
  54. angles[0] = newStartAngle;
  55. angles[1] = newEndAngle;
  56. }
  57. var PathProxy = (function () {
  58. function PathProxy(notSaveData) {
  59. this.dpr = 1;
  60. this._xi = 0;
  61. this._yi = 0;
  62. this._x0 = 0;
  63. this._y0 = 0;
  64. this._len = 0;
  65. if (notSaveData) {
  66. this._saveData = false;
  67. }
  68. if (this._saveData) {
  69. this.data = [];
  70. }
  71. }
  72. PathProxy.prototype.increaseVersion = function () {
  73. this._version++;
  74. };
  75. PathProxy.prototype.getVersion = function () {
  76. return this._version;
  77. };
  78. PathProxy.prototype.setScale = function (sx, sy, segmentIgnoreThreshold) {
  79. segmentIgnoreThreshold = segmentIgnoreThreshold || 0;
  80. if (segmentIgnoreThreshold > 0) {
  81. this._ux = mathAbs(segmentIgnoreThreshold / dpr / sx) || 0;
  82. this._uy = mathAbs(segmentIgnoreThreshold / dpr / sy) || 0;
  83. }
  84. };
  85. PathProxy.prototype.setDPR = function (dpr) {
  86. this.dpr = dpr;
  87. };
  88. PathProxy.prototype.setContext = function (ctx) {
  89. this._ctx = ctx;
  90. };
  91. PathProxy.prototype.getContext = function () {
  92. return this._ctx;
  93. };
  94. PathProxy.prototype.beginPath = function () {
  95. this._ctx && this._ctx.beginPath();
  96. this.reset();
  97. return this;
  98. };
  99. PathProxy.prototype.reset = function () {
  100. if (this._saveData) {
  101. this._len = 0;
  102. }
  103. if (this._pathSegLen) {
  104. this._pathSegLen = null;
  105. this._pathLen = 0;
  106. }
  107. this._version++;
  108. };
  109. PathProxy.prototype.moveTo = function (x, y) {
  110. this._drawPendingPt();
  111. this.addData(CMD.M, x, y);
  112. this._ctx && this._ctx.moveTo(x, y);
  113. this._x0 = x;
  114. this._y0 = y;
  115. this._xi = x;
  116. this._yi = y;
  117. return this;
  118. };
  119. PathProxy.prototype.lineTo = function (x, y) {
  120. var dx = mathAbs(x - this._xi);
  121. var dy = mathAbs(y - this._yi);
  122. var exceedUnit = dx > this._ux || dy > this._uy;
  123. this.addData(CMD.L, x, y);
  124. if (this._ctx && exceedUnit) {
  125. this._ctx.lineTo(x, y);
  126. }
  127. if (exceedUnit) {
  128. this._xi = x;
  129. this._yi = y;
  130. this._pendingPtDist = 0;
  131. }
  132. else {
  133. var d2 = dx * dx + dy * dy;
  134. if (d2 > this._pendingPtDist) {
  135. this._pendingPtX = x;
  136. this._pendingPtY = y;
  137. this._pendingPtDist = d2;
  138. }
  139. }
  140. return this;
  141. };
  142. PathProxy.prototype.bezierCurveTo = function (x1, y1, x2, y2, x3, y3) {
  143. this._drawPendingPt();
  144. this.addData(CMD.C, x1, y1, x2, y2, x3, y3);
  145. if (this._ctx) {
  146. this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
  147. }
  148. this._xi = x3;
  149. this._yi = y3;
  150. return this;
  151. };
  152. PathProxy.prototype.quadraticCurveTo = function (x1, y1, x2, y2) {
  153. this._drawPendingPt();
  154. this.addData(CMD.Q, x1, y1, x2, y2);
  155. if (this._ctx) {
  156. this._ctx.quadraticCurveTo(x1, y1, x2, y2);
  157. }
  158. this._xi = x2;
  159. this._yi = y2;
  160. return this;
  161. };
  162. PathProxy.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) {
  163. this._drawPendingPt();
  164. tmpAngles[0] = startAngle;
  165. tmpAngles[1] = endAngle;
  166. normalizeArcAngles(tmpAngles, anticlockwise);
  167. startAngle = tmpAngles[0];
  168. endAngle = tmpAngles[1];
  169. var delta = endAngle - startAngle;
  170. this.addData(CMD.A, cx, cy, r, r, startAngle, delta, 0, anticlockwise ? 0 : 1);
  171. this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);
  172. this._xi = mathCos(endAngle) * r + cx;
  173. this._yi = mathSin(endAngle) * r + cy;
  174. return this;
  175. };
  176. PathProxy.prototype.arcTo = function (x1, y1, x2, y2, radius) {
  177. this._drawPendingPt();
  178. if (this._ctx) {
  179. this._ctx.arcTo(x1, y1, x2, y2, radius);
  180. }
  181. return this;
  182. };
  183. PathProxy.prototype.rect = function (x, y, w, h) {
  184. this._drawPendingPt();
  185. this._ctx && this._ctx.rect(x, y, w, h);
  186. this.addData(CMD.R, x, y, w, h);
  187. return this;
  188. };
  189. PathProxy.prototype.closePath = function () {
  190. this._drawPendingPt();
  191. this.addData(CMD.Z);
  192. var ctx = this._ctx;
  193. var x0 = this._x0;
  194. var y0 = this._y0;
  195. if (ctx) {
  196. ctx.closePath();
  197. }
  198. this._xi = x0;
  199. this._yi = y0;
  200. return this;
  201. };
  202. PathProxy.prototype.fill = function (ctx) {
  203. ctx && ctx.fill();
  204. this.toStatic();
  205. };
  206. PathProxy.prototype.stroke = function (ctx) {
  207. ctx && ctx.stroke();
  208. this.toStatic();
  209. };
  210. PathProxy.prototype.len = function () {
  211. return this._len;
  212. };
  213. PathProxy.prototype.setData = function (data) {
  214. if (!this._saveData) {
  215. return;
  216. }
  217. var len = data.length;
  218. if (!(this.data && this.data.length === len) && hasTypedArray) {
  219. this.data = new Float32Array(len);
  220. }
  221. for (var i = 0; i < len; i++) {
  222. this.data[i] = data[i];
  223. }
  224. this._len = len;
  225. };
  226. PathProxy.prototype.appendPath = function (path) {
  227. if (!this._saveData) {
  228. return;
  229. }
  230. if (!(path instanceof Array)) {
  231. path = [path];
  232. }
  233. var len = path.length;
  234. var appendSize = 0;
  235. var offset = this._len;
  236. for (var i = 0; i < len; i++) {
  237. appendSize += path[i].len();
  238. }
  239. var oldData = this.data;
  240. if (hasTypedArray && (oldData instanceof Float32Array || !oldData)) {
  241. this.data = new Float32Array(offset + appendSize);
  242. if (offset > 0 && oldData) {
  243. for (var k = 0; k < offset; k++) {
  244. this.data[k] = oldData[k];
  245. }
  246. }
  247. }
  248. for (var i = 0; i < len; i++) {
  249. var appendPathData = path[i].data;
  250. for (var k = 0; k < appendPathData.length; k++) {
  251. this.data[offset++] = appendPathData[k];
  252. }
  253. }
  254. this._len = offset;
  255. };
  256. PathProxy.prototype.addData = function (cmd, a, b, c, d, e, f, g, h) {
  257. if (!this._saveData) {
  258. return;
  259. }
  260. var data = this.data;
  261. if (this._len + arguments.length > data.length) {
  262. this._expandData();
  263. data = this.data;
  264. }
  265. for (var i = 0; i < arguments.length; i++) {
  266. data[this._len++] = arguments[i];
  267. }
  268. };
  269. PathProxy.prototype._drawPendingPt = function () {
  270. if (this._pendingPtDist > 0) {
  271. this._ctx && this._ctx.lineTo(this._pendingPtX, this._pendingPtY);
  272. this._pendingPtDist = 0;
  273. }
  274. };
  275. PathProxy.prototype._expandData = function () {
  276. if (!(this.data instanceof Array)) {
  277. var newData = [];
  278. for (var i = 0; i < this._len; i++) {
  279. newData[i] = this.data[i];
  280. }
  281. this.data = newData;
  282. }
  283. };
  284. PathProxy.prototype.toStatic = function () {
  285. if (!this._saveData) {
  286. return;
  287. }
  288. this._drawPendingPt();
  289. var data = this.data;
  290. if (data instanceof Array) {
  291. data.length = this._len;
  292. if (hasTypedArray && this._len > 11) {
  293. this.data = new Float32Array(data);
  294. }
  295. }
  296. };
  297. PathProxy.prototype.getBoundingRect = function () {
  298. min[0] = min[1] = min2[0] = min2[1] = Number.MAX_VALUE;
  299. max[0] = max[1] = max2[0] = max2[1] = -Number.MAX_VALUE;
  300. var data = this.data;
  301. var xi = 0;
  302. var yi = 0;
  303. var x0 = 0;
  304. var y0 = 0;
  305. var i;
  306. for (i = 0; i < this._len;) {
  307. var cmd = data[i++];
  308. var isFirst = i === 1;
  309. if (isFirst) {
  310. xi = data[i];
  311. yi = data[i + 1];
  312. x0 = xi;
  313. y0 = yi;
  314. }
  315. switch (cmd) {
  316. case CMD.M:
  317. xi = x0 = data[i++];
  318. yi = y0 = data[i++];
  319. min2[0] = x0;
  320. min2[1] = y0;
  321. max2[0] = x0;
  322. max2[1] = y0;
  323. break;
  324. case CMD.L:
  325. fromLine(xi, yi, data[i], data[i + 1], min2, max2);
  326. xi = data[i++];
  327. yi = data[i++];
  328. break;
  329. case CMD.C:
  330. fromCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], min2, max2);
  331. xi = data[i++];
  332. yi = data[i++];
  333. break;
  334. case CMD.Q:
  335. fromQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], min2, max2);
  336. xi = data[i++];
  337. yi = data[i++];
  338. break;
  339. case CMD.A:
  340. var cx = data[i++];
  341. var cy = data[i++];
  342. var rx = data[i++];
  343. var ry = data[i++];
  344. var startAngle = data[i++];
  345. var endAngle = data[i++] + startAngle;
  346. i += 1;
  347. var anticlockwise = !data[i++];
  348. if (isFirst) {
  349. x0 = mathCos(startAngle) * rx + cx;
  350. y0 = mathSin(startAngle) * ry + cy;
  351. }
  352. fromArc(cx, cy, rx, ry, startAngle, endAngle, anticlockwise, min2, max2);
  353. xi = mathCos(endAngle) * rx + cx;
  354. yi = mathSin(endAngle) * ry + cy;
  355. break;
  356. case CMD.R:
  357. x0 = xi = data[i++];
  358. y0 = yi = data[i++];
  359. var width = data[i++];
  360. var height = data[i++];
  361. fromLine(x0, y0, x0 + width, y0 + height, min2, max2);
  362. break;
  363. case CMD.Z:
  364. xi = x0;
  365. yi = y0;
  366. break;
  367. }
  368. vec2.min(min, min, min2);
  369. vec2.max(max, max, max2);
  370. }
  371. if (i === 0) {
  372. min[0] = min[1] = max[0] = max[1] = 0;
  373. }
  374. return new BoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]);
  375. };
  376. PathProxy.prototype._calculateLength = function () {
  377. var data = this.data;
  378. var len = this._len;
  379. var ux = this._ux;
  380. var uy = this._uy;
  381. var xi = 0;
  382. var yi = 0;
  383. var x0 = 0;
  384. var y0 = 0;
  385. if (!this._pathSegLen) {
  386. this._pathSegLen = [];
  387. }
  388. var pathSegLen = this._pathSegLen;
  389. var pathTotalLen = 0;
  390. var segCount = 0;
  391. for (var i = 0; i < len;) {
  392. var cmd = data[i++];
  393. var isFirst = i === 1;
  394. if (isFirst) {
  395. xi = data[i];
  396. yi = data[i + 1];
  397. x0 = xi;
  398. y0 = yi;
  399. }
  400. var l = -1;
  401. switch (cmd) {
  402. case CMD.M:
  403. xi = x0 = data[i++];
  404. yi = y0 = data[i++];
  405. break;
  406. case CMD.L: {
  407. var x2 = data[i++];
  408. var y2 = data[i++];
  409. var dx = x2 - xi;
  410. var dy = y2 - yi;
  411. if (mathAbs(dx) > ux || mathAbs(dy) > uy || i === len - 1) {
  412. l = Math.sqrt(dx * dx + dy * dy);
  413. xi = x2;
  414. yi = y2;
  415. }
  416. break;
  417. }
  418. case CMD.C: {
  419. var x1 = data[i++];
  420. var y1 = data[i++];
  421. var x2 = data[i++];
  422. var y2 = data[i++];
  423. var x3 = data[i++];
  424. var y3 = data[i++];
  425. l = cubicLength(xi, yi, x1, y1, x2, y2, x3, y3, 10);
  426. xi = x3;
  427. yi = y3;
  428. break;
  429. }
  430. case CMD.Q: {
  431. var x1 = data[i++];
  432. var y1 = data[i++];
  433. var x2 = data[i++];
  434. var y2 = data[i++];
  435. l = quadraticLength(xi, yi, x1, y1, x2, y2, 10);
  436. xi = x2;
  437. yi = y2;
  438. break;
  439. }
  440. case CMD.A:
  441. var cx = data[i++];
  442. var cy = data[i++];
  443. var rx = data[i++];
  444. var ry = data[i++];
  445. var startAngle = data[i++];
  446. var delta = data[i++];
  447. var endAngle = delta + startAngle;
  448. i += 1;
  449. if (isFirst) {
  450. x0 = mathCos(startAngle) * rx + cx;
  451. y0 = mathSin(startAngle) * ry + cy;
  452. }
  453. l = mathMax(rx, ry) * mathMin(PI2, Math.abs(delta));
  454. xi = mathCos(endAngle) * rx + cx;
  455. yi = mathSin(endAngle) * ry + cy;
  456. break;
  457. case CMD.R: {
  458. x0 = xi = data[i++];
  459. y0 = yi = data[i++];
  460. var width = data[i++];
  461. var height = data[i++];
  462. l = width * 2 + height * 2;
  463. break;
  464. }
  465. case CMD.Z: {
  466. var dx = x0 - xi;
  467. var dy = y0 - yi;
  468. l = Math.sqrt(dx * dx + dy * dy);
  469. xi = x0;
  470. yi = y0;
  471. break;
  472. }
  473. }
  474. if (l >= 0) {
  475. pathSegLen[segCount++] = l;
  476. pathTotalLen += l;
  477. }
  478. }
  479. this._pathLen = pathTotalLen;
  480. return pathTotalLen;
  481. };
  482. PathProxy.prototype.rebuildPath = function (ctx, percent) {
  483. var d = this.data;
  484. var ux = this._ux;
  485. var uy = this._uy;
  486. var len = this._len;
  487. var x0;
  488. var y0;
  489. var xi;
  490. var yi;
  491. var x;
  492. var y;
  493. var drawPart = percent < 1;
  494. var pathSegLen;
  495. var pathTotalLen;
  496. var accumLength = 0;
  497. var segCount = 0;
  498. var displayedLength;
  499. var pendingPtDist = 0;
  500. var pendingPtX;
  501. var pendingPtY;
  502. if (drawPart) {
  503. if (!this._pathSegLen) {
  504. this._calculateLength();
  505. }
  506. pathSegLen = this._pathSegLen;
  507. pathTotalLen = this._pathLen;
  508. displayedLength = percent * pathTotalLen;
  509. if (!displayedLength) {
  510. return;
  511. }
  512. }
  513. lo: for (var i = 0; i < len;) {
  514. var cmd = d[i++];
  515. var isFirst = i === 1;
  516. if (isFirst) {
  517. xi = d[i];
  518. yi = d[i + 1];
  519. x0 = xi;
  520. y0 = yi;
  521. }
  522. if (cmd !== CMD.L && pendingPtDist > 0) {
  523. ctx.lineTo(pendingPtX, pendingPtY);
  524. pendingPtDist = 0;
  525. }
  526. switch (cmd) {
  527. case CMD.M:
  528. x0 = xi = d[i++];
  529. y0 = yi = d[i++];
  530. ctx.moveTo(xi, yi);
  531. break;
  532. case CMD.L: {
  533. x = d[i++];
  534. y = d[i++];
  535. var dx = mathAbs(x - xi);
  536. var dy = mathAbs(y - yi);
  537. if (dx > ux || dy > uy) {
  538. if (drawPart) {
  539. var l = pathSegLen[segCount++];
  540. if (accumLength + l > displayedLength) {
  541. var t = (displayedLength - accumLength) / l;
  542. ctx.lineTo(xi * (1 - t) + x * t, yi * (1 - t) + y * t);
  543. break lo;
  544. }
  545. accumLength += l;
  546. }
  547. ctx.lineTo(x, y);
  548. xi = x;
  549. yi = y;
  550. pendingPtDist = 0;
  551. }
  552. else {
  553. var d2 = dx * dx + dy * dy;
  554. if (d2 > pendingPtDist) {
  555. pendingPtX = x;
  556. pendingPtY = y;
  557. pendingPtDist = d2;
  558. }
  559. }
  560. break;
  561. }
  562. case CMD.C: {
  563. var x1 = d[i++];
  564. var y1 = d[i++];
  565. var x2 = d[i++];
  566. var y2 = d[i++];
  567. var x3 = d[i++];
  568. var y3 = d[i++];
  569. if (drawPart) {
  570. var l = pathSegLen[segCount++];
  571. if (accumLength + l > displayedLength) {
  572. var t = (displayedLength - accumLength) / l;
  573. cubicSubdivide(xi, x1, x2, x3, t, tmpOutX);
  574. cubicSubdivide(yi, y1, y2, y3, t, tmpOutY);
  575. ctx.bezierCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2], tmpOutX[3], tmpOutY[3]);
  576. break lo;
  577. }
  578. accumLength += l;
  579. }
  580. ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
  581. xi = x3;
  582. yi = y3;
  583. break;
  584. }
  585. case CMD.Q: {
  586. var x1 = d[i++];
  587. var y1 = d[i++];
  588. var x2 = d[i++];
  589. var y2 = d[i++];
  590. if (drawPart) {
  591. var l = pathSegLen[segCount++];
  592. if (accumLength + l > displayedLength) {
  593. var t = (displayedLength - accumLength) / l;
  594. quadraticSubdivide(xi, x1, x2, t, tmpOutX);
  595. quadraticSubdivide(yi, y1, y2, t, tmpOutY);
  596. ctx.quadraticCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2]);
  597. break lo;
  598. }
  599. accumLength += l;
  600. }
  601. ctx.quadraticCurveTo(x1, y1, x2, y2);
  602. xi = x2;
  603. yi = y2;
  604. break;
  605. }
  606. case CMD.A:
  607. var cx = d[i++];
  608. var cy = d[i++];
  609. var rx = d[i++];
  610. var ry = d[i++];
  611. var startAngle = d[i++];
  612. var delta = d[i++];
  613. var psi = d[i++];
  614. var anticlockwise = !d[i++];
  615. var r = (rx > ry) ? rx : ry;
  616. var isEllipse = mathAbs(rx - ry) > 1e-3;
  617. var endAngle = startAngle + delta;
  618. var breakBuild = false;
  619. if (drawPart) {
  620. var l = pathSegLen[segCount++];
  621. if (accumLength + l > displayedLength) {
  622. endAngle = startAngle + delta * (displayedLength - accumLength) / l;
  623. breakBuild = true;
  624. }
  625. accumLength += l;
  626. }
  627. if (isEllipse && ctx.ellipse) {
  628. ctx.ellipse(cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise);
  629. }
  630. else {
  631. ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);
  632. }
  633. if (breakBuild) {
  634. break lo;
  635. }
  636. if (isFirst) {
  637. x0 = mathCos(startAngle) * rx + cx;
  638. y0 = mathSin(startAngle) * ry + cy;
  639. }
  640. xi = mathCos(endAngle) * rx + cx;
  641. yi = mathSin(endAngle) * ry + cy;
  642. break;
  643. case CMD.R:
  644. x0 = xi = d[i];
  645. y0 = yi = d[i + 1];
  646. x = d[i++];
  647. y = d[i++];
  648. var width = d[i++];
  649. var height = d[i++];
  650. if (drawPart) {
  651. var l = pathSegLen[segCount++];
  652. if (accumLength + l > displayedLength) {
  653. var d_1 = displayedLength - accumLength;
  654. ctx.moveTo(x, y);
  655. ctx.lineTo(x + mathMin(d_1, width), y);
  656. d_1 -= width;
  657. if (d_1 > 0) {
  658. ctx.lineTo(x + width, y + mathMin(d_1, height));
  659. }
  660. d_1 -= height;
  661. if (d_1 > 0) {
  662. ctx.lineTo(x + mathMax(width - d_1, 0), y + height);
  663. }
  664. d_1 -= width;
  665. if (d_1 > 0) {
  666. ctx.lineTo(x, y + mathMax(height - d_1, 0));
  667. }
  668. break lo;
  669. }
  670. accumLength += l;
  671. }
  672. ctx.rect(x, y, width, height);
  673. break;
  674. case CMD.Z:
  675. if (drawPart) {
  676. var l = pathSegLen[segCount++];
  677. if (accumLength + l > displayedLength) {
  678. var t = (displayedLength - accumLength) / l;
  679. ctx.lineTo(xi * (1 - t) + x0 * t, yi * (1 - t) + y0 * t);
  680. break lo;
  681. }
  682. accumLength += l;
  683. }
  684. ctx.closePath();
  685. xi = x0;
  686. yi = y0;
  687. }
  688. }
  689. };
  690. PathProxy.prototype.clone = function () {
  691. var newProxy = new PathProxy();
  692. var data = this.data;
  693. newProxy.data = data.slice ? data.slice()
  694. : Array.prototype.slice.call(data);
  695. newProxy._len = this._len;
  696. return newProxy;
  697. };
  698. PathProxy.prototype.canSave = function () {
  699. return !!this._saveData;
  700. };
  701. PathProxy.CMD = CMD;
  702. PathProxy.initDefaultProps = (function () {
  703. var proto = PathProxy.prototype;
  704. proto._saveData = true;
  705. proto._ux = 0;
  706. proto._uy = 0;
  707. proto._pendingPtDist = 0;
  708. proto._version = 0;
  709. })();
  710. return PathProxy;
  711. }());
  712. export default PathProxy;