@leafer-draw/node 1.9.12 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.cjs CHANGED
@@ -687,102 +687,163 @@ core.Platform.render = function(target, canvas, options) {
687
687
  if (options.topList.length) options.topList.forEach(item => item.__render(canvas, topOptions));
688
688
  };
689
689
 
690
- function fillText(ui, canvas) {
691
- const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
692
- if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
693
- let row;
694
- for (let i = 0, len = rows.length; i < len; i++) {
695
- row = rows[i];
696
- if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
697
- canvas.fillText(charData.char, charData.x, row.y);
698
- });
699
- }
700
- if (decorationY) {
701
- const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
702
- if (decorationColor) canvas.fillStyle = decorationColor;
703
- rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
704
- }
705
- }
706
-
707
- function fill(fill, ui, canvas) {
690
+ function fill(fill, ui, canvas, renderOptions) {
708
691
  canvas.fillStyle = fill;
709
- fillPathOrText(ui, canvas);
692
+ fillPathOrText(ui, canvas, renderOptions);
710
693
  }
711
694
 
712
- function fills(fills, ui, canvas) {
713
- let item;
695
+ function fills(fills, ui, canvas, renderOptions) {
696
+ let item, originPaint, countImage;
714
697
  for (let i = 0, len = fills.length; i < len; i++) {
715
- item = fills[i];
698
+ item = fills[i], originPaint = item.originPaint;
716
699
  if (item.image) {
717
- if (draw.PaintImage.checkImage(ui, canvas, item, !ui.__.__font)) continue;
700
+ countImage ? countImage++ : countImage = 1;
701
+ if (draw.PaintImage.checkImage(item, !ui.__.__font, ui, canvas, renderOptions)) continue;
718
702
  if (!item.style) {
719
- if (!i && item.image.isPlacehold) ui.drawImagePlaceholder(canvas, item.image);
703
+ if (countImage === 1 && item.image.isPlacehold) ui.drawImagePlaceholder(item, canvas, renderOptions);
720
704
  continue;
721
705
  }
722
706
  }
723
707
  canvas.fillStyle = item.style;
724
- if (item.transform || item.scaleFixed) {
708
+ if (item.transform || originPaint.scaleFixed) {
725
709
  canvas.save();
726
710
  if (item.transform) canvas.transform(item.transform);
727
- if (item.scaleFixed) {
711
+ if (originPaint.scaleFixed) {
728
712
  const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true);
729
- if (item.scaleFixed === true || item.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
713
+ if (originPaint.scaleFixed === true || originPaint.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
730
714
  }
731
- if (item.blendMode) canvas.blendMode = item.blendMode;
732
- fillPathOrText(ui, canvas);
715
+ if (originPaint.blendMode) canvas.blendMode = originPaint.blendMode;
716
+ fillPathOrText(ui, canvas, renderOptions);
733
717
  canvas.restore();
734
718
  } else {
735
- if (item.blendMode) {
736
- canvas.saveBlendMode(item.blendMode);
737
- fillPathOrText(ui, canvas);
719
+ if (originPaint.blendMode) {
720
+ canvas.saveBlendMode(originPaint.blendMode);
721
+ fillPathOrText(ui, canvas, renderOptions);
738
722
  canvas.restoreBlendMode();
739
- } else fillPathOrText(ui, canvas);
723
+ } else fillPathOrText(ui, canvas, renderOptions);
724
+ }
725
+ }
726
+ }
727
+
728
+ function fillPathOrText(ui, canvas, renderOptions) {
729
+ ui.__.__font ? draw.Paint.fillText(ui, canvas, renderOptions) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
730
+ }
731
+
732
+ function fillText(ui, canvas, _renderOptions) {
733
+ const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
734
+ if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
735
+ let row;
736
+ for (let i = 0, len = rows.length; i < len; i++) {
737
+ row = rows[i];
738
+ if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
739
+ canvas.fillText(charData.char, charData.x, row.y);
740
+ });
741
+ }
742
+ if (decorationY) {
743
+ const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
744
+ if (decorationColor) canvas.fillStyle = decorationColor;
745
+ rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
746
+ }
747
+ }
748
+
749
+ function stroke(stroke, ui, canvas, renderOptions) {
750
+ const data = ui.__;
751
+ if (!data.__strokeWidth) return;
752
+ if (data.__font) {
753
+ draw.Paint.strokeText(stroke, ui, canvas, renderOptions);
754
+ } else {
755
+ switch (data.strokeAlign) {
756
+ case "center":
757
+ drawCenter$1(stroke, 1, ui, canvas, renderOptions);
758
+ break;
759
+
760
+ case "inside":
761
+ drawInside(stroke, ui, canvas, renderOptions);
762
+ break;
763
+
764
+ case "outside":
765
+ drawOutside(stroke, ui, canvas, renderOptions);
766
+ break;
740
767
  }
741
768
  }
742
769
  }
743
770
 
744
- function fillPathOrText(ui, canvas) {
745
- ui.__.__font ? fillText(ui, canvas) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
771
+ function strokes(strokes, ui, canvas, renderOptions) {
772
+ draw.Paint.stroke(strokes, ui, canvas, renderOptions);
773
+ }
774
+
775
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas, renderOptions) {
776
+ const data = ui.__;
777
+ if (core.isObject(stroke)) {
778
+ draw.Paint.drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas, renderOptions);
779
+ } else {
780
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
781
+ canvas.stroke();
782
+ }
783
+ if (data.__useArrow) draw.Paint.strokeArrow(stroke, ui, canvas, renderOptions);
784
+ }
785
+
786
+ function drawInside(stroke, ui, canvas, renderOptions) {
787
+ canvas.save();
788
+ canvas.clipUI(ui);
789
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
790
+ canvas.restore();
791
+ }
792
+
793
+ function drawOutside(stroke, ui, canvas, renderOptions) {
794
+ const data = ui.__;
795
+ if (data.__fillAfterStroke) {
796
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
797
+ } else {
798
+ const {renderBounds: renderBounds} = ui.__layout;
799
+ const out = canvas.getSameCanvas(true, true);
800
+ ui.__drawRenderPath(out);
801
+ drawCenter$1(stroke, 2, ui, out, renderOptions);
802
+ out.clipUI(data);
803
+ out.clearWorld(renderBounds);
804
+ core.LeafHelper.copyCanvasByWorld(ui, canvas, out);
805
+ out.recycle(ui.__nowWorld);
806
+ }
746
807
  }
747
808
 
748
- function strokeText(stroke, ui, canvas) {
809
+ function strokeText(stroke, ui, canvas, renderOptions) {
749
810
  switch (ui.__.strokeAlign) {
750
811
  case "center":
751
- drawCenter$1(stroke, 1, ui, canvas);
812
+ drawCenter(stroke, 1, ui, canvas, renderOptions);
752
813
  break;
753
814
 
754
815
  case "inside":
755
- drawAlign(stroke, "inside", ui, canvas);
816
+ drawAlign(stroke, "inside", ui, canvas, renderOptions);
756
817
  break;
757
818
 
758
819
  case "outside":
759
- ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, "outside", ui, canvas);
820
+ ui.__.__fillAfterStroke ? drawCenter(stroke, 2, ui, canvas, renderOptions) : drawAlign(stroke, "outside", ui, canvas, renderOptions);
760
821
  break;
761
822
  }
762
823
  }
763
824
 
764
- function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
825
+ function drawCenter(stroke, strokeWidthScale, ui, canvas, renderOptions) {
765
826
  const data = ui.__;
766
827
  if (core.isObject(stroke)) {
767
- drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas);
828
+ draw.Paint.drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas, renderOptions);
768
829
  } else {
769
830
  canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
770
- drawTextStroke(ui, canvas);
831
+ draw.Paint.drawTextStroke(ui, canvas, renderOptions);
771
832
  }
772
833
  }
