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