@leafer-ui/node 1.9.12 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { LeaferCanvasBase, Platform, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, isArray, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, ResizeEvent, BoundsHelper, Plugin, isObject, FourNumberHelper, Matrix, isUndefined, isString, getMatrixData, MatrixHelper, MathHelper, AlignHelper, PointHelper, ImageEvent, AroundHelper, Direction4, isNumber } from "@leafer/core";
1
+ import { LeaferCanvasBase, Platform, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, isArray, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, ResizeEvent, BoundsHelper, Plugin, isObject, FourNumberHelper, Matrix, isUndefined, isString, ImageEvent, MatrixHelper, MathHelper, AlignHelper, PointHelper, getMatrixData, AroundHelper, Direction4, isNumber } from "@leafer/core";
2
2
 
3
3
  export * from "@leafer/core";
4
4
 
@@ -10,7 +10,7 @@ import { HitCanvasManager, InteractionBase } from "@leafer-ui/core";
10
10
 
11
11
  export * from "@leafer-ui/core";
12
12
 
13
- import { PaintImage, Paint, ColorConvert, PaintGradient, Export, Effect, Group, TextConvert, TwoPointBoundsHelper, Bounds as Bounds$1, FileHelper as FileHelper$1, Platform as Platform$1, isUndefined as isUndefined$1, Matrix as Matrix$1, MathHelper as MathHelper$1, Creator as Creator$1, TaskProcessor, Resource, LeaferCanvasBase as LeaferCanvasBase$1, Debug as Debug$1, Plugin as Plugin$1, UI } from "@leafer-ui/draw";
13
+ import { Paint, PaintImage, ColorConvert, PaintGradient, Effect, Group, TextConvert, TwoPointBoundsHelper, Bounds as Bounds$1, Export, FileHelper as FileHelper$1, Platform as Platform$1, isUndefined as isUndefined$1, Matrix as Matrix$1, MathHelper as MathHelper$1, Creator as Creator$1, TaskProcessor, Resource, LeaferCanvasBase as LeaferCanvasBase$1, Debug as Debug$1, Plugin as Plugin$1, UI } from "@leafer-ui/draw";
14
14
 
15
15
  function __awaiter(thisArg, _arguments, P, generator) {
16
16
  function adopt(value) {
@@ -808,6 +808,7 @@ class Picker {
808
808
  hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
809
809
  if (child.isBranch) {
810
810
  if (hit || child.__ignoreHitWorld) {
811
+ if (child.isBranchLeaf && child.__.__clipAfterFill && !child.__hitWorld(point)) continue;
811
812
  if (child.topChildren) this.eachFind(child.topChildren, false);
812
813
  this.eachFind(child.children, child.__onlyHitMask);
813
814
  if (child.isBranchLeaf) this.hitChild(child, point);
@@ -888,36 +889,19 @@ Platform.render = function(target, canvas, options) {
888
889
  if (options.topList.length) options.topList.forEach(item => item.__render(canvas, topOptions));
889
890
  };
890
891
 
891
- function fillText(ui, canvas) {
892
- const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
893
- if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
894
- let row;
895
- for (let i = 0, len = rows.length; i < len; i++) {
896
- row = rows[i];
897
- if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
898
- canvas.fillText(charData.char, charData.x, row.y);
899
- });
900
- }
901
- if (decorationY) {
902
- const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
903
- if (decorationColor) canvas.fillStyle = decorationColor;
904
- rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
905
- }
906
- }
907
-
908
- function fill(fill, ui, canvas) {
892
+ function fill(fill, ui, canvas, renderOptions) {
909
893
  canvas.fillStyle = fill;
910
- fillPathOrText(ui, canvas);
894
+ fillPathOrText(ui, canvas, renderOptions);
911
895
  }
912
896
 
913
- function fills(fills, ui, canvas) {
897
+ function fills(fills, ui, canvas, renderOptions) {
914
898
  let item;
915
899
  for (let i = 0, len = fills.length; i < len; i++) {
916
900
  item = fills[i];
917
901
  if (item.image) {
918
- if (PaintImage.checkImage(ui, canvas, item, !ui.__.__font)) continue;
902
+ if (PaintImage.checkImage(item, !ui.__.__font, ui, canvas, renderOptions)) continue;
919
903
  if (!item.style) {
920
- if (!i && item.image.isPlacehold) ui.drawImagePlaceholder(canvas, item.image);
904
+ if (!i && item.image.isPlacehold) ui.drawImagePlaceholder(item.image, canvas, renderOptions);
921
905
  continue;
922
906
  }
923
907
  }
@@ -930,60 +914,137 @@ function fills(fills, ui, canvas) {
930
914
  if (item.scaleFixed === true || item.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
931
915
  }
932
916
  if (item.blendMode) canvas.blendMode = item.blendMode;
933
- fillPathOrText(ui, canvas);
917
+ fillPathOrText(ui, canvas, renderOptions);
934
918
  canvas.restore();
935
919
  } else {
936
920
  if (item.blendMode) {
937
921
  canvas.saveBlendMode(item.blendMode);
938
- fillPathOrText(ui, canvas);
922
+ fillPathOrText(ui, canvas, renderOptions);
939
923
  canvas.restoreBlendMode();
940
- } else fillPathOrText(ui, canvas);
924
+ } else fillPathOrText(ui, canvas, renderOptions);
941
925
  }
942
926
  }
943
927
  }
944
928
 
945
- function fillPathOrText(ui, canvas) {
946
- ui.__.__font ? fillText(ui, canvas) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
929
+ function fillPathOrText(ui, canvas, renderOptions) {
930
+ ui.__.__font ? Paint.fillText(ui, canvas, renderOptions) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
931
+ }
932
+
933
+ function fillText(ui, canvas, _renderOptions) {
934
+ const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
935
+ if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
936
+ let row;
937
+ for (let i = 0, len = rows.length; i < len; i++) {
938
+ row = rows[i];
939
+ if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
940
+ canvas.fillText(charData.char, charData.x, row.y);
941
+ });
942
+ }
943
+ if (decorationY) {
944
+ const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
945
+ if (decorationColor) canvas.fillStyle = decorationColor;
946
+ rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
947
+ }
948
+ }
949
+
950
+ function stroke(stroke, ui, canvas, renderOptions) {
951
+ const data = ui.__;
952
+ if (!data.__strokeWidth) return;
953
+ if (data.__font) {
954
+ Paint.strokeText(stroke, ui, canvas, renderOptions);
955
+ } else {
956
+ switch (data.strokeAlign) {
957
+ case "center":
958
+ drawCenter$1(stroke, 1, ui, canvas, renderOptions);
959
+ break;
960
+
961
+ case "inside":
962
+ drawInside(stroke, ui, canvas, renderOptions);
963
+ break;
964
+
965
+ case "outside":
966
+ drawOutside(stroke, ui, canvas, renderOptions);
967
+ break;
968
+ }
969
+ }
970
+ }
971
+
972
+ function strokes(strokes, ui, canvas, renderOptions) {
973
+ Paint.stroke(strokes, ui, canvas, renderOptions);
974
+ }
975
+
976
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas, renderOptions) {
977
+ const data = ui.__;
978
+ if (isObject(stroke)) {
979
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas, renderOptions);
980
+ } else {
981
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
982
+ canvas.stroke();
983
+ }
984
+ if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas, renderOptions);
985
+ }
986
+
987
+ function drawInside(stroke, ui, canvas, renderOptions) {
988
+ canvas.save();
989
+ canvas.clipUI(ui);
990
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
991
+ canvas.restore();
992
+ }
993
+
994
+ function drawOutside(stroke, ui, canvas, renderOptions) {
995
+ const data = ui.__;
996
+ if (data.__fillAfterStroke) {
997
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
998
+ } else {
999
+ const {renderBounds: renderBounds} = ui.__layout;
1000
+ const out = canvas.getSameCanvas(true, true);
1001
+ ui.__drawRenderPath(out);
1002
+ drawCenter$1(stroke, 2, ui, out, renderOptions);
1003
+ out.clipUI(data);
1004
+ out.clearWorld(renderBounds);
1005
+ LeafHelper.copyCanvasByWorld(ui, canvas, out);
1006
+ out.recycle(ui.__nowWorld);
1007
+ }
947
1008
  }
