@leafer-draw/miniapp 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.
@@ -1,10 +1,10 @@
1
- import { LeaferCanvasBase, isString, Platform, isNumber, canvasPatch, DataHelper, canvasSizeAttrs, isUndefined, ResizeEvent, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, isArray, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, isObject, BoundsHelper, FourNumberHelper, Matrix, getMatrixData, MatrixHelper, MathHelper, AlignHelper, PointHelper, ImageEvent, AroundHelper, Direction4 } from "@leafer/core";
1
+ import { LeaferCanvasBase, isString, Platform, isNumber, canvasPatch, DataHelper, canvasSizeAttrs, isUndefined, ResizeEvent, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, isArray, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, isObject, BoundsHelper, FourNumberHelper, Matrix, ImageEvent, MatrixHelper, MathHelper, AlignHelper, PointHelper, getMatrixData, AroundHelper, Direction4 } from "@leafer/core";
2
2
 
3
3
  export * from "@leafer/core";
4
4
 
5
5
  export { LeaferImage } from "@leafer/core";
6
6
 
7
- import { PaintImage, Paint, ColorConvert, PaintGradient, Export, Effect, Group, TextConvert } from "@leafer-ui/draw";
7
+ import { Paint, PaintImage, ColorConvert, PaintGradient, Effect, Group, TextConvert } from "@leafer-ui/draw";
8
8
 
9
9
  export * from "@leafer-ui/draw";
10
10
 
@@ -819,102 +819,163 @@ Platform.render = function(target, canvas, options) {
819
819
  if (options.topList.length) options.topList.forEach(item => item.__render(canvas, topOptions));
820
820
  };
821
821
 
822
- function fillText(ui, canvas) {
823
- const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
824
- if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
825
- let row;
826
- for (let i = 0, len = rows.length; i < len; i++) {
827
- row = rows[i];
828
- if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
829
- canvas.fillText(charData.char, charData.x, row.y);
830
- });
831
- }
832
- if (decorationY) {
833
- const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
834
- if (decorationColor) canvas.fillStyle = decorationColor;
835
- rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
836
- }
837
- }
838
-
839
- function fill(fill, ui, canvas) {
822
+ function fill(fill, ui, canvas, renderOptions) {
840
823
  canvas.fillStyle = fill;
841
- fillPathOrText(ui, canvas);
824
+ fillPathOrText(ui, canvas, renderOptions);
842
825
  }
843
826
 
844
- function fills(fills, ui, canvas) {
845
- let item;
827
+ function fills(fills, ui, canvas, renderOptions) {
828
+ let item, originPaint, countImage;
846
829
  for (let i = 0, len = fills.length; i < len; i++) {
847
- item = fills[i];
830
+ item = fills[i], originPaint = item.originPaint;
848
831
  if (item.image) {
849
- if (PaintImage.checkImage(ui, canvas, item, !ui.__.__font)) continue;
832
+ countImage ? countImage++ : countImage = 1;
833
+ if (PaintImage.checkImage(item, !ui.__.__font, ui, canvas, renderOptions)) continue;
850
834
  if (!item.style) {
851
- if (!i && item.image.isPlacehold) ui.drawImagePlaceholder(canvas, item.image);
835
+ if (countImage === 1 && item.image.isPlacehold) ui.drawImagePlaceholder(item, canvas, renderOptions);
852
836
  continue;
853
837
  }
854
838
  }
855
839
  canvas.fillStyle = item.style;
856
- if (item.transform || item.scaleFixed) {
840
+ if (item.transform || originPaint.scaleFixed) {
857
841
  canvas.save();
858
842
  if (item.transform) canvas.transform(item.transform);
859
- if (item.scaleFixed) {
843
+ if (originPaint.scaleFixed) {
860
844
  const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true);
861
- if (item.scaleFixed === true || item.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
845
+ if (originPaint.scaleFixed === true || originPaint.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
862
846
  }
863
- if (item.blendMode) canvas.blendMode = item.blendMode;
864
- fillPathOrText(ui, canvas);
847
+ if (originPaint.blendMode) canvas.blendMode = originPaint.blendMode;
848
+ fillPathOrText(ui, canvas, renderOptions);
865
849
  canvas.restore();
866
850
  } else {
867
- if (item.blendMode) {
868
- canvas.saveBlendMode(item.blendMode);
869
- fillPathOrText(ui, canvas);
851
+ if (originPaint.blendMode) {
852
+ canvas.saveBlendMode(originPaint.blendMode);
853
+ fillPathOrText(ui, canvas, renderOptions);
870
854
  canvas.restoreBlendMode();
871
- } else fillPathOrText(ui, canvas);
855
+ } else fillPathOrText(ui, canvas, renderOptions);
872
856
  }
873
857
  }
874
858
  }
875
859
 
876
- function fillPathOrText(ui, canvas) {
877
- ui.__.__font ? fillText(ui, canvas) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
860
+ function fillPathOrText(ui, canvas, renderOptions) {
861
+ ui.__.__font ? Paint.fillText(ui, canvas, renderOptions) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
878
862
  }
879
863
 
880
- function strokeText(stroke, ui, canvas) {
864
+ function fillText(ui, canvas, _renderOptions) {
865
+ const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
866
+ if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
867
+ let row;
868
+ for (let i = 0, len = rows.length; i < len; i++) {
869
+ row = rows[i];
870
+ if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
871
+ canvas.fillText(charData.char, charData.x, row.y);
872
+ });
873
+ }
874
+ if (decorationY) {
875
+ const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
876
+ if (decorationColor) canvas.fillStyle = decorationColor;
877
+ rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
878
+ }
879
+ }
880
+
881
+ function stroke(stroke, ui, canvas, renderOptions) {
882
+ const data = ui.__;
883
+ if (!data.__strokeWidth) return;
884
+ if (data.__font) {
885
+ Paint.strokeText(stroke, ui, canvas, renderOptions);
886
+ } else {
887
+ switch (data.strokeAlign) {
888
+ case "center":
889
+ drawCenter$1(stroke, 1, ui, canvas, renderOptions);
890
+ break;
891
+
892
+ case "inside":
893
+ drawInside(stroke, ui, canvas, renderOptions);
894
+ break;
895
+
896
+ case "outside":
897
+ drawOutside(stroke, ui, canvas, renderOptions);
898
+ break;
899
+ }
900
+ }
901
+ }
902
+
903
+ function strokes(strokes, ui, canvas, renderOptions) {
904
+ Paint.stroke(strokes, ui, canvas, renderOptions);
905
+ }
906
+
907
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas, renderOptions) {
908
+ const data = ui.__;
909
+ if (isObject(stroke)) {
910
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas, renderOptions);
911
+ } else {
912
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
913
+ canvas.stroke();
914
+ }
915
+ if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas, renderOptions);
916
+ }
917
+
918
+ function drawInside(stroke, ui, canvas, renderOptions) {
919
+ canvas.save();
920
+ canvas.clipUI(ui);
921
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
922
+ canvas.restore();
923
+ }
924
+
925
+ function drawOutside(stroke, ui, canvas, renderOptions) {
926
+ const data = ui.__;
927
+ if (data.__fillAfterStroke) {
928
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
929
+ } else {
930
+ const {renderBounds: renderBounds} = ui.__layout;
931
+ const out = canvas.getSameCanvas(true, true);
932
+ ui.__drawRenderPath(out);
933
+ drawCenter$1(stroke, 2, ui, out, renderOptions);
934
+ out.clipUI(data);
935
+ out.clearWorld(renderBounds);
936
+ LeafHelper.copyCanvasByWorld(ui, canvas, out);
937
+ out.recycle(ui.__nowWorld);
938
+ }
939
+ }
940
+
941
+ function strokeText(stroke, ui, canvas, renderOptions) {
881
942
  switch (ui.__.strokeAlign) {
882
943
  case "center":
883
- drawCenter$1(stroke, 1, ui, canvas);
944
+ drawCenter(stroke, 1, ui, canvas, renderOptions);
884
945
  break;
885
946
 
886
947
  case "inside":
887
- drawAlign(stroke, "inside", ui, canvas);
948
+ drawAlign(stroke, "inside", ui, canvas, renderOptions);
888
949
  break;
889
950
 
890
951
  case "outside":
891
- ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, "outside", ui, canvas);
952
+ ui.__.__fillAfterStroke ? drawCenter(stroke, 2, ui, canvas, renderOptions) : drawAlign(stroke, "outside", ui, canvas, renderOptions);
892
953
  break;
893
954
  }
894
955
  }
895
956
 
896
- function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
957
+ function drawCenter(stroke, strokeWidthScale, ui, canvas, renderOptions) {
897
958
  const data = ui.__;
898
959
  if (isObject(stroke)) {
899
- drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas);
960
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas, renderOptions);
900
961
  } else {
901
962
  canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
902
- drawTextStroke(ui, canvas);
963
+ Paint.drawTextStroke(ui, canvas, renderOptions);
903
964
  }
