leafer-draw 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/web.esm.js CHANGED
@@ -1,10 +1,10 @@
1
- import { Debug, LeaferCanvasBase, Platform, isString, isUndefined, DataHelper, canvasSizeAttrs, ResizeEvent, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, isArray, LeafLevelList, LayoutEvent, Run, ImageManager, isObject, BoundsHelper, FourNumberHelper, Matrix, getMatrixData, MatrixHelper, MathHelper, AlignHelper, PointHelper, ImageEvent, AroundHelper, Direction4, isNumber } from "@leafer/core";
1
+ import { Debug, LeaferCanvasBase, Platform, isString, isUndefined, DataHelper, canvasSizeAttrs, ResizeEvent, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, isArray, LeafLevelList, LayoutEvent, Run, ImageManager, isObject, BoundsHelper, FourNumberHelper, Matrix, ImageEvent, MatrixHelper, MathHelper, AlignHelper, PointHelper, getMatrixData, AroundHelper, Direction4, isNumber } 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
 
@@ -872,102 +872,163 @@ Platform.render = function(target, canvas, options) {
872
872
  if (options.topList.length) options.topList.forEach(item => item.__render(canvas, topOptions));
873
873
  };
874
874
 
875
- function fillText(ui, canvas) {
876
- const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
877
- if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
878
- let row;
879
- for (let i = 0, len = rows.length; i < len; i++) {
880
- row = rows[i];
881
- if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
882
- canvas.fillText(charData.char, charData.x, row.y);
883
- });
884
- }
885
- if (decorationY) {
886
- const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
887
- if (decorationColor) canvas.fillStyle = decorationColor;
888
- rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
889
- }
890
- }
891
-
892
- function fill(fill, ui, canvas) {
875
+ function fill(fill, ui, canvas, renderOptions) {
893
876
  canvas.fillStyle = fill;
894
- fillPathOrText(ui, canvas);
877
+ fillPathOrText(ui, canvas, renderOptions);
895
878
  }
896
879
 
897
- function fills(fills, ui, canvas) {
898
- let item;
880
+ function fills(fills, ui, canvas, renderOptions) {
881
+ let item, originPaint, countImage;
899
882
  for (let i = 0, len = fills.length; i < len; i++) {
900
- item = fills[i];
883
+ item = fills[i], originPaint = item.originPaint;
901
884
  if (item.image) {
902
- if (PaintImage.checkImage(ui, canvas, item, !ui.__.__font)) continue;
885
+ countImage ? countImage++ : countImage = 1;
886
+ if (PaintImage.checkImage(item, !ui.__.__font, ui, canvas, renderOptions)) continue;
903
887
  if (!item.style) {
904
- if (!i && item.image.isPlacehold) ui.drawImagePlaceholder(canvas, item.image);
888
+ if (countImage === 1 && item.image.isPlacehold) ui.drawImagePlaceholder(item, canvas, renderOptions);
905
889
  continue;
906
890
  }
907
891
  }
908
892
  canvas.fillStyle = item.style;
909
- if (item.transform || item.scaleFixed) {
893
+ if (item.transform || originPaint.scaleFixed) {
910
894
  canvas.save();
911
895
  if (item.transform) canvas.transform(item.transform);
912
- if (item.scaleFixed) {
896
+ if (originPaint.scaleFixed) {
913
897
  const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true);
914
- if (item.scaleFixed === true || item.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
898
+ if (originPaint.scaleFixed === true || originPaint.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
915
899
  }
916
- if (item.blendMode) canvas.blendMode = item.blendMode;
917
- fillPathOrText(ui, canvas);
900
+ if (originPaint.blendMode) canvas.blendMode = originPaint.blendMode;
901
+ fillPathOrText(ui, canvas, renderOptions);
918
902
  canvas.restore();
919
903
  } else {
920
- if (item.blendMode) {
921
- canvas.saveBlendMode(item.blendMode);
922
- fillPathOrText(ui, canvas);
904
+ if (originPaint.blendMode) {
905
+ canvas.saveBlendMode(originPaint.blendMode);
906
+ fillPathOrText(ui, canvas, renderOptions);
923
907
  canvas.restoreBlendMode();
924
- } else fillPathOrText(ui, canvas);
908
+ } else fillPathOrText(ui, canvas, renderOptions);
925
909
  }
926
910
  }
927
911
  }
928
912
 
929
- function fillPathOrText(ui, canvas) {
930
- ui.__.__font ? fillText(ui, canvas) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
913
+ function fillPathOrText(ui, canvas, renderOptions) {
914
+ ui.__.__font ? Paint.fillText(ui, canvas, renderOptions) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
931
915
  }
932
916
 
933
- function strokeText(stroke, ui, canvas) {
917
+ function fillText(ui, canvas, _renderOptions) {
918
+ const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
919
+ if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
920
+ let row;
921
+ for (let i = 0, len = rows.length; i < len; i++) {
922
+ row = rows[i];
923
+ if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
924
+ canvas.fillText(charData.char, charData.x, row.y);
925
+ });
926
+ }
927
+ if (decorationY) {
928
+ const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
929
+ if (decorationColor) canvas.fillStyle = decorationColor;
930
+ rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
931
+ }
932
+ }
933
+
934
+ function stroke(stroke, ui, canvas, renderOptions) {
935
+ const data = ui.__;
936
+ if (!data.__strokeWidth) return;
937
+ if (data.__font) {
938
+ Paint.strokeText(stroke, ui, canvas, renderOptions);
939
+ } else {
940
+ switch (data.strokeAlign) {
941
+ case "center":
942
+ drawCenter$1(stroke, 1, ui, canvas, renderOptions);
943
+ break;
944
+
945
+ case "inside":
946
+ drawInside(stroke, ui, canvas, renderOptions);
947
+ break;
948
+
949
+ case "outside":
950
+ drawOutside(stroke, ui, canvas, renderOptions);
951
+ break;
952
+ }
953
+ }
954
+ }
955
+
956
+ function strokes(strokes, ui, canvas, renderOptions) {
957
+ Paint.stroke(strokes, ui, canvas, renderOptions);
958
+ }
959
+
960
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas, renderOptions) {
961
+ const data = ui.__;
962
+ if (isObject(stroke)) {
963
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas, renderOptions);
964
+ } else {
965
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
966
+ canvas.stroke();
967
+ }
968
+ if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas, renderOptions);
969
+ }
970
+
971
+ function drawInside(stroke, ui, canvas, renderOptions) {
972
+ canvas.save();
973
+ canvas.clipUI(ui);
974
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
975
+ canvas.restore();
976
+ }
977
+
978
+ function drawOutside(stroke, ui, canvas, renderOptions) {
979
+ const data = ui.__;
980
+ if (data.__fillAfterStroke) {
981
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
982
+ } else {
983
+ const {renderBounds: renderBounds} = ui.__layout;
984
+ const out = canvas.getSameCanvas(true, true);
985
+ ui.__drawRenderPath(out);
986
+ drawCenter$1(stroke, 2, ui, out, renderOptions);
987
+ out.clipUI(data);
988
+ out.clearWorld(renderBounds);
989
+ LeafHelper.copyCanvasByWorld(ui, canvas, out);
990
+ out.recycle(ui.__nowWorld);
991
+ }
992
+ }
993
+
994
+ function strokeText(stroke, ui, canvas, renderOptions) {
934
995
  switch (ui.__.strokeAlign) {
935
996
  case "center":
936
- drawCenter$1(stroke, 1, ui, canvas);
997
+ drawCenter(stroke, 1, ui, canvas, renderOptions);
937
998
  break;
938
999
 
939
1000
  case "inside":
940
- drawAlign(stroke, "inside", ui, canvas);
1001
+ drawAlign(stroke, "inside", ui, canvas, renderOptions);
941
1002
  break;
942
1003
 
943
1004
  case "outside":
944
- ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, "outside", ui, canvas);
1005
+ ui.__.__fillAfterStroke ? drawCenter(stroke, 2, ui, canvas, renderOptions) : drawAlign(stroke, "outside", ui, canvas, renderOptions);
945
1006
  break;
946
1007
  }
947
1008
  }
948
1009
 
949
- function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1010
+ function drawCenter(stroke, strokeWidthScale, ui, canvas, renderOptions) {
950
1011
  const data = ui.__;
951
1012
  if (isObject(stroke)) {
952
- drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas);
1013
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas, renderOptions);
953
1014
  } else {
954
1015
  canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
955
- drawTextStroke(ui, canvas);
1016
+ Paint.drawTextStroke(ui, canvas, renderOptions);
956
1017
  }