948
1009
 
949
- function strokeText(stroke, ui, canvas) {
1010
+ function strokeText(stroke, ui, canvas, renderOptions) {
950
1011
  switch (ui.__.strokeAlign) {
951
1012
  case "center":
952
- drawCenter$1(stroke, 1, ui, canvas);
1013
+ drawCenter(stroke, 1, ui, canvas, renderOptions);
953
1014
  break;
954
1015
 
955
1016
  case "inside":
956
- drawAlign(stroke, "inside", ui, canvas);
1017
+ drawAlign(stroke, "inside", ui, canvas, renderOptions);
957
1018
  break;
958
1019
 
959
1020
  case "outside":
960
- ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, "outside", ui, canvas);
1021
+ ui.__.__fillAfterStroke ? drawCenter(stroke, 2, ui, canvas, renderOptions) : drawAlign(stroke, "outside", ui, canvas, renderOptions);
961
1022
  break;
962
1023
  }
963
1024
  }
964
1025
 
965
- function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1026
+ function drawCenter(stroke, strokeWidthScale, ui, canvas, renderOptions) {
966
1027
  const data = ui.__;
967
1028
  if (isObject(stroke)) {
968
- drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas);
1029
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas, renderOptions);
969
1030
  } else {
970
1031
  canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
971
- drawTextStroke(ui, canvas);
1032
+ Paint.drawTextStroke(ui, canvas, renderOptions);
972
1033
  }
973
1034
  }
974
1035
 
975
- function drawAlign(stroke, align, ui, canvas) {
1036
+ function drawAlign(stroke, align, ui, canvas, renderOptions) {
976
1037
  const out = canvas.getSameCanvas(true, true);
977
1038
  out.font = ui.__.__font;
978
- drawCenter$1(stroke, 2, ui, out);
1039
+ drawCenter(stroke, 2, ui, out, renderOptions);
979
1040
  out.blendMode = align === "outside" ? "destination-out" : "destination-in";
980
- fillText(ui, out);
1041
+ Paint.fillText(ui, out, renderOptions);
981
1042
  out.blendMode = "normal";
982
1043
  LeafHelper.copyCanvasByWorld(ui, canvas, out);
983
1044
  out.recycle(ui.__nowWorld);
984
1045
  }
985
1046
 
986
- function drawTextStroke(ui, canvas) {
1047
+ function drawTextStroke(ui, canvas, _renderOptions) {
987
1048
  let row, data = ui.__.__textDrawData;
988
1049
  const {rows: rows, decorationY: decorationY} = data;
989
1050
  for (let i = 0, len = rows.length; i < len; i++) {
@@ -998,13 +1059,13 @@ function drawTextStroke(ui, canvas) {
998
1059
  }
999
1060
  }
1000
1061
 
1001
- function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
1062
+ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas, renderOptions) {
1002
1063
  let item;
1003
1064
  const data = ui.__, {__hasMultiStrokeStyle: __hasMultiStrokeStyle} = data;
1004
1065
  __hasMultiStrokeStyle || canvas.setStroke(undefined, data.__strokeWidth * strokeWidthScale, data);
1005
1066
  for (let i = 0, len = strokes.length; i < len; i++) {
1006
1067
  item = strokes[i];
1007
- if (item.image && PaintImage.checkImage(ui, canvas, item, false)) continue;
1068
+ if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
1008
1069
  if (item.style) {
1009
1070
  if (__hasMultiStrokeStyle) {
1010
1071
  const {strokeStyle: strokeStyle} = item;
@@ -1012,75 +1073,15 @@ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
1012
1073
  } else canvas.strokeStyle = item.style;
1013
1074
  if (item.blendMode) {
1014
1075
  canvas.saveBlendMode(item.blendMode);
1015
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1076
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
1016
1077
  canvas.restoreBlendMode();
1017
1078
  } else {
1018
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1079
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
1019
1080
  }
1020
1081
  }
1021
1082
  }
1022
1083
  }
1023
1084
 
1024
- function stroke(stroke, ui, canvas) {
1025
- const data = ui.__;
1026
- if (!data.__strokeWidth) return;
1027
- if (data.__font) {
1028
- strokeText(stroke, ui, canvas);
1029
- } else {
1030
- switch (data.strokeAlign) {
1031
- case "center":
1032
- drawCenter(stroke, 1, ui, canvas);
1033
- break;
1034
-
1035
- case "inside":
1036
- drawInside(stroke, ui, canvas);
1037
- break;
1038
-
1039
- case "outside":
1040
- drawOutside(stroke, ui, canvas);
1041
- break;
1042
- }
1043
- }
1044
- }
1045
-
1046
- function strokes(strokes, ui, canvas) {
1047
- stroke(strokes, ui, canvas);
1048
- }
1049
-
1050
- function drawCenter(stroke, strokeWidthScale, ui, canvas) {
1051
- const data = ui.__;
1052
- if (isObject(stroke)) {
1053
- drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas);
1054
- } else {
1055
- canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1056
- canvas.stroke();
1057
- }
1058
- if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas);
1059
- }
1060
-
1061
- function drawInside(stroke, ui, canvas) {
1062
- canvas.save();
1063
- canvas.clipUI(ui);
1064
- drawCenter(stroke, 2, ui, canvas);
1065
- canvas.restore();
1066
- }
1067
-
1068
- function drawOutside(stroke, ui, canvas) {
1069
- const data = ui.__;
1070
- if (data.__fillAfterStroke) {
1071
- drawCenter(stroke, 2, ui, canvas);
1072
- } else {
1073
- const {renderBounds: renderBounds} = ui.__layout;
1074
- const out = canvas.getSameCanvas(true, true);
1075
- ui.__drawRenderPath(out);
1076
- drawCenter(stroke, 2, ui, out);
1077
- out.clipUI(data);
1078
- out.clearWorld(renderBounds);
1079
- LeafHelper.copyCanvasByWorld(ui, canvas, out);
1080
- out.recycle(ui.__nowWorld);
1081
- }
1082
- }
1083
-
1084
1085
  const {getSpread: getSpread, copyAndSpread: copyAndSpread, toOuterOf: toOuterOf, getOuterOf: getOuterOf, getByMove: getByMove, move: move$1, getIntersectData: getIntersectData} = BoundsHelper;