773
834
 
774
- function drawAlign(stroke, align, ui, canvas) {
835
+ function drawAlign(stroke, align, ui, canvas, renderOptions) {
775
836
  const out = canvas.getSameCanvas(true, true);
776
837
  out.font = ui.__.__font;
777
- drawCenter$1(stroke, 2, ui, out);
838
+ drawCenter(stroke, 2, ui, out, renderOptions);
778
839
  out.blendMode = align === "outside" ? "destination-out" : "destination-in";
779
- fillText(ui, out);
840
+ draw.Paint.fillText(ui, out, renderOptions);
780
841
  out.blendMode = "normal";
781
842
  core.LeafHelper.copyCanvasByWorld(ui, canvas, out);
782
843
  out.recycle(ui.__nowWorld);
783
844
  }
784
845
 
785
- function drawTextStroke(ui, canvas) {
846
+ function drawTextStroke(ui, canvas, _renderOptions) {
786
847
  let row, data = ui.__.__textDrawData;
787
848
  const {rows: rows, decorationY: decorationY} = data;
788
849
  for (let i = 0, len = rows.length; i < len; i++) {
@@ -797,89 +858,29 @@ function drawTextStroke(ui, canvas) {
797
858
  }
798
859
  }
799
860
 
800
- function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
861
+ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas, renderOptions) {
801
862
  let item;
802
863
  const data = ui.__, {__hasMultiStrokeStyle: __hasMultiStrokeStyle} = data;
803
864
  __hasMultiStrokeStyle || canvas.setStroke(undefined, data.__strokeWidth * strokeWidthScale, data);
804
865
  for (let i = 0, len = strokes.length; i < len; i++) {
805
866
  item = strokes[i];
806
- if (item.image && draw.PaintImage.checkImage(ui, canvas, item, false)) continue;
867
+ if (item.image && draw.PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
807
868
  if (item.style) {
808
869
  if (__hasMultiStrokeStyle) {
809
870
  const {strokeStyle: strokeStyle} = item;
810
871
  strokeStyle ? canvas.setStroke(item.style, data.__getRealStrokeWidth(strokeStyle) * strokeWidthScale, data, strokeStyle) : canvas.setStroke(item.style, data.__strokeWidth * strokeWidthScale, data);
811
872
  } else canvas.strokeStyle = item.style;
812
- if (item.blendMode) {
813
- canvas.saveBlendMode(item.blendMode);
814
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
873
+ if (item.originPaint.blendMode) {
874
+ canvas.saveBlendMode(item.originPaint.blendMode);
875
+ isText ? draw.Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
815
876
  canvas.restoreBlendMode();
816
877
  } else {
817
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
878
+ isText ? draw.Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
818
879
  }
819
880
  }
820
881
  }
821
882
  }
822
883
 
823
- function stroke(stroke, ui, canvas) {
824
- const data = ui.__;
825
- if (!data.__strokeWidth) return;
826
- if (data.__font) {
827
- strokeText(stroke, ui, canvas);
828
- } else {
829
- switch (data.strokeAlign) {
830
- case "center":
831
- drawCenter(stroke, 1, ui, canvas);
832
- break;
833
-
834
- case "inside":
835
- drawInside(stroke, ui, canvas);
836
- break;
837
-
838
- case "outside":
839
- drawOutside(stroke, ui, canvas);
840
- break;
841
- }
842
- }
843
- }
844
-
845
- function strokes(strokes, ui, canvas) {
846
- stroke(strokes, ui, canvas);
847
- }
848
-
849
- function drawCenter(stroke, strokeWidthScale, ui, canvas) {
850
- const data = ui.__;
851
- if (core.isObject(stroke)) {
852
- drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas);
853
- } else {
854
- canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
855
- canvas.stroke();
856
- }
857
- if (data.__useArrow) draw.Paint.strokeArrow(stroke, ui, canvas);
858
- }
859
-
860
- function drawInside(stroke, ui, canvas) {
861
- canvas.save();
862
- canvas.clipUI(ui);
863
- drawCenter(stroke, 2, ui, canvas);
864
- canvas.restore();
865
- }
866
-
867
- function drawOutside(stroke, ui, canvas) {
868
- const data = ui.__;
869
- if (data.__fillAfterStroke) {
870
- drawCenter(stroke, 2, ui, canvas);
871
- } else {
872
- const {renderBounds: renderBounds} = ui.__layout;
873
- const out = canvas.getSameCanvas(true, true);
874
- ui.__drawRenderPath(out);
875
- drawCenter(stroke, 2, ui, out);
876
- out.clipUI(data);
877
- out.clearWorld(renderBounds);
878
- core.LeafHelper.copyCanvasByWorld(ui, canvas, out);
879
- out.recycle(ui.__nowWorld);
880
- }
881
- }
882
-
883
884
  const {getSpread: getSpread, copyAndSpread: copyAndSpread, toOuterOf: toOuterOf, getOuterOf: getOuterOf, getByMove: getByMove, move: move$1, getIntersectData: getIntersectData} = core.BoundsHelper;
884
885
 
885
886
  const tempBounds$1 = {};
@@ -967,62 +968,63 @@ function compute(attrName, ui) {
967
968
  if (leafPaints.some(item => item.image)) isAlphaPixel = true;
968
969
  isTransparent = true;
969
970
  }
970
- }
971
- if (attrName === "fill") {
972
- stintSet(data, "__isAlphaPixelFill", isAlphaPixel);
973
- stintSet(data, "__isTransparentFill", isTransparent);
971
+ if (attrName === "fill") {
972
+ stintSet(data, "__isAlphaPixelFill", isAlphaPixel);
973
+ stintSet(data, "__isTransparentFill", isTransparent);
974
+ } else {
975
+ stintSet(data, "__isAlphaPixelStroke", isAlphaPixel);
976
+ stintSet(data, "__isTransparentStroke", isTransparent);
977
+ stintSet(data, "__hasMultiStrokeStyle", maxChildStrokeWidth);
978
+ }
974
979
  } else {
975
- stintSet(data, "__isAlphaPixelStroke", isAlphaPixel);
976
- stintSet(data, "__isTransparentStroke", isTransparent);
977
- stintSet(data, "__hasMultiStrokeStyle", maxChildStrokeWidth);
980
+ data.__removePaint(attrName, false);
978
981
  }
979
982
  }
980
983
 
981
984
  function getLeafPaint(attrName, paint, ui) {
982
985
  if (!core.isObject(paint) || paint.visible === false || paint.opacity === 0) return undefined;
983
- let data;
986
+ let leafPaint;
984
987
  const {boxBounds: boxBounds} = ui.__layout;
985
988
  switch (paint.type) {
986
989
  case "image":
987
- data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
990
+ leafPaint = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
988
991
  break;
989
992
 
990
993
  case "linear":
991
- data = draw.PaintGradient.linearGradient(paint, boxBounds);
994
+ leafPaint = draw.PaintGradient.linearGradient(paint, boxBounds);
992
995
  break;
993
996
 
994
997
  case "radial":
995
- data = draw.PaintGradient.radialGradient(paint, boxBounds);
998
+ leafPaint = draw.PaintGradient.radialGradient(paint, boxBounds);
996
999
  break;
997
1000
 
998
1001
  case "angular":
999
- data = draw.PaintGradient.conicGradient(paint, boxBounds);
1002
+ leafPaint = draw.PaintGradient.conicGradient(paint, boxBounds);
1000
1003
  break;
1001
1004
 
1002
1005
  case "solid":
1003
1006
  const {type: type, color: color, opacity: opacity} = paint;
1004
- data = {
1007
+ leafPaint = {
1005
1008
  type: type,
1006
1009
  style: draw.ColorConvert.string(color, opacity)
1007
1010
  };
1008
1011
  break;
1009
1012
 
1010
1013
  default:
1011
- if (!core.isUndefined(paint.r)) data = {
1014
+ if (!core.isUndefined(paint.r)) leafPaint = {
1012
1015
  type: "solid",
1013
1016
  style: draw.ColorConvert.string(paint)
1014
1017
  };
1015
1018
  }
1016
- if (data) {
1017
- if (core.isString(data.style) && hasTransparent$1(data.style)) data.isTransparent = true;
1019
+ if (leafPaint) {
1020
+ leafPaint.originPaint = paint;
1021
+ if (core.isString(leafPaint.style) && hasTransparent$1(leafPaint.style)) leafPaint.isTransparent = true;
1018
1022
  if (paint.style) {
1019
1023
  if (paint.style.strokeWidth === 0) return undefined;
1020
- data.strokeStyle = paint.style;
1024
+ leafPaint.strokeStyle = paint.style;
1021
1025
  }
1022
- if (paint.editing) data.editing = paint.editing;
1023
- if (paint.blendMode) data.blendMode = paint.blendMode;
1024
1026
  }
1025
- return data;
1027
+ return leafPaint;
1026
1028
  }
1027
1029
 
1028
1030
  const PaintModule = {
@@ -1035,88 +1037,118 @@ const PaintModule = {
1035
1037
  strokes: strokes,
1036
1038
  strokeText: strokeText,
1037
1039
  drawTextStroke: drawTextStroke,
1040
+ drawStrokesStyle: drawStrokesStyle,
1038
1041
  shape: shape
1039
1042
  };
1040
1043
 
1041
- let origin = {}, tempMatrix$1 = core.getMatrixData();
1044
+ let cache, box = new core.Bounds;
1042
1045
 
1043
- const {get: get$3, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = core.MatrixHelper;
1046
+ const {isSame: isSame} = core.BoundsHelper;
1044
1047
 
1045
- function stretchMode(data, box, scaleX, scaleY) {
1046
- const transform = get$3();
1047
- translate$1(transform, box.x, box.y);
1048
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1049
- data.transform = transform;
1048
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1049
+ let leafPaint, event;
1050
+ const image = core.ImageManager.get(paint);
1051
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1052
+ leafPaint = cache.leafPaint;
1053
+ } else {
1054
+ leafPaint = {
1055
+ type: paint.type,
1056
+ image: image
1057
+ };
1058
+ if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1059
+ cache = image.use > 1 ? {
1060
+ leafPaint: leafPaint,
1061
+ paint: paint,
1062
+ boxBounds: box.set(boxBounds)
1063
+ } : null;
1064
+ }
1065
+ if (firstUse || image.loading) event = {
1066
+ image: image,
1067
+ attrName: attrName,
1068
+ attrValue: paint
1069
+ };
1070
+ if (image.ready) {
1071
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1072
+ if (firstUse) {
1073
+ onLoad(ui, event);
1074
+ onLoadSuccess(ui, event);
1075
+ }
1076
+ } else if (image.error) {
1077
+ if (firstUse) onLoadError(ui, event, image.error);
1078
+ } else {
1079
+ if (firstUse) {
1080
+ ignoreRender(ui, true);
1081
+ onLoad(ui, event);
1082
+ }
1083
+ leafPaint.loadId = image.load(() => {
1084
+ ignoreRender(ui, false);
1085
+ if (!ui.destroyed) {
1086
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1087
+ if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1088
+ ui.forceUpdate("surface");
1089
+ }
1090
+ onLoadSuccess(ui, event);
1091
+ }
1092
+ leafPaint.loadId = undefined;
1093
+ }, error => {
1094
+ ignoreRender(ui, false);
1095
+ onLoadError(ui, event, error);
1096
+ leafPaint.loadId = undefined;
1097
+ });
1098
+ if (ui.placeholderColor) {
1099
+ if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1100
+ if (!image.ready) {
1101
+ image.isPlacehold = true;
1102
+ ui.forceUpdate("surface");
1103
+ }
1104
+ }, ui.placeholderDelay);
1105
+ }
1106
+ }
1107
+ return leafPaint;
1050
1108
  }
1051
1109
 
1052
- function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1053
- const transform = get$3();
1054
- translate$1(transform, box.x + x, box.y + y);
1055
- scaleHelper(transform, scaleX, scaleY);
1056
- if (rotation) rotateOfOuter$1(transform, {
1057
- x: box.x + box.width / 2,
1058
- y: box.y + box.height / 2
1059
- }, rotation);
1060
- data.transform = transform;
1110
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1111
+ if (attrName === "fill" && !ui.__.__naturalWidth) {
1112
+ const data = ui.__;
1113
+ data.__naturalWidth = image.width / data.pixelRatio;
1114
+ data.__naturalHeight = image.height / data.pixelRatio;
1115
+ if (data.__autoSide) {
1116
+ ui.forceUpdate("width");
1117
+ if (ui.__proxyData) {
1118
+ ui.setProxyAttr("width", data.width);
1119
+ ui.setProxyAttr("height", data.height);
1120
+ }
1121
+ return false;
1122
+ }
1123
+ }
1124
+ if (!leafPaint.data) draw.PaintImage.createData(leafPaint, image, paint, boxBounds);
1125
+ return true;
1061
1126
  }
1062
1127
 
1063
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1064
- const transform = get$3();
1065
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1066
- if (clipScaleX) {
1067
- if (rotation || skew) {
1068
- set(tempMatrix$1);
1069
- scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1070
- multiplyParent(transform, tempMatrix$1);
1071
- } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1072
- }
1073
- data.transform = transform;
1128
+ function onLoad(ui, event) {
1129
+ emit(ui, core.ImageEvent.LOAD, event);
1074
1130
  }
1075
1131
 
1076
- function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1077
- const transform = get$3();
1078
- if (freeTransform) {
1079
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1080
- } else {
1081
- if (rotation) {
1082
- if (align === "center") {
1083
- rotateOfOuter$1(transform, {
1084
- x: width / 2,
1085
- y: height / 2
1086
- }, rotation);
1087
- } else {
1088
- rotate(transform, rotation);
1089
- switch (rotation) {
1090
- case 90:
1091
- translate$1(transform, height, 0);
1092
- break;
1132
+ function onLoadSuccess(ui, event) {
1133
+ emit(ui, core.ImageEvent.LOADED, event);
1134
+ }
1093
1135
 
1094
- case 180:
1095
- translate$1(transform, width, height);
1096
- break;
1136
+ function onLoadError(ui, event, error) {
1137
+ event.error = error;
1138
+ ui.forceUpdate("surface");
1139
+ emit(ui, core.ImageEvent.ERROR, event);
1140
+ }
1097
1141
 
1098
- case 270:
1099
- translate$1(transform, 0, width);
1100
- break;
1101
- }
1102
- }
1103
- }
1104
- origin.x = box.x + x;
1105
- origin.y = box.y + y;
1106
- translate$1(transform, origin.x, origin.y);
1107
- if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1108
- }
1109
- data.transform = transform;
1142
+ function emit(ui, type, data) {
1143
+ if (ui.hasEvent(type)) ui.emitEvent(new core.ImageEvent(type, data));
1110
1144
  }
1111
1145
 
1112
- function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1113
- if (rotation) rotate(transform, rotation);
1114
- if (skew) skewHelper(transform, skew.x, skew.y);
1115
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1116
- translate$1(transform, box.x + x, box.y + y);
1146
+ function ignoreRender(ui, value) {
1147
+ const {leafer: leafer} = ui;
1148
+ if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1117
1149
  }
1118
1150
 
1119
- const {get: get$2, translate: translate} = core.MatrixHelper;
1151
+ const {get: get$3, translate: translate$1} = core.MatrixHelper;
1120
1152
 
1121
1153
  const tempBox = new core.Bounds;
1122
1154
 
@@ -1125,17 +1157,13 @@ const tempScaleData = {};
1125
1157
  const tempImage = {};
1126
1158
 
1127
1159
  function createData(leafPaint, image, paint, box) {
1128
- const {changeful: changeful, sync: sync, scaleFixed: scaleFixed} = paint;
1129
- if (changeful) leafPaint.changeful = changeful;
1130
- if (sync) leafPaint.sync = sync;
1131
- if (scaleFixed) leafPaint.scaleFixed = scaleFixed;
1132
- leafPaint.data = getPatternData(paint, box, image);
1160
+ leafPaint.data = draw.PaintImage.getPatternData(paint, box, image);
1133
1161
  }
1134
1162
 
1135
1163
  function getPatternData(paint, box, image) {
1136
1164
  if (paint.padding) box = tempBox.set(box).shrink(paint.padding);
1137
1165
  if (paint.mode === "strench") paint.mode = "stretch";
1138
- let {width: width, height: height} = image;
1166
+ const {width: width, height: height} = image;
1139
1167
  const {opacity: opacity, mode: mode, align: align, offset: offset, scale: scale, size: size, rotation: rotation, skew: skew, clipSize: clipSize, repeat: repeat, gap: gap, filters: filters} = paint;
1140
1168
  const sameBox = box.width === width && box.height === height;
1141
1169
  const data = {
@@ -1166,8 +1194,8 @@ function getPatternData(paint, box, image) {
1166
1194
  case "stretch":
1167
1195
  if (!sameBox) {
1168
1196
  scaleX = box.width / width, scaleY = box.height / height;
1169
- stretchMode(data, box, scaleX, scaleY);
1170
- }
1197
+ draw.PaintImage.stretchMode(data, box, scaleX, scaleY);
1198
+ } else if (scaleX) scaleX = scaleY = undefined;
1171
1199
  break;
1172
1200
 
1173
1201
  case "normal":
@@ -1175,13 +1203,13 @@ function getPatternData(paint, box, image) {
1175
1203
  if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) {
1176
1204
  let clipScaleX, clipScaleY;
1177
1205
  if (clipSize) clipScaleX = box.width / clipSize.width, clipScaleY = box.height / clipSize.height;
1178
- clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1206
+ draw.PaintImage.clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1179
1207
  if (clipScaleX) scaleX = scaleX ? scaleX * clipScaleX : clipScaleX, scaleY = scaleY ? scaleY * clipScaleY : clipScaleY;
1180
1208
  }
1181
1209
  break;
1182
1210
 
1183
1211
  case "repeat":
1184
- if (!sameBox || scaleX || rotation || skew) repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1212
+ if (!sameBox || scaleX || rotation || skew) draw.PaintImage.repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1185
1213
  if (!repeat) data.repeat = "repeat";
1186
1214
  const count = core.isObject(repeat);
1187
1215
  if (gap || count) data.gap = getGapData(gap, count && repeat, tempImage.width, tempImage.height, box);
@@ -1190,18 +1218,16 @@ function getPatternData(paint, box, image) {
1190
1218
  case "fit":
1191
1219
  case "cover":
1192
1220
  default:
1193
- if (scaleX) fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1221
+ if (scaleX) draw.PaintImage.fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1194
1222
  }
1195
1223
  if (!data.transform) {
1196
- if (box.x || box.y) translate(data.transform = get$2(), box.x, box.y);
1224
+ if (box.x || box.y) translate$1(data.transform = get$3(), box.x, box.y);
1197
1225
  }
1198
- data.width = width;
1199
- data.height = height;
1200
1226
  if (scaleX) {
1201
1227
  data.scaleX = scaleX;
1202
1228
  data.scaleY = scaleY;
1203
1229
  }
1204
- if (opacity) data.opacity = opacity;
1230
+ if (opacity && opacity < 1) data.opacity = opacity;
1205
1231
  if (filters) data.filters = filters;
1206
1232
  if (repeat) data.repeat = core.isString(repeat) ? repeat === "x" ? "repeat-x" : "repeat-y" : "repeat";
1207
1233
  return data;
@@ -1223,234 +1249,194 @@ function getGapValue(gap, size, totalSize, rows) {
1223
1249
  return gap === "auto" ? value < 0 ? 0 : value : value;
1224
1250
  }
1225
1251
 
1226
- let cache, box = new core.Bounds;
1252
+ let origin = {}, tempMatrix$1 = core.getMatrixData();
1227
1253
 
1228
- const {isSame: isSame} = core.BoundsHelper;
1254
+ const {get: get$2, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = core.MatrixHelper;
1229
1255
 
1230
- function image(ui, attrName, paint, boxBounds, firstUse) {
1231
- let leafPaint, event;
1232
- const image = core.ImageManager.get(paint);
1233
- if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1234
- leafPaint = cache.leafPaint;
1235
- } else {
1236
- leafPaint = {
1237
- type: paint.type,
1238
- image: image
1239
- };
1240
- if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1241
- cache = image.use > 1 ? {
1242
- leafPaint: leafPaint,
1243
- paint: paint,
1244
- boxBounds: box.set(boxBounds)
1245
- } : null;
1246
- }
1247
- if (firstUse || image.loading) event = {
1248
- image: image,
1249
- attrName: attrName,
1250
- attrValue: paint
1251
- };
1252
- if (image.ready) {
1253
- checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1254
- if (firstUse) {
1255
- onLoad(ui, event);
1256
- onLoadSuccess(ui, event);
1257
- }
1258
- } else if (image.error) {
1259
- if (firstUse) onLoadError(ui, event, image.error);
1260
- } else {
1261
- if (firstUse) {
1262
- ignoreRender(ui, true);
1263
- onLoad(ui, event);
1264
- }
1265
- leafPaint.loadId = image.load(() => {
1266
- ignoreRender(ui, false);
1267
- if (!ui.destroyed) {
1268
- if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1269
- if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1270
- ui.forceUpdate("surface");
1271
- }
1272
- onLoadSuccess(ui, event);
1273
- }
1274
- leafPaint.loadId = undefined;
1275
- }, error => {
1276
- ignoreRender(ui, false);
1277
- onLoadError(ui, event, error);
1278
- leafPaint.loadId = undefined;
1279
- });
1280
- if (ui.placeholderColor) {
1281
- if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1282
- if (!image.ready) {
1283
- image.isPlacehold = true;
1284
- ui.forceUpdate("surface");
1285
- }
1286
- }, ui.placeholderDelay);
1287
- }
1288
- }
1289
- return leafPaint;
1256
+ function stretchMode(data, box, scaleX, scaleY) {
1257
+ const transform = get$2(), {x: x, y: y} = box;
1258
+ if (x || y) translate(transform, x, y); else transform.onlyScale = true;
1259
+ scaleHelper(transform, scaleX, scaleY);
1260
+ data.transform = transform;
1290
1261
  }
1291
1262
 
1292
- function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1293
- if (attrName === "fill" && !ui.__.__naturalWidth) {
1294
- const data = ui.__;
1295
- data.__naturalWidth = image.width / data.pixelRatio;
1296
- data.__naturalHeight = image.height / data.pixelRatio;
1297
- if (data.__autoSide) {
1298
- ui.forceUpdate("width");
1299
- if (ui.__proxyData) {
1300
- ui.setProxyAttr("width", data.width);
1301
- ui.setProxyAttr("height", data.height);
1302
- }
1303
- return false;
1304
- }
1305
- }
1306
- if (!leafPaint.data) createData(leafPaint, image, paint, boxBounds);
1307
- return true;
1263
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1264
+ const transform = get$2();
1265
+ translate(transform, box.x + x, box.y + y);
1266
+ scaleHelper(transform, scaleX, scaleY);
1267
+ if (rotation) rotateOfOuter$1(transform, {
1268
+ x: box.x + box.width / 2,
1269
+ y: box.y + box.height / 2
1270
+ }, rotation);
1271
+ data.transform = transform;
1308
1272
  }