957
1018
  }
958
1019
 
959
- function drawAlign(stroke, align, ui, canvas) {
1020
+ function drawAlign(stroke, align, ui, canvas, renderOptions) {
960
1021
  const out = canvas.getSameCanvas(true, true);
961
1022
  out.font = ui.__.__font;
962
- drawCenter$1(stroke, 2, ui, out);
1023
+ drawCenter(stroke, 2, ui, out, renderOptions);
963
1024
  out.blendMode = align === "outside" ? "destination-out" : "destination-in";
964
- fillText(ui, out);
1025
+ Paint.fillText(ui, out, renderOptions);
965
1026
  out.blendMode = "normal";
966
1027
  LeafHelper.copyCanvasByWorld(ui, canvas, out);
967
1028
  out.recycle(ui.__nowWorld);
968
1029
  }
969
1030
 
970
- function drawTextStroke(ui, canvas) {
1031
+ function drawTextStroke(ui, canvas, _renderOptions) {
971
1032
  let row, data = ui.__.__textDrawData;
972
1033
  const {rows: rows, decorationY: decorationY} = data;
973
1034
  for (let i = 0, len = rows.length; i < len; i++) {
@@ -982,89 +1043,29 @@ function drawTextStroke(ui, canvas) {
982
1043
  }
983
1044
  }
984
1045
 
985
- function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
1046
+ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas, renderOptions) {
986
1047
  let item;
987
1048
  const data = ui.__, {__hasMultiStrokeStyle: __hasMultiStrokeStyle} = data;
988
1049
  __hasMultiStrokeStyle || canvas.setStroke(undefined, data.__strokeWidth * strokeWidthScale, data);
989
1050
  for (let i = 0, len = strokes.length; i < len; i++) {
990
1051
  item = strokes[i];
991
- if (item.image && PaintImage.checkImage(ui, canvas, item, false)) continue;
1052
+ if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
992
1053
  if (item.style) {
993
1054
  if (__hasMultiStrokeStyle) {
994
1055
  const {strokeStyle: strokeStyle} = item;
995
1056
  strokeStyle ? canvas.setStroke(item.style, data.__getRealStrokeWidth(strokeStyle) * strokeWidthScale, data, strokeStyle) : canvas.setStroke(item.style, data.__strokeWidth * strokeWidthScale, data);
996
1057
  } else canvas.strokeStyle = item.style;
997
- if (item.blendMode) {
998
- canvas.saveBlendMode(item.blendMode);
999
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1058
+ if (item.originPaint.blendMode) {
1059
+ canvas.saveBlendMode(item.originPaint.blendMode);
1060
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
1000
1061
  canvas.restoreBlendMode();
1001
1062
  } else {
1002
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1063
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
1003
1064
  }
1004
1065
  }
1005
1066
  }
1006
1067
  }
1007
1068
 
1008
- function stroke(stroke, ui, canvas) {
1009
- const data = ui.__;
1010
- if (!data.__strokeWidth) return;
1011
- if (data.__font) {
1012
- strokeText(stroke, ui, canvas);
1013
- } else {
1014
- switch (data.strokeAlign) {
1015
- case "center":
1016
- drawCenter(stroke, 1, ui, canvas);
1017
- break;
1018
-
1019
- case "inside":
1020
- drawInside(stroke, ui, canvas);
1021
- break;
1022
-
1023
- case "outside":
1024
- drawOutside(stroke, ui, canvas);
1025
- break;
1026
- }
1027
- }
1028
- }
1029
-
1030
- function strokes(strokes, ui, canvas) {
1031
- stroke(strokes, ui, canvas);
1032
- }
1033
-
1034
- function drawCenter(stroke, strokeWidthScale, ui, canvas) {
1035
- const data = ui.__;
1036
- if (isObject(stroke)) {
1037
- drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas);
1038
- } else {
1039
- canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1040
- canvas.stroke();
1041
- }
1042
- if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas);
1043
- }
1044
-
1045
- function drawInside(stroke, ui, canvas) {
1046
- canvas.save();
1047
- canvas.clipUI(ui);
1048
- drawCenter(stroke, 2, ui, canvas);
1049
- canvas.restore();
1050
- }
1051
-
1052
- function drawOutside(stroke, ui, canvas) {
1053
- const data = ui.__;
1054
- if (data.__fillAfterStroke) {
1055
- drawCenter(stroke, 2, ui, canvas);
1056
- } else {
1057
- const {renderBounds: renderBounds} = ui.__layout;
1058
- const out = canvas.getSameCanvas(true, true);
1059
- ui.__drawRenderPath(out);
1060
- drawCenter(stroke, 2, ui, out);
1061
- out.clipUI(data);
1062
- out.clearWorld(renderBounds);
1063
- LeafHelper.copyCanvasByWorld(ui, canvas, out);
1064
- out.recycle(ui.__nowWorld);
1065
- }
1066
- }
1067
-
1068
1069
  const {getSpread: getSpread, copyAndSpread: copyAndSpread, toOuterOf: toOuterOf, getOuterOf: getOuterOf, getByMove: getByMove, move: move$1, getIntersectData: getIntersectData} = BoundsHelper;
1069
1070
 
1070
1071
  const tempBounds$1 = {};
@@ -1152,62 +1153,63 @@ function compute(attrName, ui) {
1152
1153
  if (leafPaints.some(item => item.image)) isAlphaPixel = true;
1153
1154
  isTransparent = true;
1154
1155
  }
1155
- }
1156
- if (attrName === "fill") {
1157
- stintSet(data, "__isAlphaPixelFill", isAlphaPixel);
1158
- stintSet(data, "__isTransparentFill", isTransparent);
1156
+ if (attrName === "fill") {
1157
+ stintSet(data, "__isAlphaPixelFill", isAlphaPixel);
1158
+ stintSet(data, "__isTransparentFill", isTransparent);
1159
+ } else {
1160
+ stintSet(data, "__isAlphaPixelStroke", isAlphaPixel);
1161
+ stintSet(data, "__isTransparentStroke", isTransparent);
1162
+ stintSet(data, "__hasMultiStrokeStyle", maxChildStrokeWidth);
1163
+ }
1159
1164
  } else {
1160
- stintSet(data, "__isAlphaPixelStroke", isAlphaPixel);
1161
- stintSet(data, "__isTransparentStroke", isTransparent);
1162
- stintSet(data, "__hasMultiStrokeStyle", maxChildStrokeWidth);
1165
+ data.__removePaint(attrName, false);
1163
1166
  }