904
965
  }
905
966
 
906
- function drawAlign(stroke, align, ui, canvas) {
967
+ function drawAlign(stroke, align, ui, canvas, renderOptions) {
907
968
  const out = canvas.getSameCanvas(true, true);
908
969
  out.font = ui.__.__font;
909
- drawCenter$1(stroke, 2, ui, out);
970
+ drawCenter(stroke, 2, ui, out, renderOptions);
910
971
  out.blendMode = align === "outside" ? "destination-out" : "destination-in";
911
- fillText(ui, out);
972
+ Paint.fillText(ui, out, renderOptions);
912
973
  out.blendMode = "normal";
913
974
  LeafHelper.copyCanvasByWorld(ui, canvas, out);
914
975
  out.recycle(ui.__nowWorld);
915
976
  }
916
977
 
917
- function drawTextStroke(ui, canvas) {
978
+ function drawTextStroke(ui, canvas, _renderOptions) {
918
979
  let row, data = ui.__.__textDrawData;
919
980
  const {rows: rows, decorationY: decorationY} = data;
920
981
  for (let i = 0, len = rows.length; i < len; i++) {
@@ -929,89 +990,29 @@ function drawTextStroke(ui, canvas) {
929
990
  }
930
991
  }
931
992
 
932
- function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
993
+ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas, renderOptions) {
933
994
  let item;
934
995
  const data = ui.__, {__hasMultiStrokeStyle: __hasMultiStrokeStyle} = data;
935
996
  __hasMultiStrokeStyle || canvas.setStroke(undefined, data.__strokeWidth * strokeWidthScale, data);
936
997
  for (let i = 0, len = strokes.length; i < len; i++) {
937
998
  item = strokes[i];
938
- if (item.image && PaintImage.checkImage(ui, canvas, item, false)) continue;
999
+ if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
939
1000
  if (item.style) {
940
1001
  if (__hasMultiStrokeStyle) {
941
1002
  const {strokeStyle: strokeStyle} = item;
942
1003
  strokeStyle ? canvas.setStroke(item.style, data.__getRealStrokeWidth(strokeStyle) * strokeWidthScale, data, strokeStyle) : canvas.setStroke(item.style, data.__strokeWidth * strokeWidthScale, data);
943
1004
  } else canvas.strokeStyle = item.style;
944
- if (item.blendMode) {
945
- canvas.saveBlendMode(item.blendMode);
946
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1005
+ if (item.originPaint.blendMode) {
1006
+ canvas.saveBlendMode(item.originPaint.blendMode);
1007
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
947
1008
  canvas.restoreBlendMode();
948
1009
  } else {
949
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1010
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
950
1011
  }
951
1012
  }
952
1013
  }
953
1014
  }
954
1015
 
955
- function stroke(stroke, ui, canvas) {
956
- const data = ui.__;
957
- if (!data.__strokeWidth) return;
958
- if (data.__font) {
959
- strokeText(stroke, ui, canvas);
960
- } else {
961
- switch (data.strokeAlign) {
962
- case "center":
963
- drawCenter(stroke, 1, ui, canvas);
964
- break;
965
-
966
- case "inside":
967
- drawInside(stroke, ui, canvas);
968
- break;
969
-
970
- case "outside":
971
- drawOutside(stroke, ui, canvas);
972
- break;
973
- }
974
- }
975
- }
976
-
977
- function strokes(strokes, ui, canvas) {
978
- stroke(strokes, ui, canvas);
979
- }
980
-
981
- function drawCenter(stroke, strokeWidthScale, ui, canvas) {
982
- const data = ui.__;
983
- if (isObject(stroke)) {
984
- drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas);
985
- } else {
986
- canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
987
- canvas.stroke();
988
- }
989
- if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas);
990
- }
991
-
992
- function drawInside(stroke, ui, canvas) {
993
- canvas.save();
994
- canvas.clipUI(ui);
995
- drawCenter(stroke, 2, ui, canvas);
996
- canvas.restore();
997
- }
998
-
999
- function drawOutside(stroke, ui, canvas) {
1000
- const data = ui.__;
1001
- if (data.__fillAfterStroke) {
1002
- drawCenter(stroke, 2, ui, canvas);
1003
- } else {
1004
- const {renderBounds: renderBounds} = ui.__layout;
1005
- const out = canvas.getSameCanvas(true, true);
1006
- ui.__drawRenderPath(out);
1007
- drawCenter(stroke, 2, ui, out);
1008
- out.clipUI(data);
1009
- out.clearWorld(renderBounds);
1010
- LeafHelper.copyCanvasByWorld(ui, canvas, out);
1011
- out.recycle(ui.__nowWorld);
1012
- }
1013
- }
1014
-
1015
1016
  const {getSpread: getSpread, copyAndSpread: copyAndSpread, toOuterOf: toOuterOf, getOuterOf: getOuterOf, getByMove: getByMove, move: move$1, getIntersectData: getIntersectData} = BoundsHelper;
1016
1017
 
1017
1018
  const tempBounds$1 = {};
@@ -1099,62 +1100,63 @@ function compute(attrName, ui) {
1099
1100
  if (leafPaints.some(item => item.image)) isAlphaPixel = true;
1100
1101
  isTransparent = true;
1101
1102
  }
1102
- }
1103
- if (attrName === "fill") {
1104
- stintSet(data, "__isAlphaPixelFill", isAlphaPixel);
1105
- stintSet(data, "__isTransparentFill", isTransparent);
1103
+ if (attrName === "fill") {
1104
+ stintSet(data, "__isAlphaPixelFill", isAlphaPixel);
1105
+ stintSet(data, "__isTransparentFill", isTransparent);
1106
+ } else {
1107
+ stintSet(data, "__isAlphaPixelStroke", isAlphaPixel);
1108
+ stintSet(data, "__isTransparentStroke", isTransparent);
1109
+ stintSet(data, "__hasMultiStrokeStyle", maxChildStrokeWidth);
1110
+ }
1106
1111
  } else {
1107
- stintSet(data, "__isAlphaPixelStroke", isAlphaPixel);
1108
- stintSet(data, "__isTransparentStroke", isTransparent);
1109
- stintSet(data, "__hasMultiStrokeStyle", maxChildStrokeWidth);
1112
+ data.__removePaint(attrName, false);
1110
1113
  }