1085
1086
 
1086
1087
  const tempBounds$1 = {};
@@ -1236,88 +1237,118 @@ const PaintModule = {
1236
1237
  strokes: strokes,
1237
1238
  strokeText: strokeText,
1238
1239
  drawTextStroke: drawTextStroke,
1240
+ drawStrokesStyle: drawStrokesStyle,
1239
1241
  shape: shape
1240
1242
  };
1241
1243
 
1242
- let origin = {}, tempMatrix$1 = getMatrixData();
1244
+ let cache, box = new Bounds;
1243
1245
 
1244
- const {get: get$3, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1246
+ const {isSame: isSame} = BoundsHelper;
1245
1247
 
1246
- function stretchMode(data, box, scaleX, scaleY) {
1247
- const transform = get$3();
1248
- translate$1(transform, box.x, box.y);
1249
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1250
- data.transform = transform;
1248
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1249
+ let leafPaint, event;
1250
+ const image = ImageManager.get(paint);
1251
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1252
+ leafPaint = cache.leafPaint;
1253
+ } else {
1254
+ leafPaint = {
1255
+ type: paint.type,
1256
+ image: image
1257
+ };
1258
+ if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1259
+ cache = image.use > 1 ? {
1260
+ leafPaint: leafPaint,
1261
+ paint: paint,
1262
+ boxBounds: box.set(boxBounds)
1263
+ } : null;
1264
+ }
1265
+ if (firstUse || image.loading) event = {
1266
+ image: image,
1267
+ attrName: attrName,
1268
+ attrValue: paint
1269
+ };
1270
+ if (image.ready) {
1271
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1272
+ if (firstUse) {
1273
+ onLoad(ui, event);
1274
+ onLoadSuccess(ui, event);
1275
+ }
1276
+ } else if (image.error) {
1277
+ if (firstUse) onLoadError(ui, event, image.error);
1278
+ } else {
1279
+ if (firstUse) {
1280
+ ignoreRender(ui, true);
1281
+ onLoad(ui, event);
1282
+ }
1283
+ leafPaint.loadId = image.load(() => {
1284
+ ignoreRender(ui, false);
1285
+ if (!ui.destroyed) {
1286
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1287
+ if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1288
+ ui.forceUpdate("surface");
1289
+ }
1290
+ onLoadSuccess(ui, event);
1291
+ }
1292
+ leafPaint.loadId = undefined;
1293
+ }, error => {
1294
+ ignoreRender(ui, false);
1295
+ onLoadError(ui, event, error);
1296
+ leafPaint.loadId = undefined;
1297
+ });
1298
+ if (ui.placeholderColor) {
1299
+ if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1300
+ if (!image.ready) {
1301
+ image.isPlacehold = true;
1302
+ ui.forceUpdate("surface");
1303
+ }
1304
+ }, ui.placeholderDelay);
1305
+ }
1306
+ }
1307
+ return leafPaint;
1251
1308
  }
1252
1309
 
1253
- function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1254
- const transform = get$3();
1255
- translate$1(transform, box.x + x, box.y + y);
1256
- scaleHelper(transform, scaleX, scaleY);
1257
- if (rotation) rotateOfOuter$1(transform, {
1258
- x: box.x + box.width / 2,
1259
- y: box.y + box.height / 2
1260
- }, rotation);
1261
- data.transform = transform;
1310
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1311
+ if (attrName === "fill" && !ui.__.__naturalWidth) {
1312
+ const data = ui.__;
1313
+ data.__naturalWidth = image.width / data.pixelRatio;
1314
+ data.__naturalHeight = image.height / data.pixelRatio;
1315
+ if (data.__autoSide) {
1316
+ ui.forceUpdate("width");
1317
+ if (ui.__proxyData) {
1318
+ ui.setProxyAttr("width", data.width);
1319
+ ui.setProxyAttr("height", data.height);
1320
+ }
1321
+ return false;
1322
+ }
1323
+ }
1324
+ if (!leafPaint.data) PaintImage.createData(leafPaint, image, paint, boxBounds);
1325
+ return true;
1262
1326
  }