1164
1167
  }
1165
1168
 
1166
1169
  function getLeafPaint(attrName, paint, ui) {
1167
1170
  if (!isObject(paint) || paint.visible === false || paint.opacity === 0) return undefined;
1168
- let data;
1171
+ let leafPaint;
1169
1172
  const {boxBounds: boxBounds} = ui.__layout;
1170
1173
  switch (paint.type) {
1171
1174
  case "image":
1172
- data = PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1175
+ leafPaint = PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1173
1176
  break;
1174
1177
 
1175
1178
  case "linear":
1176
- data = PaintGradient.linearGradient(paint, boxBounds);
1179
+ leafPaint = PaintGradient.linearGradient(paint, boxBounds);
1177
1180
  break;
1178
1181
 
1179
1182
  case "radial":
1180
- data = PaintGradient.radialGradient(paint, boxBounds);
1183
+ leafPaint = PaintGradient.radialGradient(paint, boxBounds);
1181
1184
  break;
1182
1185
 
1183
1186
  case "angular":
1184
- data = PaintGradient.conicGradient(paint, boxBounds);
1187
+ leafPaint = PaintGradient.conicGradient(paint, boxBounds);
1185
1188
  break;
1186
1189
 
1187
1190
  case "solid":
1188
1191
  const {type: type, color: color, opacity: opacity} = paint;
1189
- data = {
1192
+ leafPaint = {
1190
1193
  type: type,
1191
1194
  style: ColorConvert.string(color, opacity)
1192
1195
  };
1193
1196
  break;
1194
1197
 
1195
1198
  default:
1196
- if (!isUndefined(paint.r)) data = {
1199
+ if (!isUndefined(paint.r)) leafPaint = {
1197
1200
  type: "solid",
1198
1201
  style: ColorConvert.string(paint)
1199
1202
  };
1200
1203
  }
1201
- if (data) {
1202
- if (isString(data.style) && hasTransparent$1(data.style)) data.isTransparent = true;
1204
+ if (leafPaint) {
1205
+ leafPaint.originPaint = paint;
1206
+ if (isString(leafPaint.style) && hasTransparent$1(leafPaint.style)) leafPaint.isTransparent = true;
1203
1207
  if (paint.style) {
1204
1208
  if (paint.style.strokeWidth === 0) return undefined;
1205
- data.strokeStyle = paint.style;
1209
+ leafPaint.strokeStyle = paint.style;
1206
1210
  }
1207
- if (paint.editing) data.editing = paint.editing;
1208
- if (paint.blendMode) data.blendMode = paint.blendMode;
1209
1211
  }
1210
- return data;
1212
+ return leafPaint;
1211
1213
  }
1212
1214
 
1213
1215
  const PaintModule = {
@@ -1220,88 +1222,118 @@ const PaintModule = {
1220
1222
  strokes: strokes,
1221
1223
  strokeText: strokeText,
1222
1224
  drawTextStroke: drawTextStroke,
1225
+ drawStrokesStyle: drawStrokesStyle,
1223
1226
  shape: shape
1224
1227
  };
1225
1228
 
1226
- let origin = {}, tempMatrix$1 = getMatrixData();
1229
+ let cache, box = new Bounds;
1227
1230
 
1228
- const {get: get$3, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1231
+ const {isSame: isSame} = BoundsHelper;
1229
1232
 
1230
- function stretchMode(data, box, scaleX, scaleY) {
1231
- const transform = get$3();
1232
- translate$1(transform, box.x, box.y);
1233
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1234
- data.transform = transform;
1233
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1234
+ let leafPaint, event;
1235
+ const image = ImageManager.get(paint);
1236
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1237
+ leafPaint = cache.leafPaint;
1238
+ } else {
1239
+ leafPaint = {
1240
+ type: paint.type,
1241
+ image: image
1242
+ };
1243
+ if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1244
+ cache = image.use > 1 ? {
1245
+ leafPaint: leafPaint,
1246
+ paint: paint,
1247
+ boxBounds: box.set(boxBounds)
1248
+ } : null;
1249
+ }
1250
+ if (firstUse || image.loading) event = {
1251
+ image: image,
1252
+ attrName: attrName,
1253
+ attrValue: paint
1254
+ };
1255
+ if (image.ready) {
1256
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1257
+ if (firstUse) {
1258
+ onLoad(ui, event);
1259
+ onLoadSuccess(ui, event);
1260
+ }
1261
+ } else if (image.error) {
1262
+ if (firstUse) onLoadError(ui, event, image.error);
1263
+ } else {
1264
+ if (firstUse) {
1265
+ ignoreRender(ui, true);
1266
+ onLoad(ui, event);
1267
+ }
1268
+ leafPaint.loadId = image.load(() => {
1269
+ ignoreRender(ui, false);
1270
+ if (!ui.destroyed) {
1271
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1272
+ if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1273
+ ui.forceUpdate("surface");
1274
+ }
1275
+ onLoadSuccess(ui, event);
1276
+ }
1277
+ leafPaint.loadId = undefined;
1278
+ }, error => {
1279
+ ignoreRender(ui, false);
1280
+ onLoadError(ui, event, error);
1281
+ leafPaint.loadId = undefined;
1282
+ });
1283
+ if (ui.placeholderColor) {
1284
+ if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1285
+ if (!image.ready) {
1286
+ image.isPlacehold = true;
1287
+ ui.forceUpdate("surface");
1288
+ }
1289
+ }, ui.placeholderDelay);
1290
+ }
1291
+ }
1292
+ return leafPaint;
1235
1293
  }
1236
1294
 
1237
- function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1238
- const transform = get$3();
1239
- translate$1(transform, box.x + x, box.y + y);
1240
- scaleHelper(transform, scaleX, scaleY);
1241
- if (rotation) rotateOfOuter$1(transform, {
1242
- x: box.x + box.width / 2,
1243
- y: box.y + box.height / 2
1244
- }, rotation);
1245
- data.transform = transform;
1295
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1296
+ if (attrName === "fill" && !ui.__.__naturalWidth) {
1297
+ const data = ui.__;
1298
+ data.__naturalWidth = image.width / data.pixelRatio;
1299
+ data.__naturalHeight = image.height / data.pixelRatio;
1300
+ if (data.__autoSide) {
1301
+ ui.forceUpdate("width");
1302
+ if (ui.__proxyData) {
1303
+ ui.setProxyAttr("width", data.width);
1304
+ ui.setProxyAttr("height", data.height);
1305
+ }
1306
+ return false;
1307
+ }
1308
+ }
1309
+ if (!leafPaint.data) PaintImage.createData(leafPaint, image, paint, boxBounds);
1310
+ return true;
1246
1311
  }