1111
1114
  }
1112
1115
 
1113
1116
  function getLeafPaint(attrName, paint, ui) {
1114
1117
  if (!isObject(paint) || paint.visible === false || paint.opacity === 0) return undefined;
1115
- let data;
1118
+ let leafPaint;
1116
1119
  const {boxBounds: boxBounds} = ui.__layout;
1117
1120
  switch (paint.type) {
1118
1121
  case "image":
1119
- data = PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1122
+ leafPaint = PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1120
1123
  break;
1121
1124
 
1122
1125
  case "linear":
1123
- data = PaintGradient.linearGradient(paint, boxBounds);
1126
+ leafPaint = PaintGradient.linearGradient(paint, boxBounds);
1124
1127
  break;
1125
1128
 
1126
1129
  case "radial":
1127
- data = PaintGradient.radialGradient(paint, boxBounds);
1130
+ leafPaint = PaintGradient.radialGradient(paint, boxBounds);
1128
1131
  break;
1129
1132
 
1130
1133
  case "angular":
1131
- data = PaintGradient.conicGradient(paint, boxBounds);
1134
+ leafPaint = PaintGradient.conicGradient(paint, boxBounds);
1132
1135
  break;
1133
1136
 
1134
1137
  case "solid":
1135
1138
  const {type: type, color: color, opacity: opacity} = paint;
1136
- data = {
1139
+ leafPaint = {
1137
1140
  type: type,
1138
1141
  style: ColorConvert.string(color, opacity)
1139
1142
  };
1140
1143
  break;
1141
1144
 
1142
1145
  default:
1143
- if (!isUndefined(paint.r)) data = {
1146
+ if (!isUndefined(paint.r)) leafPaint = {
1144
1147
  type: "solid",
1145
1148
  style: ColorConvert.string(paint)
1146
1149
  };
1147
1150
  }
1148
- if (data) {
1149
- if (isString(data.style) && hasTransparent$1(data.style)) data.isTransparent = true;
1151
+ if (leafPaint) {
1152
+ leafPaint.originPaint = paint;
1153
+ if (isString(leafPaint.style) && hasTransparent$1(leafPaint.style)) leafPaint.isTransparent = true;
1150
1154
  if (paint.style) {
1151
1155
  if (paint.style.strokeWidth === 0) return undefined;
1152
- data.strokeStyle = paint.style;
1156
+ leafPaint.strokeStyle = paint.style;
1153
1157
  }
1154
- if (paint.editing) data.editing = paint.editing;
1155
- if (paint.blendMode) data.blendMode = paint.blendMode;
1156
1158
  }
1157
- return data;
1159
+ return leafPaint;
1158
1160
  }
1159
1161
 
1160
1162
  const PaintModule = {
@@ -1167,88 +1169,118 @@ const PaintModule = {
1167
1169
  strokes: strokes,
1168
1170
  strokeText: strokeText,
1169
1171
  drawTextStroke: drawTextStroke,
1172
+ drawStrokesStyle: drawStrokesStyle,
1170
1173
  shape: shape
1171
1174
  };
1172
1175
 
1173
- let origin = {}, tempMatrix$1 = getMatrixData();
1176
+ let cache, box = new Bounds;
1174
1177
 
1175
- const {get: get$3, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1178
+ const {isSame: isSame} = BoundsHelper;
1176
1179
 
1177
- function stretchMode(data, box, scaleX, scaleY) {
1178
- const transform = get$3();
1179
- translate$1(transform, box.x, box.y);
1180
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1181
- data.transform = transform;
1180
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1181
+ let leafPaint, event;
1182
+ const image = ImageManager.get(paint);
1183
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1184
+ leafPaint = cache.leafPaint;
1185
+ } else {
1186
+ leafPaint = {
1187
+ type: paint.type,
1188
+ image: image
1189
+ };
1190
+ if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1191
+ cache = image.use > 1 ? {
1192
+ leafPaint: leafPaint,
1193
+ paint: paint,
1194
+ boxBounds: box.set(boxBounds)
1195
+ } : null;
1196
+ }
1197
+ if (firstUse || image.loading) event = {
1198
+ image: image,
1199
+ attrName: attrName,
1200
+ attrValue: paint
1201
+ };
1202
+ if (image.ready) {
1203
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1204
+ if (firstUse) {
1205
+ onLoad(ui, event);
1206
+ onLoadSuccess(ui, event);
1207
+ }
1208
+ } else if (image.error) {
1209
+ if (firstUse) onLoadError(ui, event, image.error);
1210
+ } else {
1211
+ if (firstUse) {
1212
+ ignoreRender(ui, true);
1213
+ onLoad(ui, event);
1214
+ }
1215
+ leafPaint.loadId = image.load(() => {
1216
+ ignoreRender(ui, false);
1217
+ if (!ui.destroyed) {
1218
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1219
+ if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1220
+ ui.forceUpdate("surface");
1221
+ }
1222
+ onLoadSuccess(ui, event);
1223
+ }
1224
+ leafPaint.loadId = undefined;
1225
+ }, error => {
1226
+ ignoreRender(ui, false);
1227
+ onLoadError(ui, event, error);
1228
+ leafPaint.loadId = undefined;
1229
+ });
1230
+ if (ui.placeholderColor) {
1231
+ if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1232
+ if (!image.ready) {
1233
+ image.isPlacehold = true;
1234
+ ui.forceUpdate("surface");
1235
+ }
1236
+ }, ui.placeholderDelay);
1237
+ }
1238
+ }
1239
+ return leafPaint;
1182
1240
  }
1183
1241
 
1184
- function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1185
- const transform = get$3();
1186
- translate$1(transform, box.x + x, box.y + y);
1187
- scaleHelper(transform, scaleX, scaleY);
1188
- if (rotation) rotateOfOuter$1(transform, {
1189
- x: box.x + box.width / 2,
1190
- y: box.y + box.height / 2
1191
- }, rotation);
1192
- data.transform = transform;
1242
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1243
+ if (attrName === "fill" && !ui.__.__naturalWidth) {
1244
+ const data = ui.__;
1245
+ data.__naturalWidth = image.width / data.pixelRatio;
1246
+ data.__naturalHeight = image.height / data.pixelRatio;
1247
+ if (data.__autoSide) {
1248
+ ui.forceUpdate("width");
1249
+ if (ui.__proxyData) {
1250
+ ui.setProxyAttr("width", data.width);
1251
+ ui.setProxyAttr("height", data.height);
1252
+ }
1253
+ return false;
1254
+ }
1255
+ }
1256
+ if (!leafPaint.data) PaintImage.createData(leafPaint, image, paint, boxBounds);
1257
+ return true;
1193
1258
  }
