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