1247
1312
 
1248
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1249
- const transform = get$3();
1250
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1251
- if (clipScaleX) {
1252
- if (rotation || skew) {
1253
- set(tempMatrix$1);
1254
- scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1255
- multiplyParent(transform, tempMatrix$1);
1256
- } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1257
- }
1258
- data.transform = transform;
1313
+ function onLoad(ui, event) {
1314
+ emit(ui, ImageEvent.LOAD, event);
1259
1315
  }
1260
1316
 
1261
- function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1262
- const transform = get$3();
1263
- if (freeTransform) {
1264
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1265
- } else {
1266
- if (rotation) {
1267
- if (align === "center") {
1268
- rotateOfOuter$1(transform, {
1269
- x: width / 2,
1270
- y: height / 2
1271
- }, rotation);
1272
- } else {
1273
- rotate(transform, rotation);
1274
- switch (rotation) {
1275
- case 90:
1276
- translate$1(transform, height, 0);
1277
- break;
1317
+ function onLoadSuccess(ui, event) {
1318
+ emit(ui, ImageEvent.LOADED, event);
1319
+ }
1278
1320
 
1279
- case 180:
1280
- translate$1(transform, width, height);
1281
- break;
1321
+ function onLoadError(ui, event, error) {
1322
+ event.error = error;
1323
+ ui.forceUpdate("surface");
1324
+ emit(ui, ImageEvent.ERROR, event);
1325
+ }
1282
1326
 
1283
- case 270:
1284
- translate$1(transform, 0, width);
1285
- break;
1286
- }
1287
- }
1288
- }
1289
- origin.x = box.x + x;
1290
- origin.y = box.y + y;
1291
- translate$1(transform, origin.x, origin.y);
1292
- if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1293
- }
1294
- data.transform = transform;
1327
+ function emit(ui, type, data) {
1328
+ if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1295
1329
  }
1296
1330
 
1297
- function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1298
- if (rotation) rotate(transform, rotation);
1299
- if (skew) skewHelper(transform, skew.x, skew.y);
1300
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1301
- translate$1(transform, box.x + x, box.y + y);
1331
+ function ignoreRender(ui, value) {
1332
+ const {leafer: leafer} = ui;
1333
+ if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1302
1334
  }
1303
1335
 
1304
- const {get: get$2, translate: translate} = MatrixHelper;
1336
+ const {get: get$3, translate: translate$1} = MatrixHelper;
1305
1337
 
1306
1338
  const tempBox = new Bounds;
1307
1339
 
@@ -1310,17 +1342,13 @@ const tempScaleData = {};
1310
1342
  const tempImage = {};
1311
1343
 
1312
1344
  function createData(leafPaint, image, paint, box) {
1313
- const {changeful: changeful, sync: sync, scaleFixed: scaleFixed} = paint;
1314
- if (changeful) leafPaint.changeful = changeful;
1315
- if (sync) leafPaint.sync = sync;
1316
- if (scaleFixed) leafPaint.scaleFixed = scaleFixed;
1317
- leafPaint.data = getPatternData(paint, box, image);
1345
+ leafPaint.data = PaintImage.getPatternData(paint, box, image);
1318
1346
  }
1319
1347
 