1263
1327
 
1264
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1265
- const transform = get$3();
1266
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1267
- if (clipScaleX) {
1268
- if (rotation || skew) {
1269
- set(tempMatrix$1);
1270
- scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1271
- multiplyParent(transform, tempMatrix$1);
1272
- } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1273
- }
1274
- data.transform = transform;
1328
+ function onLoad(ui, event) {
1329
+ emit(ui, ImageEvent.LOAD, event);
1275
1330
  }
1276
1331
 
1277
- function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1278
- const transform = get$3();
1279
- if (freeTransform) {
1280
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1281
- } else {
1282
- if (rotation) {
1283
- if (align === "center") {
1284
- rotateOfOuter$1(transform, {
1285
- x: width / 2,
1286
- y: height / 2
1287
- }, rotation);
1288
- } else {
1289
- rotate(transform, rotation);
1290
- switch (rotation) {
1291
- case 90:
1292
- translate$1(transform, height, 0);
1293
- break;
1332
+ function onLoadSuccess(ui, event) {
1333
+ emit(ui, ImageEvent.LOADED, event);
1334
+ }
1294
1335
 
1295
- case 180:
1296
- translate$1(transform, width, height);
1297
- break;
1336
+ function onLoadError(ui, event, error) {
1337
+ event.error = error;
1338
+ ui.forceUpdate("surface");
1339
+ emit(ui, ImageEvent.ERROR, event);
1340
+ }
1298
1341
 
1299
- case 270:
1300
- translate$1(transform, 0, width);
1301
- break;
1302
- }
1303
- }
1304
- }
1305
- origin.x = box.x + x;
1306
- origin.y = box.y + y;
1307
- translate$1(transform, origin.x, origin.y);
1308
- if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1309
- }
1310
- data.transform = transform;
1342
+ function emit(ui, type, data) {
1343
+ if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1311
1344
  }
1312
1345
 
1313
- function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1314
- if (rotation) rotate(transform, rotation);
1315
- if (skew) skewHelper(transform, skew.x, skew.y);
1316
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1317
- translate$1(transform, box.x + x, box.y + y);
1346
+ function ignoreRender(ui, value) {
1347
+ const {leafer: leafer} = ui;
1348
+ if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1318
1349
  }
1319
1350
 
1320
- const {get: get$2, translate: translate} = MatrixHelper;
1351
+ const {get: get$3, translate: translate$1} = MatrixHelper;
1321
1352
 
1322
1353
  const tempBox = new Bounds;
1323
1354
 
@@ -1330,13 +1361,13 @@ function createData(leafPaint, image, paint, box) {
1330
1361
  if (changeful) leafPaint.changeful = changeful;
1331
1362
  if (sync) leafPaint.sync = sync;
1332
1363
  if (scaleFixed) leafPaint.scaleFixed = scaleFixed;
1333
- leafPaint.data = getPatternData(paint, box, image);
1364
+ leafPaint.data = PaintImage.getPatternData(paint, box, image);
1334
1365
  }
1335
1366
 
