|
774 | 774 | * Sets fill properties on the current element
|
775 | 775 | */
|
776 | 776 | ctx.prototype.fill = function () {
|
777 |
| - var element = this.__currentElement; |
778 |
| - var matrixString = this.__currentMatrix.toString(); |
| 777 | + var element = getOrCreateElementToApplyStyleTo.call(this, "fill", "stroke"); |
779 | 778 |
|
780 |
| - var group = this.__closestGroupOrSvg(); |
781 |
| - if (group.__hasFill || group.__hasStroke && group.__matrixString !== matrixString) { |
782 |
| - element = this.__currentElement = this.__createElement("path", {}, true); |
783 |
| - group.appendChild(element); |
| 779 | + /** `fillRule` could be first or second argument: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill **/ |
| 780 | + if (arguments[0] === "evenodd" || arguments[1] === "evenodd") { |
| 781 | + element.setAttribute("fill-rule", "evenodd"); |
784 | 782 | }
|
785 | 783 |
|
786 |
| - if (element.nodeName === "path") { |
787 |
| - element.setAttribute("paint-order", "stroke fill markers"); |
788 |
| - |
789 |
| - /** `fillRule` could be first or second argument: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill **/ |
790 |
| - if (arguments[0] === "evenodd" || arguments[1] === "evenodd") { |
791 |
| - element.setAttribute("fill-rule", "evenodd"); |
792 |
| - } |
793 |
| - } |
794 |
| - |
795 |
| - this.__applyCurrentDefaultPath(); |
796 | 784 | this.__applyStyleToCurrentElement("fill");
|
797 | 785 | this.__applyTransform(element, "fill");
|
798 |
| - |
799 |
| - group.__hasFill = true; |
800 |
| - group.__matrixString = matrixString; |
801 | 786 | };
|
802 | 787 |
|
803 | 788 | /**
|
804 | 789 | * Sets the stroke property on the current element
|
805 | 790 | */
|
806 | 791 | ctx.prototype.stroke = function () {
|
| 792 | + var element = getOrCreateElementToApplyStyleTo.call(this, "stroke", "fill"); |
| 793 | + |
| 794 | + this.__applyStyleToCurrentElement("stroke"); |
| 795 | + this.__applyTransform(element, "stroke"); |
| 796 | + }; |
| 797 | + |
| 798 | + function getOrCreateElementToApplyStyleTo(paint1, paint2) { |
807 | 799 | var element = this.__currentElement;
|
808 | 800 | var matrixString = this.__currentMatrix.toString();
|
809 | 801 |
|
810 | 802 | var group = this.__closestGroupOrSvg();
|
811 |
| - if (group.__hasStroke || group.__hasFill && group.__matrixString !== matrixString) { |
812 |
| - element = this.__currentElement = this.__createElement("path", {}, true); |
813 |
| - group.appendChild(element); |
| 803 | + var extras = group.__extras || (group.__extras = {}) |
| 804 | + var currentPath = this.__currentDefaultPath; |
| 805 | + |
| 806 | + if (extras[paint1] || extras[paint2] && extras.matrixString !== matrixString) { |
| 807 | + var pathHasNotChanged = currentPath === extras.currentPath; |
| 808 | + if (pathHasNotChanged) { |
| 809 | + if (element.nodeName === "path") { |
| 810 | + convertPathToDef.call(this, group); |
| 811 | + } |
| 812 | + element = appendUseElement.call(this, group, extras.id); |
| 813 | + } else { |
| 814 | + element = this.__currentElement = this.__createElement("path", {}, true); |
| 815 | + group.appendChild(element); |
| 816 | + this.__applyCurrentDefaultPath(); |
| 817 | + } |
| 818 | + } else { |
| 819 | + this.__applyCurrentDefaultPath(); |
814 | 820 | }
|
815 | 821 |
|
| 822 | + element.setAttribute("paint-order", `${paint2} ${paint1} markers`); |
| 823 | + |
| 824 | + extras[paint1] = true; |
| 825 | + extras.currentPath = currentPath; |
| 826 | + extras.matrixString = matrixString; |
| 827 | + |
| 828 | + return element; |
| 829 | + }; |
| 830 | + |
| 831 | + function convertPathToDef(group, id) { |
| 832 | + var element = this.__currentElement; |
| 833 | + |
| 834 | + /** Create <path> <def> **/ |
| 835 | + var id = group.__extras.id = randomString(this.__ids); |
| 836 | + var link = this.__createElement("path"); |
| 837 | + link.setAttribute("id", id); |
| 838 | + link.setAttribute("d", element.getAttribute("d")); |
| 839 | + this.__defs.appendChild(link); |
| 840 | + |
| 841 | + /** Convert previous <path> to <use> **/ |
816 | 842 | if (element.nodeName === "path") {
|
817 |
| - element.setAttribute("paint-order", "fill stroke markers"); |
| 843 | + element.remove(); |
| 844 | + var attributes = element.attributes; |
| 845 | + element = appendUseElement.call(this, group, id); |
| 846 | + for (var i = 0; i < attributes.length; i ++) { |
| 847 | + var attribute = attributes[i]; |
| 848 | + if (attribute.name === "d") continue; |
| 849 | + element.setAttribute(attribute.name, attribute.value); |
| 850 | + } |
818 | 851 | }
|
| 852 | + }; |
819 | 853 |
|
820 |
| - this.__applyCurrentDefaultPath(); |
821 |
| - this.__applyStyleToCurrentElement("stroke"); |
822 |
| - this.__applyTransform(element, "stroke"); |
823 |
| - |
824 |
| - group.__hasStroke = true; |
825 |
| - group.__matrixString = matrixString; |
| 854 | + function appendUseElement(group, id) { |
| 855 | + var element = this.__currentElement = this.__createElement("use", {}, true); |
| 856 | + element.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", `#${id}`); |
| 857 | + group.appendChild(element); |
| 858 | + return element; |
826 | 859 | };
|
827 | 860 |
|
828 | 861 | /**
|
829 | 862 | * Adds a rectangle to the path.
|
830 | 863 | */
|
831 | 864 | ctx.prototype.rect = function (x, y, width, height) {
|
832 |
| - // var group = this.__closestGroupOrSvg(); |
833 |
| - // if (group.__hasFill || group.__hasStroke) { |
834 |
| - // var element = this.__currentElement = this.__createElement("path", {}, true); |
835 |
| - // group.appendChild(element); |
836 |
| - // } |
837 | 865 | this.moveTo(x, y);
|
838 | 866 | this.lineTo(x+width, y);
|
839 | 867 | this.lineTo(x+width, y+height);
|
|
0 commit comments