1194
1259
 
1195
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1196
- const transform = get$3();
1197
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1198
- if (clipScaleX) {
1199
- if (rotation || skew) {
1200
- set(tempMatrix$1);
1201
- scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1202
- multiplyParent(transform, tempMatrix$1);
1203
- } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1204
- }
1205
- data.transform = transform;
1260
+ function onLoad(ui, event) {
1261
+ emit(ui, ImageEvent.LOAD, event);
1206
1262
  }
1207
1263
 
1208
- function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1209
- const transform = get$3();
1210
- if (freeTransform) {
1211
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1212
- } else {
1213
- if (rotation) {
1214
- if (align === "center") {
1215
- rotateOfOuter$1(transform, {
1216
- x: width / 2,
1217
- y: height / 2
1218
- }, rotation);
1219
- } else {
1220
- rotate(transform, rotation);
1221
- switch (rotation) {
1222
- case 90:
1223
- translate$1(transform, height, 0);
1224
- break;
1264
+ function onLoadSuccess(ui, event) {
1265
+ emit(ui, ImageEvent.LOADED, event);
1266
+ }
1225
1267
 
1226
- case 180:
1227
- translate$1(transform, width, height);
1228
- break;
1268
+ function onLoadError(ui, event, error) {
1269
+ event.error = error;
1270
+ ui.forceUpdate("surface");
1271
+ emit(ui, ImageEvent.ERROR, event);
1272
+ }
1229
1273
 
1230
- case 270:
1231
- translate$1(transform, 0, width);
1232
- break;
1233
- }
1234
- }
1235
- }
1236
- origin.x = box.x + x;
1237
- origin.y = box.y + y;
1238
- translate$1(transform, origin.x, origin.y);
1239
- if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1240
- }
1241
- data.transform = transform;
1274
+ function emit(ui, type, data) {
1275
+ if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1242
1276
  }
1243
1277
 
1244
- function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1245
- if (rotation) rotate(transform, rotation);
1246
- if (skew) skewHelper(transform, skew.x, skew.y);
1247
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1248
- translate$1(transform, box.x + x, box.y + y);
1278
+ function ignoreRender(ui, value) {
1279
+ const {leafer: leafer} = ui;
1280
+ if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1249
1281
  }
1250
1282
 
1251
- const {get: get$2, translate: translate} = MatrixHelper;
1283
+ const {get: get$3, translate: translate$1} = MatrixHelper;
1252
1284
 
1253
1285
  const tempBox = new Bounds;
1254
1286
 
@@ -1257,17 +1289,13 @@ const tempScaleData = {};
1257
1289
  const tempImage = {};
1258
1290
 
1259
1291
  function createData(leafPaint, image, paint, box) {
1260
- const {changeful: changeful, sync: sync, scaleFixed: scaleFixed} = paint;
1261
- if (changeful) leafPaint.changeful = changeful;
1262
- if (sync) leafPaint.sync = sync;
1263
- if (scaleFixed) leafPaint.scaleFixed = scaleFixed;
1264
- leafPaint.data = getPatternData(paint, box, image);
1292
+ leafPaint.data = PaintImage.getPatternData(paint, box, image);
1265
1293
  }
1266
1294
 
