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