1336
1367
  function getPatternData(paint, box, image) {
1337
1368
  if (paint.padding) box = tempBox.set(box).shrink(paint.padding);
1338
1369
  if (paint.mode === "strench") paint.mode = "stretch";
1339
- let {width: width, height: height} = image;
1370
+ const {width: width, height: height} = image;
1340
1371
  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;
1341
1372
  const sameBox = box.width === width && box.height === height;
1342
1373
  const data = {
@@ -1367,8 +1398,8 @@ function getPatternData(paint, box, image) {
1367
1398
  case "stretch":
1368
1399
  if (!sameBox) {
1369
1400
  scaleX = box.width / width, scaleY = box.height / height;
1370
- stretchMode(data, box, scaleX, scaleY);
1371
- }
1401
+ PaintImage.stretchMode(data, box, scaleX, scaleY);
1402
+ } else if (scaleX) scaleX = scaleY = undefined;
1372
1403
  break;
1373
1404
 
1374
1405
  case "normal":
@@ -1376,13 +1407,13 @@ function getPatternData(paint, box, image) {
1376
1407
  if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) {
1377
1408
  let clipScaleX, clipScaleY;
1378
1409
  if (clipSize) clipScaleX = box.width / clipSize.width, clipScaleY = box.height / clipSize.height;
1379
- clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1410
+ PaintImage.clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1380
1411
  if (clipScaleX) scaleX = scaleX ? scaleX * clipScaleX : clipScaleX, scaleY = scaleY ? scaleY * clipScaleY : clipScaleY;
1381
1412
  }
1382
1413
  break;
1383
1414
 
1384
1415
  case "repeat":
1385
- if (!sameBox || scaleX || rotation || skew) repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1416
+ if (!sameBox || scaleX || rotation || skew) PaintImage.repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1386
1417
  if (!repeat) data.repeat = "repeat";
1387
1418
  const count = isObject(repeat);
1388
1419
  if (gap || count) data.gap = getGapData(gap, count && repeat, tempImage.width, tempImage.height, box);
@@ -1391,18 +1422,16 @@ function getPatternData(paint, box, image) {
1391
1422
  case "fit":
1392
1423
  case "cover":
1393
1424
  default:
1394
- if (scaleX) fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1425
+ if (scaleX) PaintImage.fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1395
1426
  }
1396
1427
  if (!data.transform) {
1397
- if (box.x || box.y) translate(data.transform = get$2(), box.x, box.y);
1428
+ if (box.x || box.y) translate$1(data.transform = get$3(), box.x, box.y);
1398
1429
  }
1399
- data.width = width;
1400
- data.height = height;
1401
1430
  if (scaleX) {
1402
1431
  data.scaleX = scaleX;
1403
1432
  data.scaleY = scaleY;
1404
1433
  }
1405
- if (opacity) data.opacity = opacity;
1434
+ if (opacity && opacity < 1) data.opacity = opacity;
1406
1435
  if (filters) data.filters = filters;
1407
1436
  if (repeat) data.repeat = isString(repeat) ? repeat === "x" ? "repeat-x" : "repeat-y" : "repeat";
1408
1437
  return data;
@@ -1424,234 +1453,194 @@ function getGapValue(gap, size, totalSize, rows) {
1424
1453
  return gap === "auto" ? value < 0 ? 0 : value : value;
1425
1454
  }
1426
1455
 
1427
- let cache, box = new Bounds;
1456
+ let origin = {}, tempMatrix$1 = getMatrixData();
1428
1457
 
1429
- const {isSame: isSame} = BoundsHelper;
1458
+ const {get: get$2, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1430
1459
 
1431
- function image(ui, attrName, paint, boxBounds, firstUse) {
1432
- let leafPaint, event;
1433
- const image = ImageManager.get(paint);
1434
- if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1435
- leafPaint = cache.leafPaint;
1436
- } else {
1437
- leafPaint = {
1438
- type: paint.type,
1439
- image: image
1440
- };
1441
- if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1442
- cache = image.use > 1 ? {
1443
- leafPaint: leafPaint,
1444
- paint: paint,
1445
- boxBounds: box.set(boxBounds)
1446
- } : null;
1447
- }
1448
- if (firstUse || image.loading) event = {
1449
- image: image,
1450
- attrName: attrName,
1451
- attrValue: paint
1452
- };
1453
- if (image.ready) {
1454
- checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1455
- if (firstUse) {
1456
- onLoad(ui, event);
1457
- onLoadSuccess(ui, event);
1458
- }
1459
- } else if (image.error) {
1460
- if (firstUse) onLoadError(ui, event, image.error);
1461
- } else {
1462
- if (firstUse) {
1463
- ignoreRender(ui, true);
1464
- onLoad(ui, event);
1465
- }
1466
- leafPaint.loadId = image.load(() => {
1467
- ignoreRender(ui, false);
1468
- if (!ui.destroyed) {
1469
- if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1470
- if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1471
- ui.forceUpdate("surface");
1472
- }
1473
- onLoadSuccess(ui, event);
1474
- }
1475
- leafPaint.loadId = undefined;
1476
- }, error => {
1477
- ignoreRender(ui, false);
1478
- onLoadError(ui, event, error);
1479
- leafPaint.loadId = undefined;
1480
- });
1481
- if (ui.placeholderColor) {
1482
- if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1483
- if (!image.ready) {
1484
- image.isPlacehold = true;
1485
- ui.forceUpdate("surface");
1486
- }
1487
- }, ui.placeholderDelay);
1488
- }
1489
- }
1490
- return leafPaint;
1460
+ function stretchMode(data, box, scaleX, scaleY) {
1461
+ const transform = get$2(), {x: x, y: y} = box;
1462
+ if (x || y) translate(transform, x, y); else transform.onlyScale = true;
1463
+ scaleHelper(transform, scaleX, scaleY);
1464
+ data.transform = transform;
1491
1465
  }
1492
1466
 
1493
- function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1494
- if (attrName === "fill" && !ui.__.__naturalWidth) {
1495
- const data = ui.__;
1496
- data.__naturalWidth = image.width / data.pixelRatio;
1497
- data.__naturalHeight = image.height / data.pixelRatio;
1498
- if (data.__autoSide) {
1499
- ui.forceUpdate("width");
1500
- if (ui.__proxyData) {
1501
- ui.setProxyAttr("width", data.width);
1502
- ui.setProxyAttr("height", data.height);
1503
- }
1504
- return false;
1505
- }
1506
- }
1507
- if (!leafPaint.data) createData(leafPaint, image, paint, boxBounds);
1508
- return true;
1467
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1468
+ const transform = get$2();
1469
+ translate(transform, box.x + x, box.y + y);
1470
+ scaleHelper(transform, scaleX, scaleY);
1471
+ if (rotation) rotateOfOuter$1(transform, {
1472
+ x: box.x + box.width / 2,
1473
+ y: box.y + box.height / 2
1474
+ }, rotation);
1475
+ data.transform = transform;
1509
1476
  }
1510
1477
 
1511
- function onLoad(ui, event) {
1512
- emit(ui, ImageEvent.LOAD, event);
1478
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1479
+ const transform = get$2();
1480
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1481
+ if (clipScaleX) {
1482
+ if (rotation || skew) {
1483
+ set(tempMatrix$1);
1484
+ scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1485
+ multiplyParent(transform, tempMatrix$1);
1486
+ } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1487
+ }
1488
+ data.transform = transform;
1513
1489
  }
1514
1490
 
1515
- function onLoadSuccess(ui, event) {
1516
- emit(ui, ImageEvent.LOADED, event);
1517
- }
1491
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1492
+ const transform = get$2();
1493
+ if (freeTransform) {
1494
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1495
+ } else {
1496
+ if (rotation) {
1497
+ if (align === "center") {
1498
+ rotateOfOuter$1(transform, {
1499
+ x: width / 2,
1500
+ y: height / 2
1501
+ }, rotation);
1502
+ } else {
1503
+ rotate(transform, rotation);
1504
+ switch (rotation) {
1505
+ case 90:
1506
+ translate(transform, height, 0);
1507
+ break;
1518
1508
 
1519
- function onLoadError(ui, event, error) {
1520
- event.error = error;
1521
- ui.forceUpdate("surface");
1522
- emit(ui, ImageEvent.ERROR, event);
1523
- }
1509
+ case 180:
1510
+ translate(transform, width, height);
1511
+ break;
1524
1512
 
1525
- function emit(ui, type, data) {
1526
- if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1513
+ case 270:
1514
+ translate(transform, 0, width);
1515
+ break;
1516
+ }
1517
+ }
1518
+ }
1519
+ origin.x = box.x + x;
1520
+ origin.y = box.y + y;
1521
+ translate(transform, origin.x, origin.y);
1522
+ if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1523
+ }
1524
+ data.transform = transform;
1527
1525
  }