1267
1295
  function getPatternData(paint, box, image) {
1268
1296
  if (paint.padding) box = tempBox.set(box).shrink(paint.padding);
1269
1297
  if (paint.mode === "strench") paint.mode = "stretch";
1270
- let {width: width, height: height} = image;
1298
+ const {width: width, height: height} = image;
1271
1299
  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;
1272
1300
  const sameBox = box.width === width && box.height === height;
1273
1301
  const data = {
@@ -1298,8 +1326,8 @@ function getPatternData(paint, box, image) {
1298
1326
  case "stretch":
1299
1327
  if (!sameBox) {
1300
1328
  scaleX = box.width / width, scaleY = box.height / height;
1301
- stretchMode(data, box, scaleX, scaleY);
1302
- }
1329
+ PaintImage.stretchMode(data, box, scaleX, scaleY);
1330
+ } else if (scaleX) scaleX = scaleY = undefined;
1303
1331
  break;
1304
1332
 
1305
1333
  case "normal":
@@ -1307,13 +1335,13 @@ function getPatternData(paint, box, image) {
1307
1335
  if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) {
1308
1336
  let clipScaleX, clipScaleY;
1309
1337
  if (clipSize) clipScaleX = box.width / clipSize.width, clipScaleY = box.height / clipSize.height;
1310
- clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1338
+ PaintImage.clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1311
1339
  if (clipScaleX) scaleX = scaleX ? scaleX * clipScaleX : clipScaleX, scaleY = scaleY ? scaleY * clipScaleY : clipScaleY;
1312
1340
  }
1313
1341
  break;
1314
1342
 
1315
1343
  case "repeat":
1316
- if (!sameBox || scaleX || rotation || skew) repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1344
+ if (!sameBox || scaleX || rotation || skew) PaintImage.repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1317
1345
  if (!repeat) data.repeat = "repeat";
1318
1346
  const count = isObject(repeat);
1319
1347
  if (gap || count) data.gap = getGapData(gap, count && repeat, tempImage.width, tempImage.height, box);
@@ -1322,18 +1350,16 @@ function getPatternData(paint, box, image) {
1322
1350
  case "fit":
1323
1351
  case "cover":
1324
1352
  default:
1325
- if (scaleX) fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1353
+ if (scaleX) PaintImage.fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1326
1354
  }
1327
1355
  if (!data.transform) {
1328
- if (box.x || box.y) translate(data.transform = get$2(), box.x, box.y);
1356
+ if (box.x || box.y) translate$1(data.transform = get$3(), box.x, box.y);
1329
1357
  }
1330
- data.width = width;
1331
- data.height = height;
1332
1358
  if (scaleX) {
1333
1359
  data.scaleX = scaleX;
1334
1360
  data.scaleY = scaleY;
1335
1361
  }
1336
- if (opacity) data.opacity = opacity;
1362
+ if (opacity && opacity < 1) data.opacity = opacity;
1337
1363
  if (filters) data.filters = filters;
1338
1364
  if (repeat) data.repeat = isString(repeat) ? repeat === "x" ? "repeat-x" : "repeat-y" : "repeat";
1339
1365
  return data;
@@ -1355,180 +1381,82 @@ function getGapValue(gap, size, totalSize, rows) {
1355
1381
  return gap === "auto" ? value < 0 ? 0 : value : value;
1356
1382
  }
1357
1383
 
1358
- let cache, box = new Bounds;
1359
-
1360
- const {isSame: isSame} = BoundsHelper;
1361
-
1362
- function image(ui, attrName, paint, boxBounds, firstUse) {
1363
- let leafPaint, event;
1364
- const image = ImageManager.get(paint);
1365
- if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1366
- leafPaint = cache.leafPaint;
1367
- } else {
1368
- leafPaint = {
1369
- type: paint.type,
1370
- image: image
1371
- };
1372
- if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1373
- cache = image.use > 1 ? {
1374
- leafPaint: leafPaint,
1375
- paint: paint,
1376
- boxBounds: box.set(boxBounds)
1377
- } : null;
1378
- }
1379
- if (firstUse || image.loading) event = {
1380
- image: image,
1381
- attrName: attrName,
1382
- attrValue: paint
1383
- };
1384
- if (image.ready) {
1385
- checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1386
- if (firstUse) {
1387
- onLoad(ui, event);
1388
- onLoadSuccess(ui, event);
1389
- }
1390
- } else if (image.error) {
1391
- if (firstUse) onLoadError(ui, event, image.error);
1392
- } else {
1393
- if (firstUse) {
1394
- ignoreRender(ui, true);
1395
- onLoad(ui, event);
1396
- }
1397
- leafPaint.loadId = image.load(() => {
1398
- ignoreRender(ui, false);
1399
- if (!ui.destroyed) {
1400
- if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1401
- if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1402
- ui.forceUpdate("surface");
1403
- }
1404
- onLoadSuccess(ui, event);
1405
- }
1406
- leafPaint.loadId = undefined;
1407
- }, error => {
1408
- ignoreRender(ui, false);
1409
- onLoadError(ui, event, error);
1410
- leafPaint.loadId = undefined;
1411
- });
1412
- if (ui.placeholderColor) {
1413
- if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1414
- if (!image.ready) {
1415
- image.isPlacehold = true;
1416
- ui.forceUpdate("surface");
1417
- }
1418
- }, ui.placeholderDelay);
1419
- }
1420
- }
1421
- return leafPaint;
1422
- }
1423
-
1424
- function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1425
- if (attrName === "fill" && !ui.__.__naturalWidth) {
1426
- const data = ui.__;
1427
- data.__naturalWidth = image.width / data.pixelRatio;
1428
- data.__naturalHeight = image.height / data.pixelRatio;
1429
- if (data.__autoSide) {
1430
- ui.forceUpdate("width");
1431
- if (ui.__proxyData) {
1432
- ui.setProxyAttr("width", data.width);
1433
- ui.setProxyAttr("height", data.height);
1434
- }
1435
- return false;
1436
- }
1437
- }
1438
- if (!leafPaint.data) createData(leafPaint, image, paint, boxBounds);
1439
- return true;
1440
- }
1441
-
1442
- function onLoad(ui, event) {
1443
- emit(ui, ImageEvent.LOAD, event);
1444
- }
1384
+ let origin = {}, tempMatrix$1 = getMatrixData();
1445
1385
 
