|
591 | 591 | ctx.prototype.beginPath = function () {
|
592 | 592 | // Note that there is only one current default path, it is not part of the drawing state.
|
593 | 593 | // See also: https://html.spec.whatwg.org/multipage/scripting.html#current-default-path
|
594 |
| - this.__currentDefaultPath = ""; |
| 594 | + this.__currentPath = ""; |
595 | 595 | this.__currentPosition = {};
|
596 | 596 | };
|
597 | 597 |
|
598 |
| - /** |
599 |
| - * Helper function to apply currentDefaultPath to current path element |
600 |
| - * @private |
601 |
| - */ |
602 |
| - ctx.prototype.__applyCurrentDefaultPath = function () { |
603 |
| - var path = this.__currentDefaultPath; |
604 |
| - if (!path) { |
605 |
| - return |
606 |
| - } |
607 |
| - |
608 |
| - var element = this.__currentElement; |
609 |
| - // if (element.nodeName !== "path") { |
610 |
| - var group = this.__closestGroupOrSvg(); |
611 |
| - element = this.__currentElement = this.__createElement("path", {}, true); |
612 |
| - group.appendChild(element); |
613 |
| - // } |
614 |
| - |
615 |
| - element.setAttribute("d", path); |
616 |
| - }; |
617 |
| - |
618 | 598 | /**
|
619 | 599 | * Adds the move command to the current path element,
|
620 | 600 | * if the currentPathElement is not empty create a new path element
|
621 | 601 | */
|
622 | 602 | ctx.prototype.moveTo = function (x, y) {
|
623 | 603 | // creates a new subpath with the given point
|
624 |
| - this.__currentPosition = {x, y}; |
625 |
| - this.__currentDefaultPath += `M ${x} ${y}`; |
| 604 | + setCurrentpath.call(this, x, y, `M ${x} ${y}`); |
626 | 605 | };
|
627 | 606 |
|
628 | 607 | /**
|
629 | 608 | * Closes the current path
|
630 | 609 | */
|
631 | 610 | ctx.prototype.closePath = function () {
|
632 |
| - if (this.__currentDefaultPath) { |
633 |
| - this.__currentDefaultPath += "Z"; |
| 611 | + if (this.__currentPath) { |
| 612 | + this.__currentPath += "Z"; |
634 | 613 | }
|
635 | 614 | };
|
636 | 615 |
|
637 | 616 | /**
|
638 | 617 | * Adds a line to command
|
639 | 618 | */
|
640 | 619 | ctx.prototype.lineTo = function (x, y) {
|
641 |
| - this.__currentPosition = {x, y}; |
642 |
| - this.__currentDefaultPath += `L ${x} ${y}`; |
| 620 | + setCurrentpath.call(this, x, y, `L ${x} ${y}`); |
643 | 621 | };
|
644 | 622 |
|
645 | 623 | /**
|
646 | 624 | * Add a bezier command
|
647 | 625 | */
|
648 | 626 | ctx.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
|
649 |
| - this.__currentPosition = {x, y}; |
650 |
| - this.__currentDefaultPath += `C ${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x} ${y}`; |
| 627 | + setCurrentpath.call(this, x, y, `C ${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x} ${y}`); |
651 | 628 | };
|
652 | 629 |
|
653 | 630 | /**
|
654 | 631 | * Adds a quadratic curve to command
|
655 | 632 | */
|
656 | 633 | ctx.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
|
657 |
| - this.__currentPosition = {x, y}; |
658 |
| - this.__currentDefaultPath += `Q ${cpx} ${cpy} ${x} ${y}`; |
| 634 | + setCurrentpath.call(this, x, y, `Q ${cpx} ${cpy} ${x} ${y}`); |
659 | 635 | };
|
660 | 636 |
|
| 637 | + function setCurrentpath(x, y, value) { |
| 638 | + this.__currentPosition = {x, y}; |
| 639 | + this.__currentPath || (this.__currentPath = ""); |
| 640 | + this.__currentPath += value; |
| 641 | + } |
661 | 642 |
|
662 | 643 | /**
|
663 | 644 | * Adds the arcTo to the current path
|
|
744 | 725 | var endAngle = getAngle(unit_vec_origin_end_tangent);
|
745 | 726 |
|
746 | 727 | // Connect the point (x0, y0) to the start tangent point by a straight line
|
747 |
| - moveOrLineTo(x + unit_vec_origin_start_tangent[0] * radius, |
748 |
| - y + unit_vec_origin_start_tangent[1] * radius); |
| 728 | + moveOrLineTo.call(this, x + unit_vec_origin_start_tangent[0] * radius, |
| 729 | + y + unit_vec_origin_start_tangent[1] * radius); |
749 | 730 |
|
750 | 731 | // Connect the start tangent point to the end tangent point by arc
|
751 | 732 | // and adding the end tangent point to the subpath.
|
|
776 | 757 | * Sets the stroke property on the current element
|
777 | 758 | */
|
778 | 759 | ctx.prototype.stroke = function () {
|
779 |
| - var element = getOrCreateElementToApplyStyleTo.call(this, "stroke", "fill"); |
| 760 | + getOrCreateElementToApplyStyleTo.call(this, "stroke", "fill"); |
780 | 761 | };
|
781 | 762 |
|
782 | 763 | function getOrCreateElementToApplyStyleTo(paintMethod1, paintMethod2) {
|
783 |
| - var currentPath = this.__currentDefaultPath; |
| 764 | + var currentPath = this.__currentPath; |
784 | 765 | if (!currentPath) {
|
785 | 766 | return
|
786 | 767 | }
|
787 | 768 |
|
788 | 769 | var element = this.__currentElement;
|
789 | 770 | var group = this.__closestGroupOrSvg();
|
790 | 771 | var matrixString = this.__currentMatrix.toString();
|
791 |
| - var extras = group.__extras || (group.__extras = {}) |
792 |
| - if (extras[paintMethod1] || extras[paintMethod2] && extras.matrixString !== matrixString) { |
793 |
| - var pathHasNoChange = currentPath === extras.currentPath; |
| 772 | + var state = group.__state || (group.__state = {}) |
| 773 | + if (state[paintMethod1] || state[paintMethod2] && state.matrixString !== matrixString) { |
| 774 | + var pathHasNoChange = currentPath === state.currentPath; |
794 | 775 | if (pathHasNoChange) {
|
795 | 776 | /** Convert <path> to <def> **/
|
796 | 777 | if (element.nodeName === "path") {
|
797 | 778 | convertPathToDef.call(this, group);
|
798 | 779 | }
|
799 | 780 |
|
800 | 781 | /** Append <use> element references <def> **/
|
801 |
| - element = appendUseElement.call(this, group, extras.id); |
| 782 | + element = appendUseElement.call(this, group, state.id); |
802 | 783 | } else {
|
803 |
| - this.__applyCurrentDefaultPath(); |
| 784 | + applyCurrentDefaultPath.call(this, true); |
804 | 785 | }
|
805 | 786 | } else {
|
806 |
| - this.__applyCurrentDefaultPath(); |
| 787 | + applyCurrentDefaultPath.call(this, false); |
807 | 788 | }
|
808 | 789 |
|
809 | 790 | element.setAttribute("paint-order", `${paintMethod2} ${paintMethod1} markers`);
|
810 | 791 |
|
811 |
| - extras[paintMethod1] = true; |
812 |
| - extras.currentPath = currentPath; |
813 |
| - extras.matrixString = matrixString; |
| 792 | + state[paintMethod1] = true; |
| 793 | + state.currentPath = currentPath; |
| 794 | + state.matrixString = matrixString; |
814 | 795 |
|
815 | 796 | this.__applyStyleToCurrentElement(paintMethod1);
|
816 | 797 | this.__applyTransform(element, paintMethod1);
|
817 | 798 |
|
818 | 799 | return element;
|
819 | 800 | };
|
820 | 801 |
|
821 |
| - function hashString(string) { |
| 802 | + function applyCurrentDefaultPath(needsNewPath) { |
| 803 | + var element = this.__currentElement; |
| 804 | + var path = this.__currentPath; |
| 805 | + if (!path) { |
| 806 | + return |
| 807 | + } |
| 808 | + |
| 809 | + if (needsNewPath || element.nodeName !== "path") { |
| 810 | + var group = this.__closestGroupOrSvg(); |
| 811 | + element = this.__currentElement = this.__createElement("path", {}, true); |
| 812 | + group.appendChild(element); |
| 813 | + } |
| 814 | + |
| 815 | + element.setAttribute("d", path); |
| 816 | + }; |
| 817 | + |
| 818 | + function hashString(string) { |
822 | 819 | /** https://github.com/darkskyapp/string-hash **/
|
823 | 820 | let hash = 5381;
|
824 | 821 | let i = string.length;
|
|
830 | 827 | var element = this.__currentElement;
|
831 | 828 |
|
832 | 829 | /** Create <path> in <defs> **/
|
833 |
| - var extras = group.__extras |
| 830 | + var extras = group.__state |
834 | 831 | var id = extras.id
|
835 | 832 | if (!id) {
|
836 | 833 | id = extras.id = `path-${hashString(extras.currentPath)}`;
|
|
1150 | 1147 | ry = radius,
|
1151 | 1148 | xAxisRotation = 0;
|
1152 | 1149 |
|
1153 |
| - this.__currentDefaultPath += `A ${rx} ${ry} ${xAxisRotation} ${largeArcFlag} ${sweepFlag} ${endX} ${endY}`; |
| 1150 | + this.__currentPath += `A ${rx} ${ry} ${xAxisRotation} ${largeArcFlag} ${sweepFlag} ${endX} ${endY}`; |
1154 | 1151 | this.__currentPosition = {x: endX, y: endY};
|
1155 | 1152 | };
|
1156 | 1153 |
|
1157 | 1154 | function moveOrLineTo(x, y) {
|
1158 |
| - if (this.__currentDefaultPath) { |
| 1155 | + if (this.__currentPath) { |
1159 | 1156 | this.lineTo(x, y);
|
1160 | 1157 | } else {
|
1161 | 1158 | this.moveTo(x, y);
|
|
1166 | 1163 | * Generates a ClipPath from the clip command.
|
1167 | 1164 | */
|
1168 | 1165 | ctx.prototype.clip = function () {
|
1169 |
| - this.__applyCurrentDefaultPath(); |
| 1166 | + applyCurrentDefaultPath.call(this, false); |
1170 | 1167 |
|
1171 | 1168 | var group = this.__closestGroupOrSvg(),
|
1172 | 1169 | clipPath = this.__createElement("clipPath"),
|
1173 |
| - id = randomString(this.__ids), |
| 1170 | + id = randomString(this.__ids), |
1174 | 1171 | newGroup = this.__createElement("g");
|
1175 | 1172 |
|
1176 | 1173 | this.__currentElement.remove();
|
|
0 commit comments