1309
1273
 
1310
- function onLoad(ui, event) {
1311
- emit(ui, core.ImageEvent.LOAD, event);
1274
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1275
+ const transform = get$2();
1276
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1277
+ if (clipScaleX) {
1278
+ if (rotation || skew) {
1279
+ set(tempMatrix$1);
1280
+ scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1281
+ multiplyParent(transform, tempMatrix$1);
1282
+ } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1283
+ }
1284
+ data.transform = transform;
1312
1285
  }
1313
1286
 
1314
- function onLoadSuccess(ui, event) {
1315
- emit(ui, core.ImageEvent.LOADED, event);
1316
- }
1287
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1288
+ const transform = get$2();
1289
+ if (freeTransform) {
1290
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1291
+ } else {
1292
+ if (rotation) {
1293
+ if (align === "center") {
1294
+ rotateOfOuter$1(transform, {
1295
+ x: width / 2,
1296
+ y: height / 2
1297
+ }, rotation);
1298
+ } else {
1299
+ rotate(transform, rotation);
1300
+ switch (rotation) {
1301
+ case 90:
1302
+ translate(transform, height, 0);
1303
+ break;
1317
1304
 
1318
- function onLoadError(ui, event, error) {
1319
- event.error = error;
1320
- ui.forceUpdate("surface");
1321
- emit(ui, core.ImageEvent.ERROR, event);
1322
- }
1305
+ case 180:
1306
+ translate(transform, width, height);
1307
+ break;
1323
1308
 
1324
- function emit(ui, type, data) {
1325
- if (ui.hasEvent(type)) ui.emitEvent(new core.ImageEvent(type, data));
1309
+ case 270:
1310
+ translate(transform, 0, width);
1311
+ break;
1312
+ }
1313
+ }
1314
+ }
1315
+ origin.x = box.x + x;
1316
+ origin.y = box.y + y;
1317
+ translate(transform, origin.x, origin.y);
1318
+ if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1319
+ }
1320
+ data.transform = transform;
1326
1321
  }