1446
- function onLoadSuccess(ui, event) {
1447
- emit(ui, ImageEvent.LOADED, event);
1448
- }
1386
+ const {get: get$2, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1449
1387
 
1450
- function onLoadError(ui, event, error) {
1451
- event.error = error;
1452
- ui.forceUpdate("surface");
1453
- emit(ui, ImageEvent.ERROR, event);
1388
+ function stretchMode(data, box, scaleX, scaleY) {
1389
+ const transform = get$2(), {x: x, y: y} = box;
1390
+ if (x || y) translate(transform, x, y); else transform.onlyScale = true;
1391
+ scaleHelper(transform, scaleX, scaleY);
1392
+ data.transform = transform;
1454
1393
  }
1455
1394
 
1456
- function emit(ui, type, data) {
1457
- if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1395
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1396
+ const transform = get$2();
1397
+ translate(transform, box.x + x, box.y + y);
1398
+ scaleHelper(transform, scaleX, scaleY);
1399
+ if (rotation) rotateOfOuter$1(transform, {
1400
+ x: box.x + box.width / 2,
1401
+ y: box.y + box.height / 2
1402
+ }, rotation);
1403
+ data.transform = transform;
1458
1404
  }
1459
1405
 
1460
- function ignoreRender(ui, value) {
1461
- const {leafer: leafer} = ui;
1462
- if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1406
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1407
+ const transform = get$2();
1408
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1409
+ if (clipScaleX) {
1410
+ if (rotation || skew) {
1411
+ set(tempMatrix$1);
1412
+ scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1413
+ multiplyParent(transform, tempMatrix$1);
1414
+ } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1415
+ }
1416
+ data.transform = transform;
1463
1417
  }
1464
1418
 
1465
- const {get: get$1, scale: scale, copy: copy$1} = MatrixHelper;
1419
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1420
+ const transform = get$2();
1421
+ if (freeTransform) {
1422
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1423
+ } else {
1424
+ if (rotation) {
1425
+ if (align === "center") {
1426
+ rotateOfOuter$1(transform, {
1427
+ x: width / 2,
1428
+ y: height / 2
1429
+ }, rotation);
1430
+ } else {
1431
+ rotate(transform, rotation);
1432
+ switch (rotation) {
1433
+ case 90:
1434
+ translate(transform, height, 0);
1435
+ break;
1466
1436
 
1467
- const {floor: floor, ceil: ceil, max: max$1, abs: abs$1} = Math;
1437
+ case 180:
1438
+ translate(transform, width, height);
1439
+ break;
1468
1440
 
1469
- function createPattern(ui, paint, pixelRatio) {
1470
- let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1471
- const id = scaleX + "-" + scaleY + "-" + pixelRatio;
1472
- if (paint.patternId !== id && !ui.destroyed) {
1473
- const {image: image, data: data} = paint;
1474
- let imageScale, imageMatrix, {width: width, height: height, scaleX: sx, scaleY: sy, transform: transform, repeat: repeat, gap: gap} = data;
1475
- scaleX *= pixelRatio;
1476
- scaleY *= pixelRatio;
1477
- if (sx) {
1478
- sx = abs$1(sx);
1479
- sy = abs$1(sy);
1480
- imageMatrix = get$1();
1481
- copy$1(imageMatrix, transform);
1482
- scale(imageMatrix, 1 / sx, 1 / sy);
1483
- scaleX *= sx;
1484
- scaleY *= sy;
1485
- }
1486
- width *= scaleX;
1487
- height *= scaleY;
1488
- const size = width * height;
1489
- if (!repeat) {
1490
- if (size > Platform.image.maxCacheSize) return false;
1491
- }
1492
- let maxSize = Platform.image.maxPatternSize;
1493
- if (image.isSVG) {
1494
- const ws = width / image.width;
1495
- if (ws > 1) imageScale = ws / ceil(ws);
1496
- } else {
1497
- const imageSize = image.width * image.height;
1498
- if (maxSize > imageSize) maxSize = imageSize;
1499
- }
1500
- if (size > maxSize) imageScale = Math.sqrt(size / maxSize);
1501
- if (imageScale) {
1502
- scaleX /= imageScale;
1503
- scaleY /= imageScale;
1504
- width /= imageScale;
1505
- height /= imageScale;
1506
- }
1507
- if (sx) {
1508
- scaleX /= sx;
1509
- scaleY /= sy;
1510
- }
1511
- const xGap = gap && gap.x * scaleX;
1512
- const yGap = gap && gap.y * scaleY;
1513
- if (transform || scaleX !== 1 || scaleY !== 1) {
1514
- const canvasWidth = width + (xGap || 0);
1515
- const canvasHeight = height + (yGap || 0);
1516
- scaleX /= canvasWidth / max$1(floor(canvasWidth), 1);
1517
- scaleY /= canvasHeight / max$1(floor(canvasHeight), 1);
1518
- if (!imageMatrix) {
1519
- imageMatrix = get$1();
1520
- if (transform) copy$1(imageMatrix, transform);
1441
+ case 270:
1442
+ translate(transform, 0, width);
1443
+ break;
1444
+ }
1521
1445
  }
1522
- scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1523
1446
  }
1524
- const canvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1525
- const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1526
- paint.style = pattern;
1527
- paint.patternId = id;
1528
- return true;
1529
- } else {
1530
- return false;
1447
+ origin.x = box.x + x;
1448
+ origin.y = box.y + y;
1449
+ translate(transform, origin.x, origin.y);
1450
+ if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1531
1451
  }
1452
+ data.transform = transform;
1453
+ }
1454
+
1455
+ function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1456
+ if (rotation) rotate(transform, rotation);
1457
+ if (skew) skewHelper(transform, skew.x, skew.y);
1458
+ if (scaleX) scaleHelper(transform, scaleX, scaleY);
1459
+ translate(transform, box.x + x, box.y + y);
1532
1460
  }
1533
1461
 
1534
1462
  function __awaiter(thisArg, _arguments, P, generator) {
@@ -1564,58 +1492,116 @@ typeof SuppressedError === "function" ? SuppressedError : function(error, suppre
1564
1492
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1565
1493
  };
1566
1494
 
1567
- function checkImage(ui, canvas, paint, allowDraw) {
1568
- const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1569
- const {pixelRatio: pixelRatio} = canvas, {data: data} = paint;
1570
- if (!data || paint.patternId === scaleX + "-" + scaleY + "-" + pixelRatio && !Export.running) {
1495
+ const {get: get$1, scale: scale, copy: copy$1} = MatrixHelper;
1496
+
1497
+ const {getFloorScale: getFloorScale} = MathHelper, {abs: abs$1} = Math;
1498
+
1499
+ function createPatternTask(paint, ui, canvas, renderOptions) {
1500
+ if (!paint.patternTask) {
1501
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1502
+ paint.patternTask = null;
1503
+ if (canvas.bounds.hit(ui.__nowWorld)) PaintImage.createPattern(paint, ui, canvas, renderOptions);
1504
+ ui.forceUpdate("surface");
1505
+ }), 300);
1506
+ }
1507
+ }
1508
+
1509
+ function createPattern(paint, ui, canvas, renderOptions) {
1510
+ let {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions), id = scaleX + "-" + scaleY;
1511
+ if (paint.patternId !== id && !ui.destroyed) {
1512
+ if (!(Platform.image.isLarge(paint.image, scaleX, scaleY) && !paint.data.repeat)) {
1513
+ const {image: image, data: data} = paint, {transform: transform, gap: gap} = data, fixScale = PaintImage.getPatternFixScale(paint, scaleX, scaleY);
1514
+ let imageMatrix, xGap, yGap, {width: width, height: height} = image;
1515
+ if (fixScale) scaleX *= fixScale, scaleY *= fixScale;
1516
+ width *= scaleX;
1517
+ height *= scaleY;
1518
+ if (gap) {
1519
+ xGap = gap.x * scaleX / abs$1(data.scaleX || 1);
1520
+ yGap = gap.y * scaleY / abs$1(data.scaleY || 1);
1521
+ }
1522
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1523
+ scaleX *= getFloorScale(width + (xGap || 0));
1524
+ scaleY *= getFloorScale(height + (yGap || 0));
1525
+ imageMatrix = get$1();
1526
+ if (transform) copy$1(imageMatrix, transform);
1527
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1528
+ }
1529
+ const imageCanvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1530
+ const pattern = image.getPattern(imageCanvas, data.repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1531
+ paint.style = pattern;
1532
+ paint.patternId = id;
1533
+ }
1534
+ }
1535
+ }
1536
+
1537
+ function getPatternFixScale(paint, imageScaleX, imageScaleY) {
1538
+ const {image: image} = paint;
1539
+ let fixScale, maxSize = Platform.image.maxPatternSize, imageSize = image.width * image.height;
1540
+ if (image.isSVG) {
1541
+ if (imageScaleX > 1) fixScale = Math.ceil(imageScaleX) / imageScaleX;
1542
+ } else {
1543
+ if (maxSize > imageSize) maxSize = imageSize;
1544
+ }
1545
+ if ((imageSize *= imageScaleX * imageScaleY) > maxSize) fixScale = Math.sqrt(maxSize / imageSize);
1546
+ return fixScale;
1547
+ }
1548
+
1549
+ function checkImage(paint, drawImage, ui, canvas, renderOptions) {
1550
+ const {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions);
1551
+ const {image: image, data: data, originPaint: originPaint} = paint, {exporting: exporting} = renderOptions;
1552
+ if (!data || paint.patternId === scaleX + "-" + scaleY && !exporting) {
1571
1553
  return false;
1572
1554
  } else {
1573
- if (allowDraw) {
1555
+ if (drawImage) {
1574
1556
  if (data.repeat) {
1575
- allowDraw = false;
1576
- } else if (!(paint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || Export.running)) {
1577
- let {width: width, height: height} = data;
1578
- width *= scaleX * pixelRatio;
1579
- height *= scaleY * pixelRatio;
1580
- if (data.scaleX) {
1581
- width *= data.scaleX;
1582
- height *= data.scaleY;
1583
- }
1584
- allowDraw = width * height > Platform.image.maxCacheSize;
1557
+ drawImage = false;
1558
+ } else if (!(originPaint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || exporting)) {
1559
+ drawImage = Platform.image.isLarge(image, scaleX, scaleY);
1585
1560
  }
1586
1561
  }
1587
- if (allowDraw) {
1562
+ if (drawImage) {
1588
1563
  if (ui.__.__isFastShadow) {
1589
1564
  canvas.fillStyle = paint.style || "#000";
1590
1565
  canvas.fill();
1591
1566
  }
1592
- drawImage(ui, canvas, paint, data);
1567
+ PaintImage.drawImage(paint, scaleX, scaleY, ui, canvas, renderOptions);
1593
1568
  return true;
1594
1569
  } else {
1595
- if (!paint.style || paint.sync || Export.running) {
1596
- createPattern(ui, paint, pixelRatio);
1597
- } else {
1598
- if (!paint.patternTask) {
1599
- paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1600
- paint.patternTask = null;
1601
- if (canvas.bounds.hit(ui.__nowWorld)) createPattern(ui, paint, pixelRatio);
1602
- ui.forceUpdate("surface");
1603
- }), 300);
1604
- }
1605
- }
1570
+ if (!paint.style || originPaint.sync || exporting) PaintImage.createPattern(paint, ui, canvas, renderOptions); else PaintImage.createPatternTask(paint, ui, canvas, renderOptions);
1606
1571
  return false;
1607
1572
  }
1608
1573
  }
1609
1574
  }
1610
1575
 
1611
- function drawImage(ui, canvas, paint, data) {
1612
- canvas.save();
1613
- canvas.clipUI(ui);
1614
- if (paint.blendMode) canvas.blendMode = paint.blendMode;
1615
- if (data.opacity) canvas.opacity *= data.opacity;
1616
- if (data.transform) canvas.transform(data.transform);
1617
- canvas.drawImage(paint.image.getFull(data.filters), 0, 0, data.width, data.height);
1618
- canvas.restore();
1576
+ function drawImage(paint, _imageScaleX, _imageScaleY, ui, canvas, _renderOptions) {
1577
+ const {data: data, image: image} = paint, {blendMode: blendMode} = paint.originPaint, {opacity: opacity, transform: transform} = data, view = image.getFull(data.filters), u = ui.__;
1578
+ let {width: width, height: height} = image, clipUI;
1579
+ if ((clipUI = transform && !transform.onlyScale || u.path || u.cornerRadius) || opacity || blendMode) {
1580
+ canvas.save();
1581
+ clipUI && canvas.clipUI(ui);
1582
+ blendMode && (canvas.blendMode = blendMode);
1583
+ opacity && (canvas.opacity *= opacity);
1584
+ transform && canvas.transform(transform);
1585
+ canvas.drawImage(view, 0, 0, width, height);
1586
+ canvas.restore();
1587
+ } else {
1588
+ if (data.scaleX) width *= data.scaleX, height *= data.scaleY;
1589
+ canvas.drawImage(view, 0, 0, width, height);
1590
+ }
1591
+ }
1592
+
1593
+ function getImageRenderScaleData(paint, ui, canvas, _renderOptions) {
1594
+ const scaleData = ui.getRenderScaleData(true, paint.originPaint.scaleFixed), {data: data} = paint;
1595
+ if (canvas) {
1596
+ const {pixelRatio: pixelRatio} = canvas;
1597
+ scaleData.scaleX *= pixelRatio;
1598
+ scaleData.scaleY *= pixelRatio;
1599
+ }
1600
+ if (data && data.scaleX) {
1601
+ scaleData.scaleX *= Math.abs(data.scaleX);
1602
+ scaleData.scaleY *= Math.abs(data.scaleY);
1603
+ }
1604
+ return scaleData;
1619
1605
  }
1620
1606
 
1621
1607
  function recycleImage(attrName, data) {
@@ -1647,8 +1633,12 @@ function recycleImage(attrName, data) {
1647
1633
  const PaintImageModule = {
1648
1634
  image: image,
1649
1635
  checkImage: checkImage,
1650
- createPattern: createPattern,
1636
+ drawImage: drawImage,
1637
+ getImageRenderScaleData: getImageRenderScaleData,
1651
1638
  recycleImage: recycleImage,
1639
+ createPatternTask: createPatternTask,
1640
+ createPattern: createPattern,
1641
+ getPatternFixScale: getPatternFixScale,
1652
1642
  createData: createData,
1653
1643
  getPatternData: getPatternData,
1654
1644
  stretchMode: stretchMode,
@@ -2104,10 +2094,8 @@ function createRows(drawData, content, style) {
2104
2094
  bounds = drawData.bounds;
2105
2095
  findMaxWidth = !bounds.width && !style.autoSizeAlign;
2106
2096
  const {__letterSpacing: __letterSpacing, paraIndent: paraIndent, textCase: textCase} = style;
2107
- const {canvas: canvas} = Platform;
2108
- const {width: width, height: height} = bounds;
2109
- const charMode = width || height || __letterSpacing || textCase !== "none";
2110
- if (charMode) {
2097
+ const {canvas: canvas} = Platform, {width: width} = bounds;
2098
+ if (style.__isCharMode) {
2111
2099
  const wrap = style.textWrap !== "none";
2112
2100
  const breakAll = style.textWrap === "break";
2113
2101
  paraStart = true;
@@ -2236,12 +2224,19 @@ const TextMode = 2;
2236
2224
  function layoutChar(drawData, style, width, _height) {
2237
2225
  const {rows: rows} = drawData;
2238
2226
  const {textAlign: textAlign, paraIndent: paraIndent, letterSpacing: letterSpacing} = style;
2239
- let charX, addWordWidth, indentWidth, mode, wordChar, wordsLength;
2227
+ const justifyLast = width && textAlign.includes("both");
2228
+ const justify = justifyLast || width && textAlign.includes("justify");
2229
+ const justifyLetter = justify && textAlign.includes("letter");
2230
+ let charX, remainingWidth, addWordWidth, addLetterWidth, indentWidth, mode, wordChar, wordsLength, isLastWord, canJustify;
2240
2231
  rows.forEach(row => {
2241
2232
  if (row.words) {
2242
2233
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0, wordsLength = row.words.length;
2243
- addWordWidth = width && (textAlign === "justify" || textAlign === "both") && wordsLength > 1 ? (width - row.width - indentWidth) / (wordsLength - 1) : 0;
2244
- mode = letterSpacing || row.isOverflow ? CharMode : addWordWidth > .01 ? WordMode : TextMode;
2234
+ if (justify) {
2235
+ canJustify = !row.paraEnd || justifyLast;
2236
+ remainingWidth = width - row.width - indentWidth;
2237
+ if (justifyLetter) addLetterWidth = remainingWidth / (row.words.reduce((total, item) => total + item.data.length, 0) - 1); else addWordWidth = wordsLength > 1 ? remainingWidth / (wordsLength - 1) : 0;
2238
+ }
2239
+ mode = letterSpacing || row.isOverflow || justifyLetter ? CharMode : addWordWidth ? WordMode : TextMode;
2245
2240
  if (row.isOverflow && !letterSpacing) row.textMode = true;
2246
2241
  if (mode === TextMode) {
2247
2242
  row.x += indentWidth;
@@ -2259,11 +2254,15 @@ function layoutChar(drawData, style, width, _height) {
2259
2254
  charX = toWordChar(word.data, charX, wordChar);
2260
2255
  if (row.isOverflow || wordChar.char !== " ") row.data.push(wordChar);
2261
2256
  } else {
2262
- charX = toChar(word.data, charX, row.data, row.isOverflow);
2257
+ charX = toChar(word.data, charX, row.data, row.isOverflow, canJustify && addLetterWidth);
2263
2258
  }
2264
- if (addWordWidth && (!row.paraEnd || textAlign === "both") && index !== wordsLength - 1) {
2265
- charX += addWordWidth;
2266
- row.width += addWordWidth;
2259
+ if (canJustify) {
2260
+ isLastWord = index === wordsLength - 1;
2261
+ if (addWordWidth) {
2262
+ if (!isLastWord) charX += addWordWidth, row.width += addWordWidth;
2263
+ } else if (addLetterWidth) {
2264
+ row.width += addLetterWidth * (word.data.length - (isLastWord ? 1 : 0));
2265
+ }
2267
2266
  }
2268
2267
  });
2269
2268
  }
@@ -2289,13 +2288,14 @@ function toWordChar(data, charX, wordChar) {
2289
2288
  return charX;
2290
2289
  }
2291
2290
 
2292
- function toChar(data, charX, rowData, isOverflow) {
2291
+ function toChar(data, charX, rowData, isOverflow, addLetterWidth) {
2293
2292
  data.forEach(char => {
2294
2293
  if (isOverflow || char.char !== " ") {
2295
2294
  char.x = charX;
2296
2295
  rowData.push(char);
2297
2296
  }
2298
2297
  charX += char.width;
2298
+ addLetterWidth && (charX += addLetterWidth);
2299
2299
  });
2300
2300
  return charX;
2301
2301
  }
@@ -2437,10 +2437,10 @@ function getDrawData(content, style) {
2437
2437
  let x = 0, y = 0;
2438
2438
  let width = style.__getInput("width") || 0;
2439
2439
  let height = style.__getInput("height") || 0;
2440
- const {textDecoration: textDecoration, __font: __font, __padding: padding} = style;
2440
+ const {__padding: padding} = style;
2441
2441
  if (padding) {
2442
- if (width) x = padding[left], width -= padding[right] + padding[left]; else if (!style.autoSizeAlign) x = padding[left];
2443
- if (height) y = padding[top], height -= padding[top] + padding[bottom]; else if (!style.autoSizeAlign) y = padding[top];
2442
+ if (width) x = padding[left], width -= padding[right] + padding[left], !width && (width = .01); else if (!style.autoSizeAlign) x = padding[left];
2443
+ if (height) y = padding[top], height -= padding[top] + padding[bottom], !height && (height = .01); else if (!style.autoSizeAlign) y = padding[top];
2444
2444
  }
2445
2445
  const drawData = {
2446
2446
  bounds: {
@@ -2451,14 +2451,14 @@ function getDrawData(content, style) {
2451
2451
  },
2452
2452
  rows: [],
2453
2453
  paraNumber: 0,
2454
- font: Platform.canvas.font = __font
2454
+ font: Platform.canvas.font = style.__font
2455
2455
  };
2456
2456
  createRows(drawData, content, style);
2457
2457
  if (padding) padAutoText(padding, drawData, style, width, height);
2458
2458
  layoutText(drawData, style);
2459
- layoutChar(drawData, style, width);
2459
+ if (style.__isCharMode) layoutChar(drawData, style, width);
2460
2460
  if (drawData.overflow) clipText(drawData, style, x, width);
2461
- if (textDecoration !== "none") decorationText(drawData, style);
2461
+ if (style.textDecoration !== "none") decorationText(drawData, style);
2462
2462
  return drawData;
2463
2463
  }
2464
2464