1528
1526
 
1529
- function ignoreRender(ui, value) {
1530
- const {leafer: leafer} = ui;
1531
- if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1527
+ function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1528
+ if (rotation) rotate(transform, rotation);
1529
+ if (skew) skewHelper(transform, skew.x, skew.y);
1530
+ if (scaleX) scaleHelper(transform, scaleX, scaleY);
1531
+ translate(transform, box.x + x, box.y + y);
1532
1532
  }
1533
1533
 
1534
1534
  const {get: get$1, scale: scale, copy: copy$1} = MatrixHelper;
1535
1535
 
1536
- const {floor: floor, ceil: ceil, max: max$1, abs: abs$1} = Math;
1536
+ const {getFloorScale: getFloorScale} = MathHelper, {abs: abs$1} = Math;
1537
1537
 
1538
- function createPattern(ui, paint, pixelRatio) {
1539
- let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1540
- const id = scaleX + "-" + scaleY + "-" + pixelRatio;
1538
+ function createPatternTask(paint, ui, canvas, renderOptions) {
1539
+ if (!paint.patternTask) {
1540
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1541
+ paint.patternTask = null;
1542
+ if (canvas.bounds.hit(ui.__nowWorld)) PaintImage.createPattern(paint, ui, canvas, renderOptions);
1543
+ ui.forceUpdate("surface");
1544
+ }), 300);
1545
+ }
1546
+ }
1547
+
1548
+ function createPattern(paint, ui, canvas, renderOptions) {
1549
+ let {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions), id = scaleX + "-" + scaleY;
1541
1550
  if (paint.patternId !== id && !ui.destroyed) {
1542
- const {image: image, data: data} = paint;
1543
- let imageScale, imageMatrix, {width: width, height: height, scaleX: sx, scaleY: sy, transform: transform, repeat: repeat, gap: gap} = data;
1544
- scaleX *= pixelRatio;
1545
- scaleY *= pixelRatio;
1546
- if (sx) {
1547
- sx = abs$1(sx);
1548
- sy = abs$1(sy);
1549
- imageMatrix = get$1();
1550
- copy$1(imageMatrix, transform);
1551
- scale(imageMatrix, 1 / sx, 1 / sy);
1552
- scaleX *= sx;
1553
- scaleY *= sy;
1554
- }
1555
- width *= scaleX;
1556
- height *= scaleY;
1557
- const size = width * height;
1558
- if (!repeat) {
1559
- if (size > Platform.image.maxCacheSize) return false;
1560
- }
1561
- let maxSize = Platform.image.maxPatternSize;
1562
- if (image.isSVG) {
1563
- const ws = width / image.width;
1564
- if (ws > 1) imageScale = ws / ceil(ws);
1565
- } else {
1566
- const imageSize = image.width * image.height;
1567
- if (maxSize > imageSize) maxSize = imageSize;
1568
- }
1569
- if (size > maxSize) imageScale = Math.sqrt(size / maxSize);
1570
- if (imageScale) {
1571
- scaleX /= imageScale;
1572
- scaleY /= imageScale;
1573
- width /= imageScale;
1574
- height /= imageScale;
1575
- }
1576
- if (sx) {
1577
- scaleX /= sx;
1578
- scaleY /= sy;
1579
- }
1580
- const xGap = gap && gap.x * scaleX;
1581
- const yGap = gap && gap.y * scaleY;
1582
- if (transform || scaleX !== 1 || scaleY !== 1) {
1583
- const canvasWidth = width + (xGap || 0);
1584
- const canvasHeight = height + (yGap || 0);
1585
- scaleX /= canvasWidth / max$1(floor(canvasWidth), 1);
1586
- scaleY /= canvasHeight / max$1(floor(canvasHeight), 1);
1587
- if (!imageMatrix) {
1551
+ if (!(Platform.image.isLarge(paint.image, scaleX, scaleY) && !paint.data.repeat)) {
1552
+ const {image: image, data: data} = paint, {transform: transform, gap: gap} = data, fixScale = PaintImage.getPatternFixScale(paint, scaleX, scaleY);
1553
+ let imageMatrix, xGap, yGap, {width: width, height: height} = image;
1554
+ if (fixScale) scaleX *= fixScale, scaleY *= fixScale;
1555
+ width *= scaleX;
1556
+ height *= scaleY;
1557
+ if (gap) {
1558
+ xGap = gap.x * scaleX / abs$1(data.scaleX || 1);
1559
+ yGap = gap.y * scaleY / abs$1(data.scaleY || 1);
1560
+ }
1561
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1562
+ scaleX *= getFloorScale(width + (xGap || 0));
1563
+ scaleY *= getFloorScale(height + (yGap || 0));
1588
1564
  imageMatrix = get$1();
1589
1565
  if (transform) copy$1(imageMatrix, transform);
1566
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1590
1567
  }
1591
- scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1568
+ const imageCanvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1569
+ const pattern = image.getPattern(imageCanvas, data.repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1570
+ paint.style = pattern;
1571
+ paint.patternId = id;
1592
1572
  }
1593
- const canvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1594
- const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1595
- paint.style = pattern;
1596
- paint.patternId = id;
1597
- return true;
1573
+ }
1574
+ }
1575
+
1576
+ function getPatternFixScale(paint, imageScaleX, imageScaleY) {
1577
+ const {image: image} = paint;
1578
+ let fixScale, maxSize = Platform.image.maxPatternSize, imageSize = image.width * image.height;
1579
+ if (image.isSVG) {
1580
+ if (imageScaleX > 1) fixScale = Math.ceil(imageScaleX) / imageScaleX;
1598
1581
  } else {
1599
- return false;
1582
+ if (maxSize > imageSize) maxSize = imageSize;
1600
1583
  }
1584
+ if ((imageSize *= imageScaleX * imageScaleY) > maxSize) fixScale = Math.sqrt(maxSize / imageSize);
1585
+ return fixScale;
1601
1586
  }
1602
1587
 
1603
- function checkImage(ui, canvas, paint, allowDraw) {
1604
- const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1605
- const {pixelRatio: pixelRatio} = canvas, {data: data} = paint;
1606
- if (!data || paint.patternId === scaleX + "-" + scaleY + "-" + pixelRatio && !Export.running) {
1588
+ function checkImage(paint, drawImage, ui, canvas, renderOptions) {
1589
+ const {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions);
1590
+ const {image: image, data: data} = paint, {exporting: exporting} = renderOptions;
1591
+ if (!data || paint.patternId === scaleX + "-" + scaleY && !exporting) {
1607
1592
  return false;
1608
1593
  } else {
1609
- if (allowDraw) {
1594
+ if (drawImage) {
1610
1595
  if (data.repeat) {
1611
- allowDraw = false;
1612
- } else if (!(paint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || Export.running)) {
1613
- let {width: width, height: height} = data;
1614
- width *= scaleX * pixelRatio;
1615
- height *= scaleY * pixelRatio;
1616
- if (data.scaleX) {
1617
- width *= data.scaleX;
1618
- height *= data.scaleY;
1619
- }
1620
- allowDraw = width * height > Platform.image.maxCacheSize;
1596
+ drawImage = false;
1597
+ } else if (!(paint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || exporting)) {
1598
+ drawImage = Platform.image.isLarge(image, scaleX, scaleY);
1621
1599
  }
1622
1600
  }
1623
- if (allowDraw) {
1601
+ if (drawImage) {
1624
1602
  if (ui.__.__isFastShadow) {
1625
1603
  canvas.fillStyle = paint.style || "#000";
1626
1604
  canvas.fill();
1627
1605
  }
1628
- drawImage(ui, canvas, paint, data);
1606
+ PaintImage.drawImage(paint, scaleX, scaleY, ui, canvas, renderOptions);
1629
1607
  return true;
1630
1608
  } else {
1631
- if (!paint.style || paint.sync || Export.running) {
1632
- createPattern(ui, paint, pixelRatio);
1633
- } else {
1634
- if (!paint.patternTask) {
1635
- paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1636
- paint.patternTask = null;
1637
- if (canvas.bounds.hit(ui.__nowWorld)) createPattern(ui, paint, pixelRatio);
1638
- ui.forceUpdate("surface");
1639
- }), 300);
1640
- }
1641
- }
1609
+ if (!paint.style || paint.sync || exporting) PaintImage.createPattern(paint, ui, canvas, renderOptions); else PaintImage.createPatternTask(paint, ui, canvas, renderOptions);
1642
1610
  return false;
1643
1611
  }
1644
1612
  }
1645
1613
  }
1646
1614
 
1647
- function drawImage(ui, canvas, paint, data) {
1648
- canvas.save();
1649
- canvas.clipUI(ui);
1650
- if (paint.blendMode) canvas.blendMode = paint.blendMode;
1651
- if (data.opacity) canvas.opacity *= data.opacity;
1652
- if (data.transform) canvas.transform(data.transform);
1653
- canvas.drawImage(paint.image.getFull(data.filters), 0, 0, data.width, data.height);
1654
- canvas.restore();
1615
+ function drawImage(paint, _imageScaleX, _imageScaleY, ui, canvas, _renderOptions) {
1616
+ const {data: data, image: image, blendMode: blendMode} = paint, {opacity: opacity, transform: transform} = data, view = image.getFull(data.filters), u = ui.__;
1617
+ let {width: width, height: height} = image, clipUI;
1618
+ if (transform && !transform.onlyScale || (clipUI = u.path || u.cornerRadius) || opacity || blendMode) {
1619
+ canvas.save();
1620
+ clipUI && canvas.clipUI(ui);
1621
+ blendMode && (canvas.blendMode = blendMode);
1622
+ opacity && (canvas.opacity *= opacity);
1623
+ transform && canvas.transform(transform);
1624
+ canvas.drawImage(view, 0, 0, width, height);
1625
+ canvas.restore();
1626
+ } else {
1627
+ if (data.scaleX) width *= data.scaleX, height *= data.scaleY;
1628
+ canvas.drawImage(view, 0, 0, width, height);
1629
+ }
1630
+ }
1631
+
1632
+ function getImageRenderScaleData(paint, ui, canvas, _renderOptions) {
1633
+ const scaleData = ui.getRenderScaleData(true, paint.scaleFixed), {data: data} = paint;
1634
+ if (canvas) {
1635
+ const {pixelRatio: pixelRatio} = canvas;
1636
+ scaleData.scaleX *= pixelRatio;
1637
+ scaleData.scaleY *= pixelRatio;
1638
+ }
1639
+ if (data && data.scaleX) {
1640
+ scaleData.scaleX *= Math.abs(data.scaleX);
1641
+ scaleData.scaleY *= Math.abs(data.scaleY);
1642
+ }
1643
+ return scaleData;
1655
1644
  }
1656
1645
 
1657
1646
  function recycleImage(attrName, data) {
@@ -1683,8 +1672,12 @@ function recycleImage(attrName, data) {
1683
1672
  const PaintImageModule = {
1684
1673
  image: image,
1685
1674
  checkImage: checkImage,
1686
- createPattern: createPattern,
1675
+ drawImage: drawImage,
1676
+ getImageRenderScaleData: getImageRenderScaleData,
1687
1677
  recycleImage: recycleImage,
1678
+ createPatternTask: createPatternTask,
1679
+ createPattern: createPattern,
1680
+ getPatternFixScale: getPatternFixScale,
1688
1681
  createData: createData,
1689
1682
  getPatternData: getPatternData,
1690
1683
  stretchMode: stretchMode,
@@ -2140,10 +2133,8 @@ function createRows(drawData, content, style) {
2140
2133
  bounds = drawData.bounds;
2141
2134
  findMaxWidth = !bounds.width && !style.autoSizeAlign;
2142
2135
  const {__letterSpacing: __letterSpacing, paraIndent: paraIndent, textCase: textCase} = style;
2143
- const {canvas: canvas} = Platform;
2144
- const {width: width, height: height} = bounds;
2145
- const charMode = width || height || __letterSpacing || textCase !== "none";
2146
- if (charMode) {
2136
+ const {canvas: canvas} = Platform, {width: width} = bounds;
2137
+ if (style.__isCharMode) {
2147
2138
  const wrap = style.textWrap !== "none";
2148
2139
  const breakAll = style.textWrap === "break";
2149
2140
  paraStart = true;
@@ -2272,12 +2263,19 @@ const TextMode = 2;
2272
2263
  function layoutChar(drawData, style, width, _height) {
2273
2264
  const {rows: rows} = drawData;
2274
2265
  const {textAlign: textAlign, paraIndent: paraIndent, letterSpacing: letterSpacing} = style;
2275
- let charX, addWordWidth, indentWidth, mode, wordChar, wordsLength;
2266
+ const justifyLast = width && textAlign.includes("both");
2267
+ const justify = justifyLast || width && textAlign.includes("justify");
2268
+ const justifyLetter = justify && textAlign.includes("letter");
2269
+ let charX, remainingWidth, addWordWidth, addLetterWidth, indentWidth, mode, wordChar, wordsLength, isLastWord, canJustify;
2276
2270
  rows.forEach(row => {
2277
2271
  if (row.words) {
2278
2272
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0, wordsLength = row.words.length;
2279
- addWordWidth = width && (textAlign === "justify" || textAlign === "both") && wordsLength > 1 ? (width - row.width - indentWidth) / (wordsLength - 1) : 0;
2280
- mode = letterSpacing || row.isOverflow ? CharMode : addWordWidth > .01 ? WordMode : TextMode;
2273
+ if (justify) {
2274
+ canJustify = !row.paraEnd || justifyLast;
2275
+ remainingWidth = width - row.width - indentWidth;
2276
+ if (justifyLetter) addLetterWidth = remainingWidth / (row.words.reduce((total, item) => total + item.data.length, 0) - 1); else addWordWidth = wordsLength > 1 ? remainingWidth / (wordsLength - 1) : 0;
2277
+ }
2278
+ mode = letterSpacing || row.isOverflow || justifyLetter ? CharMode : addWordWidth ? WordMode : TextMode;
2281
2279
  if (row.isOverflow && !letterSpacing) row.textMode = true;
2282
2280
  if (mode === TextMode) {
2283
2281
  row.x += indentWidth;
@@ -2295,11 +2293,15 @@ function layoutChar(drawData, style, width, _height) {
2295
2293
  charX = toWordChar(word.data, charX, wordChar);
2296
2294
  if (row.isOverflow || wordChar.char !== " ") row.data.push(wordChar);
2297
2295
  } else {
2298
- charX = toChar(word.data, charX, row.data, row.isOverflow);
2296
+ charX = toChar(word.data, charX, row.data, row.isOverflow, canJustify && addLetterWidth);
2299
2297
  }
2300
- if (addWordWidth && (!row.paraEnd || textAlign === "both") && index !== wordsLength - 1) {
2301
- charX += addWordWidth;
2302
- row.width += addWordWidth;
2298
+ if (canJustify) {
2299
+ isLastWord = index === wordsLength - 1;
2300
+ if (addWordWidth) {
2301
+ if (!isLastWord) charX += addWordWidth, row.width += addWordWidth;
2302
+ } else if (addLetterWidth) {
2303
+ row.width += addLetterWidth * (word.data.length - (isLastWord ? 1 : 0));
2304
+ }
2303
2305
  }
2304
2306
  });
2305
2307
  }
@@ -2325,13 +2327,14 @@ function toWordChar(data, charX, wordChar) {
2325
2327
  return charX;
2326
2328
  }
2327
2329
 
2328
- function toChar(data, charX, rowData, isOverflow) {
2330
+ function toChar(data, charX, rowData, isOverflow, addLetterWidth) {
2329
2331
  data.forEach(char => {
2330
2332
  if (isOverflow || char.char !== " ") {
2331
2333
  char.x = charX;
2332
2334
  rowData.push(char);
2333
2335
  }
2334
2336
  charX += char.width;
2337
+ addLetterWidth && (charX += addLetterWidth);
2335
2338
  });
2336
2339
  return charX;
2337
2340
  }
@@ -2473,10 +2476,10 @@ function getDrawData(content, style) {
2473
2476
  let x = 0, y = 0;
2474
2477
  let width = style.__getInput("width") || 0;
2475
2478
  let height = style.__getInput("height") || 0;
2476
- const {textDecoration: textDecoration, __font: __font, __padding: padding} = style;
2479
+ const {__padding: padding} = style;
2477
2480
  if (padding) {
2478
- if (width) x = padding[left], width -= padding[right] + padding[left]; else if (!style.autoSizeAlign) x = padding[left];
2479
- if (height) y = padding[top], height -= padding[top] + padding[bottom]; else if (!style.autoSizeAlign) y = padding[top];
2481
+ if (width) x = padding[left], width -= padding[right] + padding[left], !width && (width = .01); else if (!style.autoSizeAlign) x = padding[left];
2482
+ if (height) y = padding[top], height -= padding[top] + padding[bottom], !height && (height = .01); else if (!style.autoSizeAlign) y = padding[top];
2480
2483
  }
2481
2484
  const drawData = {
2482
2485
  bounds: {
@@ -2487,14 +2490,14 @@ function getDrawData(content, style) {
2487
2490
  },
2488
2491
  rows: [],
2489
2492
  paraNumber: 0,
2490
- font: Platform.canvas.font = __font
2493
+ font: Platform.canvas.font = style.__font
2491
2494
  };
2492
2495
  createRows(drawData, content, style);
2493
2496
  if (padding) padAutoText(padding, drawData, style, width, height);
2494
2497
  layoutText(drawData, style);
2495
- layoutChar(drawData, style, width);
2498
+ if (style.__isCharMode) layoutChar(drawData, style, width);
2496
2499
  if (drawData.overflow) clipText(drawData, style, x, width);
2497
- if (textDecoration !== "none") decorationText(drawData, style);
2500
+ if (style.textDecoration !== "none") decorationText(drawData, style);
2498
2501
  return drawData;
2499
2502
  }
2500
2503