1327
1322
 
1328
- function ignoreRender(ui, value) {
1329
- const {leafer: leafer} = ui;
1330
- if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1323
+ function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1324
+ if (rotation) rotate(transform, rotation);
1325
+ if (skew) skewHelper(transform, skew.x, skew.y);
1326
+ if (scaleX) scaleHelper(transform, scaleX, scaleY);
1327
+ translate(transform, box.x + x, box.y + y);
1331
1328
  }
1332
1329
 
1333
1330
  const {get: get$1, scale: scale, copy: copy$1} = core.MatrixHelper;
1334
1331
 
1335
- const {floor: floor, ceil: ceil, max: max$1, abs: abs$1} = Math;
1332
+ const {getFloorScale: getFloorScale} = core.MathHelper, {abs: abs$1} = Math;
1336
1333
 
1337
- function createPattern(ui, paint, pixelRatio) {
1338
- let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1339
- const id = scaleX + "-" + scaleY + "-" + pixelRatio;
1334
+ function createPatternTask(paint, ui, canvas, renderOptions) {
1335
+ if (!paint.patternTask) {
1336
+ paint.patternTask = core.ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1337
+ paint.patternTask = null;
1338
+ if (canvas.bounds.hit(ui.__nowWorld)) draw.PaintImage.createPattern(paint, ui, canvas, renderOptions);
1339
+ ui.forceUpdate("surface");
1340
+ }), 300);
1341
+ }
1342
+ }
1343
+
1344
+ function createPattern(paint, ui, canvas, renderOptions) {
1345
+ let {scaleX: scaleX, scaleY: scaleY} = draw.PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions), id = scaleX + "-" + scaleY;
1340
1346
  if (paint.patternId !== id && !ui.destroyed) {
1341
- const {image: image, data: data} = paint;
1342
- let imageScale, imageMatrix, {width: width, height: height, scaleX: sx, scaleY: sy, transform: transform, repeat: repeat, gap: gap} = data;
1343
- scaleX *= pixelRatio;
1344
- scaleY *= pixelRatio;
1345
- if (sx) {
1346
- sx = abs$1(sx);
1347
- sy = abs$1(sy);
1348
- imageMatrix = get$1();
1349
- copy$1(imageMatrix, transform);
1350
- scale(imageMatrix, 1 / sx, 1 / sy);
1351
- scaleX *= sx;
1352
- scaleY *= sy;
1353
- }
1354
- width *= scaleX;
1355
- height *= scaleY;
1356
- const size = width * height;
1357
- if (!repeat) {
1358
- if (size > core.Platform.image.maxCacheSize) return false;
1359
- }
1360
- let maxSize = core.Platform.image.maxPatternSize;
1361
- if (image.isSVG) {
1362
- const ws = width / image.width;
1363
- if (ws > 1) imageScale = ws / ceil(ws);
1364
- } else {
1365
- const imageSize = image.width * image.height;
1366
- if (maxSize > imageSize) maxSize = imageSize;
1367
- }
1368
- if (size > maxSize) imageScale = Math.sqrt(size / maxSize);
1369
- if (imageScale) {
1370
- scaleX /= imageScale;
1371
- scaleY /= imageScale;
1372
- width /= imageScale;
1373
- height /= imageScale;
1374
- }
1375
- if (sx) {
1376
- scaleX /= sx;
1377
- scaleY /= sy;
1378
- }
1379
- const xGap = gap && gap.x * scaleX;
1380
- const yGap = gap && gap.y * scaleY;
1381
- if (transform || scaleX !== 1 || scaleY !== 1) {
1382
- const canvasWidth = width + (xGap || 0);
1383
- const canvasHeight = height + (yGap || 0);
1384
- scaleX /= canvasWidth / max$1(floor(canvasWidth), 1);
1385
- scaleY /= canvasHeight / max$1(floor(canvasHeight), 1);
1386
- if (!imageMatrix) {
1347
+ if (!(core.Platform.image.isLarge(paint.image, scaleX, scaleY) && !paint.data.repeat)) {
1348
+ const {image: image, data: data} = paint, {transform: transform, gap: gap} = data, fixScale = draw.PaintImage.getPatternFixScale(paint, scaleX, scaleY);
1349
+ let imageMatrix, xGap, yGap, {width: width, height: height} = image;
1350
+ if (fixScale) scaleX *= fixScale, scaleY *= fixScale;
1351
+ width *= scaleX;
1352
+ height *= scaleY;
1353
+ if (gap) {
1354
+ xGap = gap.x * scaleX / abs$1(data.scaleX || 1);
1355
+ yGap = gap.y * scaleY / abs$1(data.scaleY || 1);
1356
+ }
1357
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1358
+ scaleX *= getFloorScale(width + (xGap || 0));
1359
+ scaleY *= getFloorScale(height + (yGap || 0));
1387
1360
  imageMatrix = get$1();
1388
1361
  if (transform) copy$1(imageMatrix, transform);
1362
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1389
1363
  }
1390
- scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1364
+ const imageCanvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1365
+ const pattern = image.getPattern(imageCanvas, data.repeat || (core.Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1366
+ paint.style = pattern;
1367
+ paint.patternId = id;
1391
1368
  }
1392
- const canvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1393
- const pattern = image.getPattern(canvas, repeat || (core.Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1394
- paint.style = pattern;
1395
- paint.patternId = id;
1396
- return true;
1369
+ }
1370
+ }
1371
+
1372
+ function getPatternFixScale(paint, imageScaleX, imageScaleY) {
1373
+ const {image: image} = paint;
1374
+ let fixScale, maxSize = core.Platform.image.maxPatternSize, imageSize = image.width * image.height;
1375
+ if (image.isSVG) {
1376
+ if (imageScaleX > 1) fixScale = Math.ceil(imageScaleX) / imageScaleX;
1397
1377
  } else {
1398
- return false;
1378
+ if (maxSize > imageSize) maxSize = imageSize;
1399
1379
  }
1380
+ if ((imageSize *= imageScaleX * imageScaleY) > maxSize) fixScale = Math.sqrt(maxSize / imageSize);
1381
+ return fixScale;
1400
1382
  }
1401
1383
 
1402
- function checkImage(ui, canvas, paint, allowDraw) {
1403
- const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1404
- const {pixelRatio: pixelRatio} = canvas, {data: data} = paint;
1405
- if (!data || paint.patternId === scaleX + "-" + scaleY + "-" + pixelRatio && !draw.Export.running) {
1384
+ function checkImage(paint, drawImage, ui, canvas, renderOptions) {
1385
+ const {scaleX: scaleX, scaleY: scaleY} = draw.PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions);
1386
+ const {image: image, data: data, originPaint: originPaint} = paint, {exporting: exporting} = renderOptions;
1387
+ if (!data || paint.patternId === scaleX + "-" + scaleY && !exporting) {
1406
1388
  return false;
1407
1389
  } else {
1408
- if (allowDraw) {
1390
+ if (drawImage) {
1409
1391
  if (data.repeat) {
1410
- allowDraw = false;
1411
- } else if (!(paint.changeful || core.Platform.name === "miniapp" && core.ResizeEvent.isResizing(ui) || draw.Export.running)) {
1412
- let {width: width, height: height} = data;
1413
- width *= scaleX * pixelRatio;
1414
- height *= scaleY * pixelRatio;
1415
- if (data.scaleX) {
1416
- width *= data.scaleX;
1417
- height *= data.scaleY;
1418
- }
1419
- allowDraw = width * height > core.Platform.image.maxCacheSize;
1392
+ drawImage = false;
1393
+ } else if (!(originPaint.changeful || core.Platform.name === "miniapp" && core.ResizeEvent.isResizing(ui) || exporting)) {
1394
+ drawImage = core.Platform.image.isLarge(image, scaleX, scaleY);
1420
1395
  }
1421
1396
  }
1422
- if (allowDraw) {
1397
+ if (drawImage) {
1423
1398
  if (ui.__.__isFastShadow) {
1424
1399
  canvas.fillStyle = paint.style || "#000";
1425
1400
  canvas.fill();
1426
1401
  }
1427
- drawImage(ui, canvas, paint, data);
1402
+ draw.PaintImage.drawImage(paint, scaleX, scaleY, ui, canvas, renderOptions);
1428
1403
  return true;
1429
1404
  } else {
1430
- if (!paint.style || paint.sync || draw.Export.running) {
1431
- createPattern(ui, paint, pixelRatio);
1432
- } else {
1433
- if (!paint.patternTask) {
1434
- paint.patternTask = core.ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1435
- paint.patternTask = null;
1436
- if (canvas.bounds.hit(ui.__nowWorld)) createPattern(ui, paint, pixelRatio);
1437
- ui.forceUpdate("surface");
1438
- }), 300);
1439
- }
1440
- }
1405
+ if (!paint.style || originPaint.sync || exporting) draw.PaintImage.createPattern(paint, ui, canvas, renderOptions); else draw.PaintImage.createPatternTask(paint, ui, canvas, renderOptions);
1441
1406
  return false;
1442
1407
  }
1443
1408
  }
1444
1409
  }
1445
1410
 
1446
- function drawImage(ui, canvas, paint, data) {
1447
- canvas.save();
1448
- canvas.clipUI(ui);
1449
- if (paint.blendMode) canvas.blendMode = paint.blendMode;
1450
- if (data.opacity) canvas.opacity *= data.opacity;
1451
- if (data.transform) canvas.transform(data.transform);
1452
- canvas.drawImage(paint.image.getFull(data.filters), 0, 0, data.width, data.height);
1453
- canvas.restore();
1411
+ function drawImage(paint, _imageScaleX, _imageScaleY, ui, canvas, _renderOptions) {
1412
+ const {data: data, image: image} = paint, {blendMode: blendMode} = paint.originPaint, {opacity: opacity, transform: transform} = data, view = image.getFull(data.filters), u = ui.__;
1413
+ let {width: width, height: height} = image, clipUI;
1414
+ if ((clipUI = transform && !transform.onlyScale || u.path || u.cornerRadius) || opacity || blendMode) {
1415
+ canvas.save();
1416
+ clipUI && canvas.clipUI(ui);
1417
+ blendMode && (canvas.blendMode = blendMode);
1418
+ opacity && (canvas.opacity *= opacity);
1419
+ transform && canvas.transform(transform);
1420
+ canvas.drawImage(view, 0, 0, width, height);
1421
+ canvas.restore();
1422
+ } else {
1423
+ if (data.scaleX) width *= data.scaleX, height *= data.scaleY;
1424
+ canvas.drawImage(view, 0, 0, width, height);
1425
+ }
1426
+ }
1427
+
1428
+ function getImageRenderScaleData(paint, ui, canvas, _renderOptions) {
1429
+ const scaleData = ui.getRenderScaleData(true, paint.originPaint.scaleFixed), {data: data} = paint;
1430
+ if (canvas) {
1431
+ const {pixelRatio: pixelRatio} = canvas;
1432
+ scaleData.scaleX *= pixelRatio;
1433
+ scaleData.scaleY *= pixelRatio;
1434
+ }
1435
+ if (data && data.scaleX) {
1436
+ scaleData.scaleX *= Math.abs(data.scaleX);
1437
+ scaleData.scaleY *= Math.abs(data.scaleY);
1438
+ }
1439
+ return scaleData;
1454
1440
  }
1455
1441
 
1456
1442
  function recycleImage(attrName, data) {
@@ -1482,8 +1468,12 @@ function recycleImage(attrName, data) {
1482
1468
  const PaintImageModule = {
1483
1469
  image: image,
1484
1470
  checkImage: checkImage,
1485
- createPattern: createPattern,
1471
+ drawImage: drawImage,
1472
+ getImageRenderScaleData: getImageRenderScaleData,
1486
1473
  recycleImage: recycleImage,
1474
+ createPatternTask: createPatternTask,
1475
+ createPattern: createPattern,
1476
+ getPatternFixScale: getPatternFixScale,
1487
1477
  createData: createData,
1488
1478
  getPatternData: getPatternData,
1489
1479
  stretchMode: stretchMode,
@@ -1939,10 +1929,8 @@ function createRows(drawData, content, style) {
1939
1929
  bounds = drawData.bounds;
1940
1930
  findMaxWidth = !bounds.width && !style.autoSizeAlign;
1941
1931
  const {__letterSpacing: __letterSpacing, paraIndent: paraIndent, textCase: textCase} = style;
1942
- const {canvas: canvas} = core.Platform;
1943
- const {width: width, height: height} = bounds;
1944
- const charMode = width || height || __letterSpacing || textCase !== "none";
1945
- if (charMode) {
1932
+ const {canvas: canvas} = core.Platform, {width: width} = bounds;
1933
+ if (style.__isCharMode) {
1946
1934
  const wrap = style.textWrap !== "none";
1947
1935
  const breakAll = style.textWrap === "break";
1948
1936
  paraStart = true;
@@ -2071,12 +2059,19 @@ const TextMode = 2;
2071
2059
  function layoutChar(drawData, style, width, _height) {
2072
2060
  const {rows: rows} = drawData;
2073
2061
  const {textAlign: textAlign, paraIndent: paraIndent, letterSpacing: letterSpacing} = style;
2074
- let charX, addWordWidth, indentWidth, mode, wordChar, wordsLength;
2062
+ const justifyLast = width && textAlign.includes("both");
2063
+ const justify = justifyLast || width && textAlign.includes("justify");
2064
+ const justifyLetter = justify && textAlign.includes("letter");
2065
+ let charX, remainingWidth, addWordWidth, addLetterWidth, indentWidth, mode, wordChar, wordsLength, isLastWord, canJustify;
2075
2066
  rows.forEach(row => {
2076
2067
  if (row.words) {
2077
2068
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0, wordsLength = row.words.length;
2078
- addWordWidth = width && (textAlign === "justify" || textAlign === "both") && wordsLength > 1 ? (width - row.width - indentWidth) / (wordsLength - 1) : 0;
2079
- mode = letterSpacing || row.isOverflow ? CharMode : addWordWidth > .01 ? WordMode : TextMode;
2069
+ if (justify) {
2070
+ canJustify = !row.paraEnd || justifyLast;
2071
+ remainingWidth = width - row.width - indentWidth;
2072
+ if (justifyLetter) addLetterWidth = remainingWidth / (row.words.reduce((total, item) => total + item.data.length, 0) - 1); else addWordWidth = wordsLength > 1 ? remainingWidth / (wordsLength - 1) : 0;
2073
+ }
2074
+ mode = letterSpacing || row.isOverflow || justifyLetter ? CharMode : addWordWidth ? WordMode : TextMode;
2080
2075
  if (row.isOverflow && !letterSpacing) row.textMode = true;
2081
2076
  if (mode === TextMode) {
2082
2077
  row.x += indentWidth;
@@ -2094,11 +2089,15 @@ function layoutChar(drawData, style, width, _height) {
2094
2089
  charX = toWordChar(word.data, charX, wordChar);
2095
2090
  if (row.isOverflow || wordChar.char !== " ") row.data.push(wordChar);
2096
2091
  } else {
2097
- charX = toChar(word.data, charX, row.data, row.isOverflow);
2092
+ charX = toChar(word.data, charX, row.data, row.isOverflow, canJustify && addLetterWidth);
2098
2093
  }
2099
- if (addWordWidth && (!row.paraEnd || textAlign === "both") && index !== wordsLength - 1) {
2100
- charX += addWordWidth;
2101
- row.width += addWordWidth;
2094
+ if (canJustify) {
2095
+ isLastWord = index === wordsLength - 1;
2096
+ if (addWordWidth) {
2097
+ if (!isLastWord) charX += addWordWidth, row.width += addWordWidth;
2098
+ } else if (addLetterWidth) {
2099
+ row.width += addLetterWidth * (word.data.length - (isLastWord ? 1 : 0));
2100
+ }
2102
2101
  }
2103
2102
  });
2104
2103
  }
@@ -2124,13 +2123,14 @@ function toWordChar(data, charX, wordChar) {
2124
2123
  return charX;
2125
2124
  }
2126
2125
 
2127
- function toChar(data, charX, rowData, isOverflow) {
2126
+ function toChar(data, charX, rowData, isOverflow, addLetterWidth) {
2128
2127
  data.forEach(char => {
2129
2128
  if (isOverflow || char.char !== " ") {
2130
2129
  char.x = charX;
2131
2130
  rowData.push(char);
2132
2131
  }
2133
2132
  charX += char.width;
2133
+ addLetterWidth && (charX += addLetterWidth);
2134
2134
  });
2135
2135
  return charX;
2136
2136
  }
@@ -2272,10 +2272,10 @@ function getDrawData(content, style) {
2272
2272
  let x = 0, y = 0;
2273
2273
  let width = style.__getInput("width") || 0;
2274
2274
  let height = style.__getInput("height") || 0;
2275
- const {textDecoration: textDecoration, __font: __font, __padding: padding} = style;
2275
+ const {__padding: padding} = style;
2276
2276
  if (padding) {
2277
- if (width) x = padding[left], width -= padding[right] + padding[left]; else if (!style.autoSizeAlign) x = padding[left];
2278
- if (height) y = padding[top], height -= padding[top] + padding[bottom]; else if (!style.autoSizeAlign) y = padding[top];
2277
+ if (width) x = padding[left], width -= padding[right] + padding[left], !width && (width = .01); else if (!style.autoSizeAlign) x = padding[left];
2278
+ if (height) y = padding[top], height -= padding[top] + padding[bottom], !height && (height = .01); else if (!style.autoSizeAlign) y = padding[top];
2279
2279
  }
2280
2280
  const drawData = {
2281
2281
  bounds: {
@@ -2286,14 +2286,14 @@ function getDrawData(content, style) {
2286
2286
  },
2287
2287
  rows: [],
2288
2288
  paraNumber: 0,
2289
- font: core.Platform.canvas.font = __font
2289
+ font: core.Platform.canvas.font = style.__font
2290
2290
  };
2291
2291
  createRows(drawData, content, style);
2292
2292
  if (padding) padAutoText(padding, drawData, style, width, height);
2293
2293
  layoutText(drawData, style);
2294
- layoutChar(drawData, style, width);
2294
+ if (style.__isCharMode) layoutChar(drawData, style, width);
2295
2295
  if (drawData.overflow) clipText(drawData, style, x, width);
2296
- if (textDecoration !== "none") decorationText(drawData, style);
2296
+ if (style.textDecoration !== "none") decorationText(drawData, style);
2297
2297
  return drawData;
2298
2298
  }
2299
2299