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