|
373 | 373 | for (i = 0; i < keys.length; i++) {
|
374 | 374 | var key = keys[i]
|
375 | 375 | style = STYLES[key];
|
376 |
| - |
377 | 376 | var attributeKey = style.apply
|
378 | 377 | if (!attributeKey || !attributeKey.includes(paintMethod)) {
|
379 | 378 | continue;
|
|
492 | 491 | var state = this.__getStyleState();
|
493 | 492 | this.__groupStack.push(parent);
|
494 | 493 | parent.appendChild(group);
|
495 |
| - this.__applyTransform(group); |
496 | 494 | this.__currentElement = group;
|
497 |
| - this.__currentMatrix = new DOMMatrix(); |
498 | 495 | this.__stack.push(state);
|
499 | 496 | };
|
500 | 497 |
|
|
506 | 503 | var state = this.__stack.pop();
|
507 | 504 |
|
508 | 505 | /** Prune empty group created when running save/restore without any content **/
|
509 |
| - var node = this.__currentElement |
| 506 | + var node = this.__currentElement; |
510 | 507 | if (node.nodeName === 'g' && !node.childNodes.length) {
|
511 |
| - node.remove() |
| 508 | + node.remove(); |
512 | 509 | }
|
513 | 510 |
|
514 | 511 | this.__currentElementsToStyle = null;
|
|
533 | 530 | }
|
534 | 531 |
|
535 | 532 | var styleId = style.__root.getAttribute("id");
|
536 |
| - var linkedReferences = ++style.__linkedReferences |
537 |
| - var id = `${styleId}-${linkedReferences}` |
538 |
| - element.setAttribute(paintMethod, `url(#${id})`) |
| 533 | + var linkedReferences = ++style.__linkedReferences; |
| 534 | + var id = `${styleId}-${linkedReferences}`; |
| 535 | + element.setAttribute(paintMethod, `url(#${id})`); |
539 | 536 |
|
540 | 537 | var link = this.__createElement(style.__root.nodeName);
|
541 | 538 | link.setAttribute("id", id)
|
|
547 | 544 | link.setAttribute("patternTransform", matrix.toString());
|
548 | 545 | }
|
549 | 546 |
|
550 |
| - this.__defs.appendChild(link) |
551 |
| - } else { |
552 |
| - element.setAttribute("transform", matrix.toString()); |
| 547 | + this.__defs.appendChild(link); |
| 548 | + return; |
553 | 549 | }
|
| 550 | + |
| 551 | + element.setAttribute("transform", matrix.toString()); |
554 | 552 | };
|
555 | 553 |
|
556 | 554 | /**
|
|
602 | 600 | this.__currentPosition = {};
|
603 | 601 | };
|
604 | 602 |
|
605 |
| - /** |
606 |
| - * Adds the move command to the current path element, |
607 |
| - * if the currentPathElement is not empty create a new path element |
608 |
| - */ |
609 |
| - ctx.prototype.moveTo = function (x, y) { |
610 |
| - // creates a new subpath with the given point |
611 |
| - setCurrentpath.call(this, x, y, `M ${x} ${y}`); |
612 |
| - }; |
613 |
| - |
614 | 603 | /**
|
615 | 604 | * Closes the current path
|
616 | 605 | */
|
|
620 | 609 | }
|
621 | 610 | };
|
622 | 611 |
|
| 612 | + /** |
| 613 | + * Adds the move command to the current path element, |
| 614 | + * if the currentPathElement is not empty create a new path element |
| 615 | + */ |
| 616 | + ctx.prototype.moveTo = function (x, y) { |
| 617 | + var point = point2d(this.__currentMatrix, x, y); |
| 618 | + // creates a new subpath with the given point |
| 619 | + setCurrentPath.call(this, point.x, point.y, `M ${point.x} ${point.y}`); |
| 620 | + }; |
| 621 | + |
623 | 622 | /**
|
624 | 623 | * Adds a line to command
|
625 | 624 | */
|
626 | 625 | ctx.prototype.lineTo = function (x, y) {
|
627 |
| - setCurrentpath.call(this, x, y, `L ${x} ${y}`); |
| 626 | + var point = point2d(this.__currentMatrix, x, y); |
| 627 | + setCurrentPath.call(this, point.x, point.y, `L ${point.x} ${point.y}`); |
628 | 628 | };
|
629 | 629 |
|
630 | 630 | /**
|
631 | 631 | * Add a bezier command
|
632 | 632 | */
|
633 | 633 | ctx.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
|
634 |
| - setCurrentpath.call(this, x, y, `C ${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x} ${y}`); |
| 634 | + var point = point2d(this.__currentMatrix, x, y); |
| 635 | + var cp1 = point2d(this.__currentMatrix, cp1x, cp1y); |
| 636 | + var cp2 = point2d(this.__currentMatrix, cp2x, cp2y); |
| 637 | + setCurrentPath.call(this, point.x, point.y, `C ${cp1.x} ${cp1.y} ${cp2.x} ${cp2.y} ${point.x} ${point.y}`); |
635 | 638 | };
|
636 | 639 |
|
637 | 640 | /**
|
638 | 641 | * Adds a quadratic curve to command
|
639 | 642 | */
|
640 | 643 | ctx.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
|
641 |
| - setCurrentpath.call(this, x, y, `Q ${cpx} ${cpy} ${x} ${y}`); |
| 644 | + var point = point2d(this.__currentMatrix, x, y); |
| 645 | + var cp = point2d(this.__currentMatrix, cpx, cpy); |
| 646 | + setCurrentPath.call(this, point.x, point.y, `Q ${cp.x} ${cp.y} ${point.x} ${point.y}`); |
642 | 647 | };
|
643 | 648 |
|
644 |
| - function setCurrentpath(x, y, value) { |
| 649 | + function setCurrentPath(x, y, value) { |
645 | 650 | this.__currentPosition = {x, y};
|
646 | 651 | this.__currentPath || (this.__currentPath = "");
|
647 | 652 | this.__currentPath += value;
|
|
770 | 775 | function getOrCreateElementToApplyStyleTo(paintMethod1, paintMethod2) {
|
771 | 776 | var currentPath = this.__currentPath;
|
772 | 777 | if (!currentPath) {
|
773 |
| - return |
| 778 | + return; |
774 | 779 | }
|
775 | 780 |
|
776 | 781 | var element = this.__currentElement;
|
777 | 782 | var group = this.__closestGroupOrSvg();
|
778 | 783 | var matrixString = this.__currentMatrix.toString();
|
779 |
| - var state = group.__state || (group.__state = {}) |
| 784 | + var state = group.__state || (group.__state = {}); |
780 | 785 | if (state[paintMethod1] || state[paintMethod2] && state.matrixString !== matrixString) {
|
781 | 786 | var pathHasNoChange = currentPath === state.currentPath;
|
782 | 787 | if (pathHasNoChange) {
|
|
979 | 984 | * Returns a canvas gradient object that has a reference to it's parent def
|
980 | 985 | */
|
981 | 986 | ctx.prototype.createLinearGradient = function (x1, y1, x2, y2) {
|
| 987 | + var point1 = point2d(this.__currentMatrix, x1, y1); |
| 988 | + var point2 = point2d(this.__currentMatrix, x2, y2); |
982 | 989 | var grad = this.__createElement("linearGradient", {
|
983 | 990 | id : randomString(this.__ids),
|
984 |
| - x1 : x1+"px", |
985 |
| - x2 : x2+"px", |
986 |
| - y1 : y1+"px", |
987 |
| - y2 : y2+"px", |
| 991 | + x1 : point1.x+"px", |
| 992 | + x2 : point2.x+"px", |
| 993 | + y1 : point1.y+"px", |
| 994 | + y2 : point2.y+"px", |
988 | 995 | gradientUnits : "userSpaceOnUse"
|
989 | 996 | });
|
990 | 997 | this.__defs.appendChild(grad);
|
|
996 | 1003 | * Returns a canvas gradient object that has a reference to it's parent def
|
997 | 1004 | */
|
998 | 1005 | ctx.prototype.createRadialGradient = function (x0, y0, r0, x1, y1, r1) {
|
| 1006 | + var scale = getCurrentScale.call(this) |
| 1007 | + var point0 = point2d(this.__currentMatrix, x0, y0); |
| 1008 | + var point1 = point2d(this.__currentMatrix, x1, y1); |
999 | 1009 | var grad = this.__createElement("radialGradient", {
|
1000 | 1010 | id : randomString(this.__ids),
|
1001 |
| - cx : x1+"px", |
1002 |
| - cy : y1+"px", |
1003 |
| - r : r1+"px", |
1004 |
| - fx : x0+"px", |
1005 |
| - fy : y0+"px", |
| 1011 | + cx : point1.x+"px", |
| 1012 | + cy : point1.y+"px", |
| 1013 | + r : r1*scale+"px", |
| 1014 | + fx : point0.x+"px", |
| 1015 | + fy : point0.y+"px", |
1006 | 1016 | gradientUnits : "userSpaceOnUse"
|
1007 | 1017 | });
|
1008 | 1018 | this.__defs.appendChild(grad);
|
1009 | 1019 | return new CanvasGradient(grad, this);
|
1010 | 1020 | };
|
1011 | 1021 |
|
| 1022 | + function getCurrentScale() { |
| 1023 | + // Extracted from: http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp |
| 1024 | + // MPL 1.1 license |
| 1025 | + |
| 1026 | + const matrix = this.__currentMatrix |
| 1027 | + let scaleX = 0 |
| 1028 | + let scaleY = 0 |
| 1029 | + let skewX = 0 |
| 1030 | + let a = matrix.a |
| 1031 | + let b = matrix.b |
| 1032 | + let c = matrix.c |
| 1033 | + let d = matrix.d |
| 1034 | + |
| 1035 | + const determinant = a * d - b * c |
| 1036 | + if (determinant) { |
| 1037 | + /** Compute X scale factor and normalize first row **/ |
| 1038 | + scaleX = Math.sqrt(a * a + b * b) |
| 1039 | + a /= scaleX |
| 1040 | + b /= scaleX |
| 1041 | + |
| 1042 | + /** Compute shear factor and make 2nd row orthogonal to 1st **/ |
| 1043 | + skewX = a * c + b * d |
| 1044 | + c -= a * skewX |
| 1045 | + d -= b * skewX |
| 1046 | + |
| 1047 | + /** Compute Y scale **/ |
| 1048 | + scaleY = Math.sqrt(c * c + d * d) |
| 1049 | + |
| 1050 | + /** Negate **/ |
| 1051 | + if (determinant < 0) { |
| 1052 | + scaleX = -scaleX |
| 1053 | + } |
| 1054 | + } |
| 1055 | + |
| 1056 | + return Math.max(scaleX, scaleY) |
| 1057 | + }; |
| 1058 | + |
1012 | 1059 | /**
|
1013 | 1060 | * Parses the font string and returns svg mapping
|
1014 | 1061 | * @private
|
|
0 commit comments