1320
1348
  function getPatternData(paint, box, image) {
1321
1349
  if (paint.padding) box = tempBox.set(box).shrink(paint.padding);
1322
1350
  if (paint.mode === "strench") paint.mode = "stretch";
1323
- let {width: width, height: height} = image;
1351
+ const {width: width, height: height} = image;
1324
1352
  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;
1325
1353
  const sameBox = box.width === width && box.height === height;
1326
1354
  const data = {
@@ -1351,8 +1379,8 @@ function getPatternData(paint, box, image) {
1351
1379
  case "stretch":
1352
1380
  if (!sameBox) {
1353
1381
  scaleX = box.width / width, scaleY = box.height / height;
1354
- stretchMode(data, box, scaleX, scaleY);
1355
- }
1382
+ PaintImage.stretchMode(data, box, scaleX, scaleY);
1383
+ } else if (scaleX) scaleX = scaleY = undefined;
1356
1384
  break;
1357
1385
 
1358
1386
  case "normal":
@@ -1360,13 +1388,13 @@ function getPatternData(paint, box, image) {
1360
1388
  if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) {
1361
1389
  let clipScaleX, clipScaleY;
1362
1390
  if (clipSize) clipScaleX = box.width / clipSize.width, clipScaleY = box.height / clipSize.height;
1363
- clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1391
+ PaintImage.clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1364
1392
  if (clipScaleX) scaleX = scaleX ? scaleX * clipScaleX : clipScaleX, scaleY = scaleY ? scaleY * clipScaleY : clipScaleY;
1365
1393
  }
1366
1394
  break;
1367
1395
 
1368
1396
  case "repeat":
1369
- if (!sameBox || scaleX || rotation || skew) repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1397
+ if (!sameBox || scaleX || rotation || skew) PaintImage.repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1370
1398
  if (!repeat) data.repeat = "repeat";
1371
1399
  const count = isObject(repeat);
1372
1400
  if (gap || count) data.gap = getGapData(gap, count && repeat, tempImage.width, tempImage.height, box);
@@ -1375,18 +1403,16 @@ function getPatternData(paint, box, image) {
1375
1403
  case "fit":
1376
1404
  case "cover":
1377
1405
  default:
1378
- if (scaleX) fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1406
+ if (scaleX) PaintImage.fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1379
1407
  }
1380
1408
  if (!data.transform) {
1381
- if (box.x || box.y) translate(data.transform = get$2(), box.x, box.y);
1409
+ if (box.x || box.y) translate$1(data.transform = get$3(), box.x, box.y);
1382
1410
  }
1383
- data.width = width;
1384
- data.height = height;
1385
1411
  if (scaleX) {
1386
1412
  data.scaleX = scaleX;
1387
1413
  data.scaleY = scaleY;
1388
1414
  }
1389
- if (opacity) data.opacity = opacity;
1415
+ if (opacity && opacity < 1) data.opacity = opacity;
1390
1416
  if (filters) data.filters = filters;
1391
1417
  if (repeat) data.repeat = isString(repeat) ? repeat === "x" ? "repeat-x" : "repeat-y" : "repeat";
1392
1418
  return data;
@@ -1408,180 +1434,82 @@ function getGapValue(gap, size, totalSize, rows) {
1408
1434
  return gap === "auto" ? value < 0 ? 0 : value : value;
1409
1435
  }
1410
1436
 
1411
- let cache, box = new Bounds;
1412
-
1413
- const {isSame: isSame} = BoundsHelper;
1414
-
1415
- function image(ui, attrName, paint, boxBounds, firstUse) {
1416
- let leafPaint, event;
1417
- const image = ImageManager.get(paint);
1418
- if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1419
- leafPaint = cache.leafPaint;
1420
- } else {
1421
- leafPaint = {
1422
- type: paint.type,
1423
- image: image
1424
- };
1425
- if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1426
- cache = image.use > 1 ? {
1427
- leafPaint: leafPaint,
1428
- paint: paint,
1429
- boxBounds: box.set(boxBounds)
1430
- } : null;
1431
- }
1432
- if (firstUse || image.loading) event = {
1433
- image: image,
1434
- attrName: attrName,
1435
- attrValue: paint
1436
- };
1437
- if (image.ready) {
1438
- checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1439
- if (firstUse) {
1440
- onLoad(ui, event);
1441
- onLoadSuccess(ui, event);
1442
- }
1443
- } else if (image.error) {
1444
- if (firstUse) onLoadError(ui, event, image.error);
1445
- } else {
1446
- if (firstUse) {
1447
- ignoreRender(ui, true);
1448
- onLoad(ui, event);
1449
- }
1450
- leafPaint.loadId = image.load(() => {
1451
- ignoreRender(ui, false);
1452
- if (!ui.destroyed) {
1453
- if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1454
- if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1455
- ui.forceUpdate("surface");
1456
- }
1457
- onLoadSuccess(ui, event);
1458
- }
1459
- leafPaint.loadId = undefined;
1460
- }, error => {
1461
- ignoreRender(ui, false);
1462
- onLoadError(ui, event, error);
1463
- leafPaint.loadId = undefined;
1464
- });
1465
- if (ui.placeholderColor) {
1466
- if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1467
- if (!image.ready) {
1468
- image.isPlacehold = true;
1469
- ui.forceUpdate("surface");
1470
- }
1471
- }, ui.placeholderDelay);
1472
- }
1473
- }
1474
- return leafPaint;
1475
- }
1476
-
1477
- function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1478
- if (attrName === "fill" && !ui.__.__naturalWidth) {
1479
- const data = ui.__;
1480
- data.__naturalWidth = image.width / data.pixelRatio;
1481
- data.__naturalHeight = image.height / data.pixelRatio;
1482
- if (data.__autoSide) {
1483
- ui.forceUpdate("width");
1484
- if (ui.__proxyData) {
1485
- ui.setProxyAttr("width", data.width);
1486
- ui.setProxyAttr("height", data.height);
1487
- }
1488
- return false;
1489
- }
1490
- }
1491
- if (!leafPaint.data) createData(leafPaint, image, paint, boxBounds);
1492
- return true;
1493
- }
1494
-
1495
- function onLoad(ui, event) {
1496
- emit(ui, ImageEvent.LOAD, event);
1497
- }
1437
+ let origin = {}, tempMatrix$1 = getMatrixData();
1498
1438
 
1499
- function onLoadSuccess(ui, event) {
1500
- emit(ui, ImageEvent.LOADED, event);
1501
- }
1439
+ const {get: get$2, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1502
1440
 
1503
- function onLoadError(ui, event, error) {
1504
- event.error = error;
1505
- ui.forceUpdate("surface");
1506
- emit(ui, ImageEvent.ERROR, event);
1441
+ function stretchMode(data, box, scaleX, scaleY) {
1442
+ const transform = get$2(), {x: x, y: y} = box;
1443
+ if (x || y) translate(transform, x, y); else transform.onlyScale = true;
1444
+ scaleHelper(transform, scaleX, scaleY);
1445
+ data.transform = transform;
1507
1446
  }
1508
1447
 
1509
- function emit(ui, type, data) {
1510
- if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1448
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1449
+ const transform = get$2();
1450
+ translate(transform, box.x + x, box.y + y);
1451
+ scaleHelper(transform, scaleX, scaleY);
1452
+ if (rotation) rotateOfOuter$1(transform, {
1453
+ x: box.x + box.width / 2,
1454
+ y: box.y + box.height / 2
1455
+ }, rotation);
1456
+ data.transform = transform;
1511
1457
  }
1512
1458
 
1513
- function ignoreRender(ui, value) {
1514
- const {leafer: leafer} = ui;
1515
- if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1459
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1460
+ const transform = get$2();
1461
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1462
+ if (clipScaleX) {
1463
+ if (rotation || skew) {
1464
+ set(tempMatrix$1);
1465
+ scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1466
+ multiplyParent(transform, tempMatrix$1);
1467
+ } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1468
+ }
1469
+ data.transform = transform;
1516
1470
  }
1517
1471
 
1518
- const {get: get$1, scale: scale, copy: copy$1} = MatrixHelper;
1472
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1473
+ const transform = get$2();
1474
+ if (freeTransform) {
1475
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1476
+ } else {
1477
+ if (rotation) {
1478
+ if (align === "center") {
1479
+ rotateOfOuter$1(transform, {
1480
+ x: width / 2,
1481
+ y: height / 2
1482
+ }, rotation);
1483
+ } else {
1484
+ rotate(transform, rotation);
1485
+ switch (rotation) {
1486
+ case 90:
1487
+ translate(transform, height, 0);
1488
+ break;
1519
1489
 
1520
- const {floor: floor, ceil: ceil, max: max$1, abs: abs$1} = Math;
1490
+ case 180:
1491
+ translate(transform, width, height);
1492
+ break;
1521
1493
 
1522
- function createPattern(ui, paint, pixelRatio) {
1523
- let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1524
- const id = scaleX + "-" + scaleY + "-" + pixelRatio;
1525
- if (paint.patternId !== id && !ui.destroyed) {
1526
- const {image: image, data: data} = paint;
1527
- let imageScale, imageMatrix, {width: width, height: height, scaleX: sx, scaleY: sy, transform: transform, repeat: repeat, gap: gap} = data;
1528
- scaleX *= pixelRatio;
1529
- scaleY *= pixelRatio;
1530
- if (sx) {
1531
- sx = abs$1(sx);
1532
- sy = abs$1(sy);
1533
- imageMatrix = get$1();
1534
- copy$1(imageMatrix, transform);
1535
- scale(imageMatrix, 1 / sx, 1 / sy);
1536
- scaleX *= sx;
1537
- scaleY *= sy;
1538
- }
1539
- width *= scaleX;
1540
- height *= scaleY;
1541
- const size = width * height;
1542
- if (!repeat) {
1543
- if (size > Platform.image.maxCacheSize) return false;
1544
- }
1545
- let maxSize = Platform.image.maxPatternSize;
1546
- if (image.isSVG) {
1547
- const ws = width / image.width;
1548
- if (ws > 1) imageScale = ws / ceil(ws);
1549
- } else {
1550
- const imageSize = image.width * image.height;
1551
- if (maxSize > imageSize) maxSize = imageSize;
1552
- }
1553
- if (size > maxSize) imageScale = Math.sqrt(size / maxSize);
1554
- if (imageScale) {
1555
- scaleX /= imageScale;
1556
- scaleY /= imageScale;
1557
- width /= imageScale;
1558
- height /= imageScale;
1559
- }
1560
- if (sx) {
1561
- scaleX /= sx;
1562
- scaleY /= sy;
1563
- }
1564
- const xGap = gap && gap.x * scaleX;
1565
- const yGap = gap && gap.y * scaleY;
1566
- if (transform || scaleX !== 1 || scaleY !== 1) {
1567
- const canvasWidth = width + (xGap || 0);
1568
- const canvasHeight = height + (yGap || 0);
1569
- scaleX /= canvasWidth / max$1(floor(canvasWidth), 1);
1570
- scaleY /= canvasHeight / max$1(floor(canvasHeight), 1);
1571
- if (!imageMatrix) {
1572
- imageMatrix = get$1();
1573
- if (transform) copy$1(imageMatrix, transform);
1494
+ case 270:
1495
+ translate(transform, 0, width);
1496
+ break;
1497
+ }
1574
1498
  }
1575
- scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1576
1499
  }
1577
- const canvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1578
- const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1579
- paint.style = pattern;
1580
- paint.patternId = id;
1581
- return true;
1582
- } else {
1583
- return false;
1500
+ origin.x = box.x + x;
1501
+ origin.y = box.y + y;
1502
+ translate(transform, origin.x, origin.y);
1503
+ if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1584
1504
  }
1505
+ data.transform = transform;
1506
+ }
1507
+
1508
+ function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1509
+ if (rotation) rotate(transform, rotation);
1510
+ if (skew) skewHelper(transform, skew.x, skew.y);
1511
+ if (scaleX) scaleHelper(transform, scaleX, scaleY);
1512
+ translate(transform, box.x + x, box.y + y);
1585
1513
  }
1586
1514
 
1587
1515
  function __awaiter(thisArg, _arguments, P, generator) {
@@ -1617,58 +1545,116 @@ typeof SuppressedError === "function" ? SuppressedError : function(error, suppre
1617
1545
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1618
1546
  };
1619
1547
 
1620
- function checkImage(ui, canvas, paint, allowDraw) {
1621
- const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1622
- const {pixelRatio: pixelRatio} = canvas, {data: data} = paint;
1623
- if (!data || paint.patternId === scaleX + "-" + scaleY + "-" + pixelRatio && !Export.running) {
1548
+ const {get: get$1, scale: scale, copy: copy$1} = MatrixHelper;
1549
+
1550
+ const {getFloorScale: getFloorScale} = MathHelper, {abs: abs$1} = Math;
1551
+
1552
+ function createPatternTask(paint, ui, canvas, renderOptions) {
1553
+ if (!paint.patternTask) {
1554
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1555
+ paint.patternTask = null;
1556
+ if (canvas.bounds.hit(ui.__nowWorld)) PaintImage.createPattern(paint, ui, canvas, renderOptions);
1557
+ ui.forceUpdate("surface");
1558
+ }), 300);
1559
+ }
1560
+ }
1561
+
1562
+ function createPattern(paint, ui, canvas, renderOptions) {
1563
+ let {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions), id = scaleX + "-" + scaleY;
1564
+ if (paint.patternId !== id && !ui.destroyed) {
1565
+ if (!(Platform.image.isLarge(paint.image, scaleX, scaleY) && !paint.data.repeat)) {
1566
+ const {image: image, data: data} = paint, {transform: transform, gap: gap} = data, fixScale = PaintImage.getPatternFixScale(paint, scaleX, scaleY);
1567
+ let imageMatrix, xGap, yGap, {width: width, height: height} = image;
1568
+ if (fixScale) scaleX *= fixScale, scaleY *= fixScale;
1569
+ width *= scaleX;
1570
+ height *= scaleY;
1571
+ if (gap) {
1572
+ xGap = gap.x * scaleX / abs$1(data.scaleX || 1);
1573
+ yGap = gap.y * scaleY / abs$1(data.scaleY || 1);
1574
+ }
1575
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1576
+ scaleX *= getFloorScale(width + (xGap || 0));
1577
+ scaleY *= getFloorScale(height + (yGap || 0));
1578
+ imageMatrix = get$1();
1579
+ if (transform) copy$1(imageMatrix, transform);
1580
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1581
+ }
1582
+ const imageCanvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1583
+ const pattern = image.getPattern(imageCanvas, data.repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1584
+ paint.style = pattern;
1585
+ paint.patternId = id;
1586
+ }
1587
+ }
1588
+ }
1589
+
1590
+ function getPatternFixScale(paint, imageScaleX, imageScaleY) {
1591
+ const {image: image} = paint;
1592
+ let fixScale, maxSize = Platform.image.maxPatternSize, imageSize = image.width * image.height;
1593
+ if (image.isSVG) {
1594
+ if (imageScaleX > 1) fixScale = Math.ceil(imageScaleX) / imageScaleX;
1595
+ } else {
1596
+ if (maxSize > imageSize) maxSize = imageSize;
1597
+ }
1598
+ if ((imageSize *= imageScaleX * imageScaleY) > maxSize) fixScale = Math.sqrt(maxSize / imageSize);
1599
+ return fixScale;
1600
+ }
1601
+
1602
+ function checkImage(paint, drawImage, ui, canvas, renderOptions) {
1603
+ const {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions);
1604
+ const {image: image, data: data, originPaint: originPaint} = paint, {exporting: exporting} = renderOptions;
1605
+ if (!data || paint.patternId === scaleX + "-" + scaleY && !exporting) {
1624
1606
  return false;
1625
1607
  } else {
1626
- if (allowDraw) {
1608
+ if (drawImage) {
1627
1609
  if (data.repeat) {
1628
- allowDraw = false;
1629
- } else if (!(paint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || Export.running)) {
1630
- let {width: width, height: height} = data;
1631
- width *= scaleX * pixelRatio;
1632
- height *= scaleY * pixelRatio;
1633
- if (data.scaleX) {
1634
- width *= data.scaleX;
1635
- height *= data.scaleY;
1636
- }
1637
- allowDraw = width * height > Platform.image.maxCacheSize;
1610
+ drawImage = false;
1611
+ } else if (!(originPaint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || exporting)) {
1612
+ drawImage = Platform.image.isLarge(image, scaleX, scaleY);
1638
1613
  }
1639
1614
  }
1640
- if (allowDraw) {
1615
+ if (drawImage) {
1641
1616
  if (ui.__.__isFastShadow) {
1642
1617
  canvas.fillStyle = paint.style || "#000";
1643
1618
  canvas.fill();
1644
1619
  }
1645
- drawImage(ui, canvas, paint, data);
1620
+ PaintImage.drawImage(paint, scaleX, scaleY, ui, canvas, renderOptions);
1646
1621
  return true;
1647
1622
  } else {
1648
- if (!paint.style || paint.sync || Export.running) {
1649
- createPattern(ui, paint, pixelRatio);
1650
- } else {
1651
- if (!paint.patternTask) {
1652
- paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1653
- paint.patternTask = null;
1654
- if (canvas.bounds.hit(ui.__nowWorld)) createPattern(ui, paint, pixelRatio);
1655
- ui.forceUpdate("surface");
1656
- }), 300);
1657
- }
1658
- }
1623
+ if (!paint.style || originPaint.sync || exporting) PaintImage.createPattern(paint, ui, canvas, renderOptions); else PaintImage.createPatternTask(paint, ui, canvas, renderOptions);
1659
1624
  return false;
1660
1625
  }
1661
1626
  }
1662
1627
  }
1663
1628
 
1664
- function drawImage(ui, canvas, paint, data) {
1665
- canvas.save();
1666
- canvas.clipUI(ui);
1667
- if (paint.blendMode) canvas.blendMode = paint.blendMode;
1668
- if (data.opacity) canvas.opacity *= data.opacity;
1669
- if (data.transform) canvas.transform(data.transform);
1670
- canvas.drawImage(paint.image.getFull(data.filters), 0, 0, data.width, data.height);
1671
- canvas.restore();
1629
+ function drawImage(paint, _imageScaleX, _imageScaleY, ui, canvas, _renderOptions) {
1630
+ const {data: data, image: image} = paint, {blendMode: blendMode} = paint.originPaint, {opacity: opacity, transform: transform} = data, view = image.getFull(data.filters), u = ui.__;
1631
+ let {width: width, height: height} = image, clipUI;
1632
+ if ((clipUI = transform && !transform.onlyScale || u.path || u.cornerRadius) || opacity || blendMode) {
1633
+ canvas.save();
1634
+ clipUI && canvas.clipUI(ui);
1635
+ blendMode && (canvas.blendMode = blendMode);
1636
+ opacity && (canvas.opacity *= opacity);
1637
+ transform && canvas.transform(transform);
1638
+ canvas.drawImage(view, 0, 0, width, height);
1639
+ canvas.restore();
1640
+ } else {
1641
+ if (data.scaleX) width *= data.scaleX, height *= data.scaleY;
1642
+ canvas.drawImage(view, 0, 0, width, height);
1643
+ }
1644
+ }
1645
+
1646
+ function getImageRenderScaleData(paint, ui, canvas, _renderOptions) {
1647
+ const scaleData = ui.getRenderScaleData(true, paint.originPaint.scaleFixed), {data: data} = paint;
1648
+ if (canvas) {
1649
+ const {pixelRatio: pixelRatio} = canvas;
1650
+ scaleData.scaleX *= pixelRatio;
1651
+ scaleData.scaleY *= pixelRatio;
1652
+ }
1653
+ if (data && data.scaleX) {
1654
+ scaleData.scaleX *= Math.abs(data.scaleX);
1655
+ scaleData.scaleY *= Math.abs(data.scaleY);
1656
+ }
1657
+ return scaleData;
1672
1658
  }
1673
1659
 
1674
1660
  function recycleImage(attrName, data) {
@@ -1700,8 +1686,12 @@ function recycleImage(attrName, data) {
1700
1686
  const PaintImageModule = {
1701
1687
  image: image,
1702
1688
  checkImage: checkImage,
1703
- createPattern: createPattern,
1689
+ drawImage: drawImage,
1690
+ getImageRenderScaleData: getImageRenderScaleData,
1704
1691
  recycleImage: recycleImage,
1692
+ createPatternTask: createPatternTask,
1693
+ createPattern: createPattern,
1694
+ getPatternFixScale: getPatternFixScale,
1705
1695
  createData: createData,
1706
1696
  getPatternData: getPatternData,
1707
1697
  stretchMode: stretchMode,
@@ -2157,10 +2147,8 @@ function createRows(drawData, content, style) {
2157
2147
  bounds = drawData.bounds;
2158
2148
  findMaxWidth = !bounds.width && !style.autoSizeAlign;
2159
2149
  const {__letterSpacing: __letterSpacing, paraIndent: paraIndent, textCase: textCase} = style;
2160
- const {canvas: canvas} = Platform;
2161
- const {width: width, height: height} = bounds;
2162
- const charMode = width || height || __letterSpacing || textCase !== "none";
2163
- if (charMode) {
2150
+ const {canvas: canvas} = Platform, {width: width} = bounds;
2151
+ if (style.__isCharMode) {
2164
2152
  const wrap = style.textWrap !== "none";
2165
2153
  const breakAll = style.textWrap === "break";
2166
2154
  paraStart = true;
@@ -2289,12 +2277,19 @@ const TextMode = 2;
2289
2277
  function layoutChar(drawData, style, width, _height) {
2290
2278
  const {rows: rows} = drawData;
2291
2279
  const {textAlign: textAlign, paraIndent: paraIndent, letterSpacing: letterSpacing} = style;
2292
- let charX, addWordWidth, indentWidth, mode, wordChar, wordsLength;
2280
+ const justifyLast = width && textAlign.includes("both");
2281
+ const justify = justifyLast || width && textAlign.includes("justify");
2282
+ const justifyLetter = justify && textAlign.includes("letter");
2283
+ let charX, remainingWidth, addWordWidth, addLetterWidth, indentWidth, mode, wordChar, wordsLength, isLastWord, canJustify;
2293
2284
  rows.forEach(row => {
2294
2285
  if (row.words) {
2295
2286
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0, wordsLength = row.words.length;
2296
- addWordWidth = width && (textAlign === "justify" || textAlign === "both") && wordsLength > 1 ? (width - row.width - indentWidth) / (wordsLength - 1) : 0;
2297
- mode = letterSpacing || row.isOverflow ? CharMode : addWordWidth > .01 ? WordMode : TextMode;
2287
+ if (justify) {
2288
+ canJustify = !row.paraEnd || justifyLast;
2289
+ remainingWidth = width - row.width - indentWidth;
2290
+ if (justifyLetter) addLetterWidth = remainingWidth / (row.words.reduce((total, item) => total + item.data.length, 0) - 1); else addWordWidth = wordsLength > 1 ? remainingWidth / (wordsLength - 1) : 0;
2291
+ }
2292
+ mode = letterSpacing || row.isOverflow || justifyLetter ? CharMode : addWordWidth ? WordMode : TextMode;
2298
2293
  if (row.isOverflow && !letterSpacing) row.textMode = true;
2299
2294
  if (mode === TextMode) {
2300
2295
  row.x += indentWidth;
@@ -2312,11 +2307,15 @@ function layoutChar(drawData, style, width, _height) {
2312
2307
  charX = toWordChar(word.data, charX, wordChar);
2313
2308
  if (row.isOverflow || wordChar.char !== " ") row.data.push(wordChar);
2314
2309
  } else {
2315
- charX = toChar(word.data, charX, row.data, row.isOverflow);
2310
+ charX = toChar(word.data, charX, row.data, row.isOverflow, canJustify && addLetterWidth);
2316
2311
  }
2317
- if (addWordWidth && (!row.paraEnd || textAlign === "both") && index !== wordsLength - 1) {
2318
- charX += addWordWidth;
2319
- row.width += addWordWidth;
2312
+ if (canJustify) {
2313
+ isLastWord = index === wordsLength - 1;
2314
+ if (addWordWidth) {
2315
+ if (!isLastWord) charX += addWordWidth, row.width += addWordWidth;
2316
+ } else if (addLetterWidth) {
2317
+ row.width += addLetterWidth * (word.data.length - (isLastWord ? 1 : 0));
2318
+ }
2320
2319
  }
2321
2320
  });
2322
2321
  }
@@ -2342,13 +2341,14 @@ function toWordChar(data, charX, wordChar) {
2342
2341
  return charX;
2343
2342
  }
2344
2343
 
2345
- function toChar(data, charX, rowData, isOverflow) {
2344
+ function toChar(data, charX, rowData, isOverflow, addLetterWidth) {
2346
2345
  data.forEach(char => {
2347
2346
  if (isOverflow || char.char !== " ") {
2348
2347
  char.x = charX;
2349
2348
  rowData.push(char);
2350
2349
  }
2351
2350
  charX += char.width;
2351
+ addLetterWidth && (charX += addLetterWidth);
2352
2352
  });
2353
2353
  return charX;
2354
2354
  }
@@ -2490,10 +2490,10 @@ function getDrawData(content, style) {
2490
2490
  let x = 0, y = 0;
2491
2491
  let width = style.__getInput("width") || 0;
2492
2492
  let height = style.__getInput("height") || 0;
2493
- const {textDecoration: textDecoration, __font: __font, __padding: padding} = style;
2493
+ const {__padding: padding} = style;
2494
2494
  if (padding) {
2495
- if (width) x = padding[left], width -= padding[right] + padding[left]; else if (!style.autoSizeAlign) x = padding[left];
2496
- if (height) y = padding[top], height -= padding[top] + padding[bottom]; else if (!style.autoSizeAlign) y = padding[top];
2495
+ if (width) x = padding[left], width -= padding[right] + padding[left], !width && (width = .01); else if (!style.autoSizeAlign) x = padding[left];
2496
+ if (height) y = padding[top], height -= padding[top] + padding[bottom], !height && (height = .01); else if (!style.autoSizeAlign) y = padding[top];
2497
2497
  }
2498
2498
  const drawData = {
2499
2499
  bounds: {
@@ -2504,14 +2504,14 @@ function getDrawData(content, style) {
2504
2504
  },
2505
2505
  rows: [],
2506
2506
  paraNumber: 0,
2507
- font: Platform.canvas.font = __font
2507
+ font: Platform.canvas.font = style.__font
2508
2508
  };
2509
2509
  createRows(drawData, content, style);
2510
2510
  if (padding) padAutoText(padding, drawData, style, width, height);
2511
2511
  layoutText(drawData, style);
2512
- layoutChar(drawData, style, width);
2512
+ if (style.__isCharMode) layoutChar(drawData, style, width);
2513
2513
  if (drawData.overflow) clipText(drawData, style, x, width);
2514
- if (textDecoration !== "none") decorationText(drawData, style);
2514
+ if (style.textDecoration !== "none") decorationText(drawData, style);
2515
2515
  return drawData;
2516
2516
  }
2517
2517