@leafer-ui/miniapp 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, 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, BoundsHelper, Plugin, isObject, 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, BoundsHelper, Plugin, isObject, FourNumberHelper, Matrix, ImageEvent, MatrixHelper, MathHelper, AlignHelper, PointHelper, getMatrixData, AroundHelper, Direction4 } from "@leafer/core";
2
2
 
3
3
  export * from "@leafer/core";
4
4
 
@@ -8,7 +8,7 @@ import { InteractionHelper, InteractionBase, isUndefined as isUndefined$1, HitCa
8
8
 
9
9
  export * from "@leafer-ui/core";
10
10
 
11
- import { PaintImage, Paint, ColorConvert, PaintGradient, Export, Effect, Group, TextConvert, Leafer } from "@leafer-ui/draw";
11
+ import { Paint, PaintImage, ColorConvert, PaintGradient, Effect, Group, TextConvert, Leafer } from "@leafer-ui/draw";
12
12
 
13
13
  class LeaferCanvas extends LeaferCanvasBase {
14
14
  get allowBackgroundColor() {
@@ -936,6 +936,7 @@ class Picker {
936
936
  hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
937
937
  if (child.isBranch) {
938
938
  if (hit || child.__ignoreHitWorld) {
939
+ if (child.isBranchLeaf && child.__.__clipAfterFill && !child.__hitWorld(point)) continue;
939
940
  if (child.topChildren) this.eachFind(child.topChildren, false);
940
941
  this.eachFind(child.children, child.__onlyHitMask);
941
942
  if (child.isBranchLeaf) this.hitChild(child, point);
@@ -1128,36 +1129,19 @@ class Interaction extends InteractionBase {
1128
1129
  }
1129
1130
  }
1130
1131
 
1131
- function fillText(ui, canvas) {
1132
- const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
1133
- if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
1134
- let row;
1135
- for (let i = 0, len = rows.length; i < len; i++) {
1136
- row = rows[i];
1137
- if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
1138
- canvas.fillText(charData.char, charData.x, row.y);
1139
- });
1140
- }
1141
- if (decorationY) {
1142
- const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
1143
- if (decorationColor) canvas.fillStyle = decorationColor;
1144
- rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
1145
- }
1146
- }
1147
-
1148
- function fill(fill, ui, canvas) {
1132
+ function fill(fill, ui, canvas, renderOptions) {
1149
1133
  canvas.fillStyle = fill;
1150
- fillPathOrText(ui, canvas);
1134
+ fillPathOrText(ui, canvas, renderOptions);
1151
1135
  }
1152
1136
 
1153
- function fills(fills, ui, canvas) {
1137
+ function fills(fills, ui, canvas, renderOptions) {
1154
1138
  let item;
1155
1139
  for (let i = 0, len = fills.length; i < len; i++) {
1156
1140
  item = fills[i];
1157
1141
  if (item.image) {
1158
- if (PaintImage.checkImage(ui, canvas, item, !ui.__.__font)) continue;
1142
+ if (PaintImage.checkImage(item, !ui.__.__font, ui, canvas, renderOptions)) continue;
1159
1143
  if (!item.style) {
1160
- if (!i && item.image.isPlacehold) ui.drawImagePlaceholder(canvas, item.image);
1144
+ if (!i && item.image.isPlacehold) ui.drawImagePlaceholder(item.image, canvas, renderOptions);
1161
1145
  continue;
1162
1146
  }
1163
1147
  }
@@ -1170,60 +1154,137 @@ function fills(fills, ui, canvas) {
1170
1154
  if (item.scaleFixed === true || item.scaleFixed === "zoom-in" && scaleX > 1 && scaleY > 1) canvas.scale(1 / scaleX, 1 / scaleY);
1171
1155
  }
1172
1156
  if (item.blendMode) canvas.blendMode = item.blendMode;
1173
- fillPathOrText(ui, canvas);
1157
+ fillPathOrText(ui, canvas, renderOptions);
1174
1158
  canvas.restore();
1175
1159
  } else {
1176
1160
  if (item.blendMode) {
1177
1161
  canvas.saveBlendMode(item.blendMode);
1178
- fillPathOrText(ui, canvas);
1162
+ fillPathOrText(ui, canvas, renderOptions);
1179
1163
  canvas.restoreBlendMode();
1180
- } else fillPathOrText(ui, canvas);
1164
+ } else fillPathOrText(ui, canvas, renderOptions);
1165
+ }
1166
+ }
1167
+ }
1168
+
1169
+ function fillPathOrText(ui, canvas, renderOptions) {
1170
+ ui.__.__font ? Paint.fillText(ui, canvas, renderOptions) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
1171
+ }
1172
+
1173
+ function fillText(ui, canvas, _renderOptions) {
1174
+ const data = ui.__, {rows: rows, decorationY: decorationY} = data.__textDrawData;
1175
+ if (data.__isPlacehold && data.placeholderColor) canvas.fillStyle = data.placeholderColor;
1176
+ let row;
1177
+ for (let i = 0, len = rows.length; i < len; i++) {
1178
+ row = rows[i];
1179
+ if (row.text) canvas.fillText(row.text, row.x, row.y); else if (row.data) row.data.forEach(charData => {
1180
+ canvas.fillText(charData.char, charData.x, row.y);
1181
+ });
1182
+ }
1183
+ if (decorationY) {
1184
+ const {decorationColor: decorationColor, decorationHeight: decorationHeight} = data.__textDrawData;
1185
+ if (decorationColor) canvas.fillStyle = decorationColor;
1186
+ rows.forEach(row => decorationY.forEach(value => canvas.fillRect(row.x, row.y + value, row.width, decorationHeight)));
1187
+ }
1188
+ }
1189
+
1190
+ function stroke(stroke, ui, canvas, renderOptions) {
1191
+ const data = ui.__;
1192
+ if (!data.__strokeWidth) return;
1193
+ if (data.__font) {
1194
+ Paint.strokeText(stroke, ui, canvas, renderOptions);
1195
+ } else {
1196
+ switch (data.strokeAlign) {
1197
+ case "center":
1198
+ drawCenter$1(stroke, 1, ui, canvas, renderOptions);
1199
+ break;
1200
+
1201
+ case "inside":
1202
+ drawInside(stroke, ui, canvas, renderOptions);
1203
+ break;
1204
+
1205
+ case "outside":
1206
+ drawOutside(stroke, ui, canvas, renderOptions);
1207
+ break;
1181
1208
  }
1182
1209
  }
1183
1210
  }
1184
1211
 
1185
- function fillPathOrText(ui, canvas) {
1186
- ui.__.__font ? fillText(ui, canvas) : ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill();
1212
+ function strokes(strokes, ui, canvas, renderOptions) {
1213
+ Paint.stroke(strokes, ui, canvas, renderOptions);
1214
+ }
1215
+
1216
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas, renderOptions) {
1217
+ const data = ui.__;
1218
+ if (isObject(stroke)) {
1219
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas, renderOptions);
1220
+ } else {
1221
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1222
+ canvas.stroke();
1223
+ }
1224
+ if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas, renderOptions);
1225
+ }
1226
+
1227
+ function drawInside(stroke, ui, canvas, renderOptions) {
1228
+ canvas.save();
1229
+ canvas.clipUI(ui);
1230
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
1231
+ canvas.restore();
1187
1232
  }
1188
1233
 
1189
- function strokeText(stroke, ui, canvas) {
1234
+ function drawOutside(stroke, ui, canvas, renderOptions) {
1235
+ const data = ui.__;
1236
+ if (data.__fillAfterStroke) {
1237
+ drawCenter$1(stroke, 2, ui, canvas, renderOptions);
1238
+ } else {
1239
+ const {renderBounds: renderBounds} = ui.__layout;
1240
+ const out = canvas.getSameCanvas(true, true);
1241
+ ui.__drawRenderPath(out);
1242
+ drawCenter$1(stroke, 2, ui, out, renderOptions);
1243
+ out.clipUI(data);
1244
+ out.clearWorld(renderBounds);
1245
+ LeafHelper.copyCanvasByWorld(ui, canvas, out);
1246
+ out.recycle(ui.__nowWorld);
1247
+ }
1248
+ }
1249
+
1250
+ function strokeText(stroke, ui, canvas, renderOptions) {
1190
1251
  switch (ui.__.strokeAlign) {
1191
1252
  case "center":
1192
- drawCenter$1(stroke, 1, ui, canvas);
1253
+ drawCenter(stroke, 1, ui, canvas, renderOptions);
1193
1254
  break;
1194
1255
 
1195
1256
  case "inside":
1196
- drawAlign(stroke, "inside", ui, canvas);
1257
+ drawAlign(stroke, "inside", ui, canvas, renderOptions);
1197
1258
  break;
1198
1259
 
1199
1260
  case "outside":
1200
- ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, "outside", ui, canvas);
1261
+ ui.__.__fillAfterStroke ? drawCenter(stroke, 2, ui, canvas, renderOptions) : drawAlign(stroke, "outside", ui, canvas, renderOptions);
1201
1262
  break;
1202
1263
  }
1203
1264
  }
1204
1265
 
1205
- function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1266
+ function drawCenter(stroke, strokeWidthScale, ui, canvas, renderOptions) {
1206
1267
  const data = ui.__;
1207
1268
  if (isObject(stroke)) {
1208
- drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas);
1269
+ Paint.drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas, renderOptions);
1209
1270
  } else {
1210
1271
  canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1211
- drawTextStroke(ui, canvas);
1272
+ Paint.drawTextStroke(ui, canvas, renderOptions);
1212
1273
  }
1213
1274
  }
1214
1275
 
1215
- function drawAlign(stroke, align, ui, canvas) {
1276
+ function drawAlign(stroke, align, ui, canvas, renderOptions) {
1216
1277
  const out = canvas.getSameCanvas(true, true);
1217
1278
  out.font = ui.__.__font;
1218
- drawCenter$1(stroke, 2, ui, out);
1279
+ drawCenter(stroke, 2, ui, out, renderOptions);
1219
1280
  out.blendMode = align === "outside" ? "destination-out" : "destination-in";
1220
- fillText(ui, out);
1281
+ Paint.fillText(ui, out, renderOptions);
1221
1282
  out.blendMode = "normal";
1222
1283
  LeafHelper.copyCanvasByWorld(ui, canvas, out);
1223
1284
  out.recycle(ui.__nowWorld);
1224
1285
  }
1225
1286
 
1226
- function drawTextStroke(ui, canvas) {
1287
+ function drawTextStroke(ui, canvas, _renderOptions) {
1227
1288
  let row, data = ui.__.__textDrawData;
1228
1289
  const {rows: rows, decorationY: decorationY} = data;
1229
1290
  for (let i = 0, len = rows.length; i < len; i++) {
@@ -1238,13 +1299,13 @@ function drawTextStroke(ui, canvas) {
1238
1299
  }
1239
1300
  }
1240
1301
 
1241
- function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
1302
+ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas, renderOptions) {
1242
1303
  let item;
1243
1304
  const data = ui.__, {__hasMultiStrokeStyle: __hasMultiStrokeStyle} = data;
1244
1305
  __hasMultiStrokeStyle || canvas.setStroke(undefined, data.__strokeWidth * strokeWidthScale, data);
1245
1306
  for (let i = 0, len = strokes.length; i < len; i++) {
1246
1307
  item = strokes[i];
1247
- if (item.image && PaintImage.checkImage(ui, canvas, item, false)) continue;
1308
+ if (item.image && PaintImage.checkImage(item, false, ui, canvas, renderOptions)) continue;
1248
1309
  if (item.style) {
1249
1310
  if (__hasMultiStrokeStyle) {
1250
1311
  const {strokeStyle: strokeStyle} = item;
@@ -1252,75 +1313,15 @@ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
1252
1313
  } else canvas.strokeStyle = item.style;
1253
1314
  if (item.blendMode) {
1254
1315
  canvas.saveBlendMode(item.blendMode);
1255
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1316
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
1256
1317
  canvas.restoreBlendMode();
1257
1318
  } else {
1258
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1319
+ isText ? Paint.drawTextStroke(ui, canvas, renderOptions) : canvas.stroke();
1259
1320
  }
1260
1321
  }
1261
1322
  }
1262
1323
  }
1263
1324
 
1264
- function stroke(stroke, ui, canvas) {
1265
- const data = ui.__;
1266
- if (!data.__strokeWidth) return;
1267
- if (data.__font) {
1268
- strokeText(stroke, ui, canvas);
1269
- } else {
1270
- switch (data.strokeAlign) {
1271
- case "center":
1272
- drawCenter(stroke, 1, ui, canvas);
1273
- break;
1274
-
1275
- case "inside":
1276
- drawInside(stroke, ui, canvas);
1277
- break;
1278
-
1279
- case "outside":
1280
- drawOutside(stroke, ui, canvas);
1281
- break;
1282
- }
1283
- }
1284
- }
1285
-
1286
- function strokes(strokes, ui, canvas) {
1287
- stroke(strokes, ui, canvas);
1288
- }
1289
-
1290
- function drawCenter(stroke, strokeWidthScale, ui, canvas) {
1291
- const data = ui.__;
1292
- if (isObject(stroke)) {
1293
- drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas);
1294
- } else {
1295
- canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1296
- canvas.stroke();
1297
- }
1298
- if (data.__useArrow) Paint.strokeArrow(stroke, ui, canvas);
1299
- }
1300
-
1301
- function drawInside(stroke, ui, canvas) {
1302
- canvas.save();
1303
- canvas.clipUI(ui);
1304
- drawCenter(stroke, 2, ui, canvas);
1305
- canvas.restore();
1306
- }
1307
-
1308
- function drawOutside(stroke, ui, canvas) {
1309
- const data = ui.__;
1310
- if (data.__fillAfterStroke) {
1311
- drawCenter(stroke, 2, ui, canvas);
1312
- } else {
1313
- const {renderBounds: renderBounds} = ui.__layout;
1314
- const out = canvas.getSameCanvas(true, true);
1315
- ui.__drawRenderPath(out);
1316
- drawCenter(stroke, 2, ui, out);
1317
- out.clipUI(data);
1318
- out.clearWorld(renderBounds);
1319
- LeafHelper.copyCanvasByWorld(ui, canvas, out);
1320
- out.recycle(ui.__nowWorld);
1321
- }
1322
- }
1323
-
1324
1325
  const {getSpread: getSpread, copyAndSpread: copyAndSpread, toOuterOf: toOuterOf, getOuterOf: getOuterOf, getByMove: getByMove, move: move$1, getIntersectData: getIntersectData} = BoundsHelper;
1325
1326
 
1326
1327
  const tempBounds$1 = {};
@@ -1476,88 +1477,118 @@ const PaintModule = {
1476
1477
  strokes: strokes,
1477
1478
  strokeText: strokeText,
1478
1479
  drawTextStroke: drawTextStroke,
1480
+ drawStrokesStyle: drawStrokesStyle,
1479
1481
  shape: shape
1480
1482
  };
1481
1483
 
1482
- let origin = {}, tempMatrix$1 = getMatrixData();
1484
+ let cache, box = new Bounds;
1483
1485
 
1484
- const {get: get$3, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1486
+ const {isSame: isSame} = BoundsHelper;
1485
1487
 
1486
- function stretchMode(data, box, scaleX, scaleY) {
1487
- const transform = get$3();
1488
- translate$1(transform, box.x, box.y);
1489
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1490
- data.transform = transform;
1488
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1489
+ let leafPaint, event;
1490
+ const image = ImageManager.get(paint);
1491
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1492
+ leafPaint = cache.leafPaint;
1493
+ } else {
1494
+ leafPaint = {
1495
+ type: paint.type,
1496
+ image: image
1497
+ };
1498
+ if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1499
+ cache = image.use > 1 ? {
1500
+ leafPaint: leafPaint,
1501
+ paint: paint,
1502
+ boxBounds: box.set(boxBounds)
1503
+ } : null;
1504
+ }
1505
+ if (firstUse || image.loading) event = {
1506
+ image: image,
1507
+ attrName: attrName,
1508
+ attrValue: paint
1509
+ };
1510
+ if (image.ready) {
1511
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1512
+ if (firstUse) {
1513
+ onLoad(ui, event);
1514
+ onLoadSuccess(ui, event);
1515
+ }
1516
+ } else if (image.error) {
1517
+ if (firstUse) onLoadError(ui, event, image.error);
1518
+ } else {
1519
+ if (firstUse) {
1520
+ ignoreRender(ui, true);
1521
+ onLoad(ui, event);
1522
+ }
1523
+ leafPaint.loadId = image.load(() => {
1524
+ ignoreRender(ui, false);
1525
+ if (!ui.destroyed) {
1526
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1527
+ if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1528
+ ui.forceUpdate("surface");
1529
+ }
1530
+ onLoadSuccess(ui, event);
1531
+ }
1532
+ leafPaint.loadId = undefined;
1533
+ }, error => {
1534
+ ignoreRender(ui, false);
1535
+ onLoadError(ui, event, error);
1536
+ leafPaint.loadId = undefined;
1537
+ });
1538
+ if (ui.placeholderColor) {
1539
+ if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1540
+ if (!image.ready) {
1541
+ image.isPlacehold = true;
1542
+ ui.forceUpdate("surface");
1543
+ }
1544
+ }, ui.placeholderDelay);
1545
+ }
1546
+ }
1547
+ return leafPaint;
1491
1548
  }
1492
1549
 
1493
- function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1494
- const transform = get$3();
1495
- translate$1(transform, box.x + x, box.y + y);
1496
- scaleHelper(transform, scaleX, scaleY);
1497
- if (rotation) rotateOfOuter$1(transform, {
1498
- x: box.x + box.width / 2,
1499
- y: box.y + box.height / 2
1500
- }, rotation);
1501
- data.transform = transform;
1550
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1551
+ if (attrName === "fill" && !ui.__.__naturalWidth) {
1552
+ const data = ui.__;
1553
+ data.__naturalWidth = image.width / data.pixelRatio;
1554
+ data.__naturalHeight = image.height / data.pixelRatio;
1555
+ if (data.__autoSide) {
1556
+ ui.forceUpdate("width");
1557
+ if (ui.__proxyData) {
1558
+ ui.setProxyAttr("width", data.width);
1559
+ ui.setProxyAttr("height", data.height);
1560
+ }
1561
+ return false;
1562
+ }
1563
+ }
1564
+ if (!leafPaint.data) PaintImage.createData(leafPaint, image, paint, boxBounds);
1565
+ return true;
1502
1566
  }
1503
1567
 
1504
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1505
- const transform = get$3();
1506
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1507
- if (clipScaleX) {
1508
- if (rotation || skew) {
1509
- set(tempMatrix$1);
1510
- scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1511
- multiplyParent(transform, tempMatrix$1);
1512
- } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1513
- }
1514
- data.transform = transform;
1568
+ function onLoad(ui, event) {
1569
+ emit(ui, ImageEvent.LOAD, event);
1515
1570
  }
1516
1571
 
1517
- function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1518
- const transform = get$3();
1519
- if (freeTransform) {
1520
- layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1521
- } else {
1522
- if (rotation) {
1523
- if (align === "center") {
1524
- rotateOfOuter$1(transform, {
1525
- x: width / 2,
1526
- y: height / 2
1527
- }, rotation);
1528
- } else {
1529
- rotate(transform, rotation);
1530
- switch (rotation) {
1531
- case 90:
1532
- translate$1(transform, height, 0);
1533
- break;
1572
+ function onLoadSuccess(ui, event) {
1573
+ emit(ui, ImageEvent.LOADED, event);
1574
+ }
1534
1575
 
1535
- case 180:
1536
- translate$1(transform, width, height);
1537
- break;
1576
+ function onLoadError(ui, event, error) {
1577
+ event.error = error;
1578
+ ui.forceUpdate("surface");
1579
+ emit(ui, ImageEvent.ERROR, event);
1580
+ }
1538
1581
 
1539
- case 270:
1540
- translate$1(transform, 0, width);
1541
- break;
1542
- }
1543
- }
1544
- }
1545
- origin.x = box.x + x;
1546
- origin.y = box.y + y;
1547
- translate$1(transform, origin.x, origin.y);
1548
- if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1549
- }
1550
- data.transform = transform;
1582
+ function emit(ui, type, data) {
1583
+ if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1551
1584
  }
1552
1585
 
1553
- function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1554
- if (rotation) rotate(transform, rotation);
1555
- if (skew) skewHelper(transform, skew.x, skew.y);
1556
- if (scaleX) scaleHelper(transform, scaleX, scaleY);
1557
- translate$1(transform, box.x + x, box.y + y);
1586
+ function ignoreRender(ui, value) {
1587
+ const {leafer: leafer} = ui;
1588
+ if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1558
1589
  }
1559
1590
 
1560
- const {get: get$2, translate: translate} = MatrixHelper;
1591
+ const {get: get$3, translate: translate$1} = MatrixHelper;
1561
1592
 
1562
1593
  const tempBox = new Bounds;
1563
1594
 
@@ -1570,13 +1601,13 @@ function createData(leafPaint, image, paint, box) {
1570
1601
  if (changeful) leafPaint.changeful = changeful;
1571
1602
  if (sync) leafPaint.sync = sync;
1572
1603
  if (scaleFixed) leafPaint.scaleFixed = scaleFixed;
1573
- leafPaint.data = getPatternData(paint, box, image);
1604
+ leafPaint.data = PaintImage.getPatternData(paint, box, image);
1574
1605
  }
1575
1606
 
1576
1607
  function getPatternData(paint, box, image) {
1577
1608
  if (paint.padding) box = tempBox.set(box).shrink(paint.padding);
1578
1609
  if (paint.mode === "strench") paint.mode = "stretch";
1579
- let {width: width, height: height} = image;
1610
+ const {width: width, height: height} = image;
1580
1611
  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;
1581
1612
  const sameBox = box.width === width && box.height === height;
1582
1613
  const data = {
@@ -1607,8 +1638,8 @@ function getPatternData(paint, box, image) {
1607
1638
  case "stretch":
1608
1639
  if (!sameBox) {
1609
1640
  scaleX = box.width / width, scaleY = box.height / height;
1610
- stretchMode(data, box, scaleX, scaleY);
1611
- }
1641
+ PaintImage.stretchMode(data, box, scaleX, scaleY);
1642
+ } else if (scaleX) scaleX = scaleY = undefined;
1612
1643
  break;
1613
1644
 
1614
1645
  case "normal":
@@ -1616,13 +1647,13 @@ function getPatternData(paint, box, image) {
1616
1647
  if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) {
1617
1648
  let clipScaleX, clipScaleY;
1618
1649
  if (clipSize) clipScaleX = box.width / clipSize.width, clipScaleY = box.height / clipSize.height;
1619
- clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1650
+ PaintImage.clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1620
1651
  if (clipScaleX) scaleX = scaleX ? scaleX * clipScaleX : clipScaleX, scaleY = scaleY ? scaleY * clipScaleY : clipScaleY;
1621
1652
  }
1622
1653
  break;
1623
1654
 
1624
1655
  case "repeat":
1625
- if (!sameBox || scaleX || rotation || skew) repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1656
+ if (!sameBox || scaleX || rotation || skew) PaintImage.repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, align, paint.freeTransform);
1626
1657
  if (!repeat) data.repeat = "repeat";
1627
1658
  const count = isObject(repeat);
1628
1659
  if (gap || count) data.gap = getGapData(gap, count && repeat, tempImage.width, tempImage.height, box);
@@ -1631,18 +1662,16 @@ function getPatternData(paint, box, image) {
1631
1662
  case "fit":
1632
1663
  case "cover":
1633
1664
  default:
1634
- if (scaleX) fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1665
+ if (scaleX) PaintImage.fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1635
1666
  }
1636
1667
  if (!data.transform) {
1637
- if (box.x || box.y) translate(data.transform = get$2(), box.x, box.y);
1668
+ if (box.x || box.y) translate$1(data.transform = get$3(), box.x, box.y);
1638
1669
  }
1639
- data.width = width;
1640
- data.height = height;
1641
1670
  if (scaleX) {
1642
1671
  data.scaleX = scaleX;
1643
1672
  data.scaleY = scaleY;
1644
1673
  }
1645
- if (opacity) data.opacity = opacity;
1674
+ if (opacity && opacity < 1) data.opacity = opacity;
1646
1675
  if (filters) data.filters = filters;
1647
1676
  if (repeat) data.repeat = isString(repeat) ? repeat === "x" ? "repeat-x" : "repeat-y" : "repeat";
1648
1677
  return data;
@@ -1664,180 +1693,82 @@ function getGapValue(gap, size, totalSize, rows) {
1664
1693
  return gap === "auto" ? value < 0 ? 0 : value : value;
1665
1694
  }
1666
1695
 
1667
- let cache, box = new Bounds;
1668
-
1669
- const {isSame: isSame} = BoundsHelper;
1670
-
1671
- function image(ui, attrName, paint, boxBounds, firstUse) {
1672
- let leafPaint, event;
1673
- const image = ImageManager.get(paint);
1674
- if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1675
- leafPaint = cache.leafPaint;
1676
- } else {
1677
- leafPaint = {
1678
- type: paint.type,
1679
- image: image
1680
- };
1681
- if (image.hasAlphaPixel) leafPaint.isTransparent = true;
1682
- cache = image.use > 1 ? {
1683
- leafPaint: leafPaint,
1684
- paint: paint,
1685
- boxBounds: box.set(boxBounds)
1686
- } : null;
1687
- }
1688
- if (firstUse || image.loading) event = {
1689
- image: image,
1690
- attrName: attrName,
1691
- attrValue: paint
1692
- };
1693
- if (image.ready) {
1694
- checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1695
- if (firstUse) {
1696
- onLoad(ui, event);
1697
- onLoadSuccess(ui, event);
1698
- }
1699
- } else if (image.error) {
1700
- if (firstUse) onLoadError(ui, event, image.error);
1701
- } else {
1702
- if (firstUse) {
1703
- ignoreRender(ui, true);
1704
- onLoad(ui, event);
1705
- }
1706
- leafPaint.loadId = image.load(() => {
1707
- ignoreRender(ui, false);
1708
- if (!ui.destroyed) {
1709
- if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1710
- if (image.hasAlphaPixel) ui.__layout.hitCanvasChanged = true;
1711
- ui.forceUpdate("surface");
1712
- }
1713
- onLoadSuccess(ui, event);
1714
- }
1715
- leafPaint.loadId = undefined;
1716
- }, error => {
1717
- ignoreRender(ui, false);
1718
- onLoadError(ui, event, error);
1719
- leafPaint.loadId = undefined;
1720
- });
1721
- if (ui.placeholderColor) {
1722
- if (!ui.placeholderDelay) image.isPlacehold = true; else setTimeout(() => {
1723
- if (!image.ready) {
1724
- image.isPlacehold = true;
1725
- ui.forceUpdate("surface");
1726
- }
1727
- }, ui.placeholderDelay);
1728
- }
1729
- }
1730
- return leafPaint;
1731
- }
1732
-
1733
- function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1734
- if (attrName === "fill" && !ui.__.__naturalWidth) {
1735
- const data = ui.__;
1736
- data.__naturalWidth = image.width / data.pixelRatio;
1737
- data.__naturalHeight = image.height / data.pixelRatio;
1738
- if (data.__autoSide) {
1739
- ui.forceUpdate("width");
1740
- if (ui.__proxyData) {
1741
- ui.setProxyAttr("width", data.width);
1742
- ui.setProxyAttr("height", data.height);
1743
- }
1744
- return false;
1745
- }
1746
- }
1747
- if (!leafPaint.data) createData(leafPaint, image, paint, boxBounds);
1748
- return true;
1749
- }
1750
-
1751
- function onLoad(ui, event) {
1752
- emit(ui, ImageEvent.LOAD, event);
1753
- }
1696
+ let origin = {}, tempMatrix$1 = getMatrixData();
1754
1697
 
1755
- function onLoadSuccess(ui, event) {
1756
- emit(ui, ImageEvent.LOADED, event);
1757
- }
1698
+ const {get: get$2, set: set, rotateOfOuter: rotateOfOuter$1, translate: translate, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = MatrixHelper;
1758
1699
 
1759
- function onLoadError(ui, event, error) {
1760
- event.error = error;
1761
- ui.forceUpdate("surface");
1762
- emit(ui, ImageEvent.ERROR, event);
1700
+ function stretchMode(data, box, scaleX, scaleY) {
1701
+ const transform = get$2(), {x: x, y: y} = box;
1702
+ if (x || y) translate(transform, x, y); else transform.onlyScale = true;
1703
+ scaleHelper(transform, scaleX, scaleY);
1704
+ data.transform = transform;
1763
1705
  }
1764
1706
 
1765
- function emit(ui, type, data) {
1766
- if (ui.hasEvent(type)) ui.emitEvent(new ImageEvent(type, data));
1707
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1708
+ const transform = get$2();
1709
+ translate(transform, box.x + x, box.y + y);
1710
+ scaleHelper(transform, scaleX, scaleY);
1711
+ if (rotation) rotateOfOuter$1(transform, {
1712
+ x: box.x + box.width / 2,
1713
+ y: box.y + box.height / 2
1714
+ }, rotation);
1715
+ data.transform = transform;
1767
1716
  }
1768
1717
 
1769
- function ignoreRender(ui, value) {
1770
- const {leafer: leafer} = ui;
1771
- if (leafer && leafer.viewReady) leafer.renderer.ignore = value;
1718
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1719
+ const transform = get$2();
1720
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1721
+ if (clipScaleX) {
1722
+ if (rotation || skew) {
1723
+ set(tempMatrix$1);
1724
+ scaleOfOuter$1(tempMatrix$1, box, clipScaleX, clipScaleY);
1725
+ multiplyParent(transform, tempMatrix$1);
1726
+ } else scaleOfOuter$1(transform, box, clipScaleX, clipScaleY);
1727
+ }
1728
+ data.transform = transform;
1772
1729
  }
1773
1730
 
1774
- const {get: get$1, scale: scale, copy: copy$1} = MatrixHelper;
1731
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, skew, align, freeTransform) {
1732
+ const transform = get$2();
1733
+ if (freeTransform) {
1734
+ layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1735
+ } else {
1736
+ if (rotation) {
1737
+ if (align === "center") {
1738
+ rotateOfOuter$1(transform, {
1739
+ x: width / 2,
1740
+ y: height / 2
1741
+ }, rotation);
1742
+ } else {
1743
+ rotate(transform, rotation);
1744
+ switch (rotation) {
1745
+ case 90:
1746
+ translate(transform, height, 0);
1747
+ break;
1775
1748
 
1776
- const {floor: floor, ceil: ceil, max: max$1, abs: abs$1} = Math;
1749
+ case 180:
1750
+ translate(transform, width, height);
1751
+ break;
1777
1752
 
1778
- function createPattern(ui, paint, pixelRatio) {
1779
- let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1780
- const id = scaleX + "-" + scaleY + "-" + pixelRatio;
1781
- if (paint.patternId !== id && !ui.destroyed) {
1782
- const {image: image, data: data} = paint;
1783
- let imageScale, imageMatrix, {width: width, height: height, scaleX: sx, scaleY: sy, transform: transform, repeat: repeat, gap: gap} = data;
1784
- scaleX *= pixelRatio;
1785
- scaleY *= pixelRatio;
1786
- if (sx) {
1787
- sx = abs$1(sx);
1788
- sy = abs$1(sy);
1789
- imageMatrix = get$1();
1790
- copy$1(imageMatrix, transform);
1791
- scale(imageMatrix, 1 / sx, 1 / sy);
1792
- scaleX *= sx;
1793
- scaleY *= sy;
1794
- }
1795
- width *= scaleX;
1796
- height *= scaleY;
1797
- const size = width * height;
1798
- if (!repeat) {
1799
- if (size > Platform.image.maxCacheSize) return false;
1800
- }
1801
- let maxSize = Platform.image.maxPatternSize;
1802
- if (image.isSVG) {
1803
- const ws = width / image.width;
1804
- if (ws > 1) imageScale = ws / ceil(ws);
1805
- } else {
1806
- const imageSize = image.width * image.height;
1807
- if (maxSize > imageSize) maxSize = imageSize;
1808
- }
1809
- if (size > maxSize) imageScale = Math.sqrt(size / maxSize);
1810
- if (imageScale) {
1811
- scaleX /= imageScale;
1812
- scaleY /= imageScale;
1813
- width /= imageScale;
1814
- height /= imageScale;
1815
- }
1816
- if (sx) {
1817
- scaleX /= sx;
1818
- scaleY /= sy;
1819
- }
1820
- const xGap = gap && gap.x * scaleX;
1821
- const yGap = gap && gap.y * scaleY;
1822
- if (transform || scaleX !== 1 || scaleY !== 1) {
1823
- const canvasWidth = width + (xGap || 0);
1824
- const canvasHeight = height + (yGap || 0);
1825
- scaleX /= canvasWidth / max$1(floor(canvasWidth), 1);
1826
- scaleY /= canvasHeight / max$1(floor(canvasHeight), 1);
1827
- if (!imageMatrix) {
1828
- imageMatrix = get$1();
1829
- if (transform) copy$1(imageMatrix, transform);
1753
+ case 270:
1754
+ translate(transform, 0, width);
1755
+ break;
1756
+ }
1830
1757
  }
1831
- scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1832
1758
  }
1833
- const canvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1834
- const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1835
- paint.style = pattern;
1836
- paint.patternId = id;
1837
- return true;
1838
- } else {
1839
- return false;
1759
+ origin.x = box.x + x;
1760
+ origin.y = box.y + y;
1761
+ translate(transform, origin.x, origin.y);
1762
+ if (scaleX) scaleOfOuter$1(transform, origin, scaleX, scaleY);
1840
1763
  }
1764
+ data.transform = transform;
1765
+ }
1766
+
1767
+ function layout(transform, box, x, y, scaleX, scaleY, rotation, skew) {
1768
+ if (rotation) rotate(transform, rotation);
1769
+ if (skew) skewHelper(transform, skew.x, skew.y);
1770
+ if (scaleX) scaleHelper(transform, scaleX, scaleY);
1771
+ translate(transform, box.x + x, box.y + y);
1841
1772
  }
1842
1773
 
1843
1774
  function __awaiter(thisArg, _arguments, P, generator) {
@@ -1873,58 +1804,116 @@ typeof SuppressedError === "function" ? SuppressedError : function(error, suppre
1873
1804
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1874
1805
  };
1875
1806
 
1876
- function checkImage(ui, canvas, paint, allowDraw) {
1877
- const {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
1878
- const {pixelRatio: pixelRatio} = canvas, {data: data} = paint;
1879
- if (!data || paint.patternId === scaleX + "-" + scaleY + "-" + pixelRatio && !Export.running) {
1807
+ const {get: get$1, scale: scale, copy: copy$1} = MatrixHelper;
1808
+
1809
+ const {getFloorScale: getFloorScale} = MathHelper, {abs: abs$1} = Math;
1810
+
1811
+ function createPatternTask(paint, ui, canvas, renderOptions) {
1812
+ if (!paint.patternTask) {
1813
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1814
+ paint.patternTask = null;
1815
+ if (canvas.bounds.hit(ui.__nowWorld)) PaintImage.createPattern(paint, ui, canvas, renderOptions);
1816
+ ui.forceUpdate("surface");
1817
+ }), 300);
1818
+ }
1819
+ }
1820
+
1821
+ function createPattern(paint, ui, canvas, renderOptions) {
1822
+ let {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions), id = scaleX + "-" + scaleY;
1823
+ if (paint.patternId !== id && !ui.destroyed) {
1824
+ if (!(Platform.image.isLarge(paint.image, scaleX, scaleY) && !paint.data.repeat)) {
1825
+ const {image: image, data: data} = paint, {transform: transform, gap: gap} = data, fixScale = PaintImage.getPatternFixScale(paint, scaleX, scaleY);
1826
+ let imageMatrix, xGap, yGap, {width: width, height: height} = image;
1827
+ if (fixScale) scaleX *= fixScale, scaleY *= fixScale;
1828
+ width *= scaleX;
1829
+ height *= scaleY;
1830
+ if (gap) {
1831
+ xGap = gap.x * scaleX / abs$1(data.scaleX || 1);
1832
+ yGap = gap.y * scaleY / abs$1(data.scaleY || 1);
1833
+ }
1834
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1835
+ scaleX *= getFloorScale(width + (xGap || 0));
1836
+ scaleY *= getFloorScale(height + (yGap || 0));
1837
+ imageMatrix = get$1();
1838
+ if (transform) copy$1(imageMatrix, transform);
1839
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1840
+ }
1841
+ const imageCanvas = image.getCanvas(width, height, data.opacity, data.filters, xGap, yGap, ui.leafer && ui.leafer.config.smooth);
1842
+ const pattern = image.getPattern(imageCanvas, data.repeat || (Platform.origin.noRepeat || "no-repeat"), imageMatrix, paint);
1843
+ paint.style = pattern;
1844
+ paint.patternId = id;
1845
+ }
1846
+ }
1847
+ }
1848
+
1849
+ function getPatternFixScale(paint, imageScaleX, imageScaleY) {
1850
+ const {image: image} = paint;
1851
+ let fixScale, maxSize = Platform.image.maxPatternSize, imageSize = image.width * image.height;
1852
+ if (image.isSVG) {
1853
+ if (imageScaleX > 1) fixScale = Math.ceil(imageScaleX) / imageScaleX;
1854
+ } else {
1855
+ if (maxSize > imageSize) maxSize = imageSize;
1856
+ }
1857
+ if ((imageSize *= imageScaleX * imageScaleY) > maxSize) fixScale = Math.sqrt(maxSize / imageSize);
1858
+ return fixScale;
1859
+ }
1860
+
1861
+ function checkImage(paint, drawImage, ui, canvas, renderOptions) {
1862
+ const {scaleX: scaleX, scaleY: scaleY} = PaintImage.getImageRenderScaleData(paint, ui, canvas, renderOptions);
1863
+ const {image: image, data: data} = paint, {exporting: exporting} = renderOptions;
1864
+ if (!data || paint.patternId === scaleX + "-" + scaleY && !exporting) {
1880
1865
  return false;
1881
1866
  } else {
1882
- if (allowDraw) {
1867
+ if (drawImage) {
1883
1868
  if (data.repeat) {
1884
- allowDraw = false;
1885
- } else if (!(paint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || Export.running)) {
1886
- let {width: width, height: height} = data;
1887
- width *= scaleX * pixelRatio;
1888
- height *= scaleY * pixelRatio;
1889
- if (data.scaleX) {
1890
- width *= data.scaleX;
1891
- height *= data.scaleY;
1892
- }
1893
- allowDraw = width * height > Platform.image.maxCacheSize;
1869
+ drawImage = false;
1870
+ } else if (!(paint.changeful || Platform.name === "miniapp" && ResizeEvent.isResizing(ui) || exporting)) {
1871
+ drawImage = Platform.image.isLarge(image, scaleX, scaleY);
1894
1872
  }
1895
1873
  }
1896
- if (allowDraw) {
1874
+ if (drawImage) {
1897
1875
  if (ui.__.__isFastShadow) {
1898
1876
  canvas.fillStyle = paint.style || "#000";
1899
1877
  canvas.fill();
1900
1878
  }
1901
- drawImage(ui, canvas, paint, data);
1879
+ PaintImage.drawImage(paint, scaleX, scaleY, ui, canvas, renderOptions);
1902
1880
  return true;
1903
1881
  } else {
1904
- if (!paint.style || paint.sync || Export.running) {
1905
- createPattern(ui, paint, pixelRatio);
1906
- } else {
1907
- if (!paint.patternTask) {
1908
- paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function*() {
1909
- paint.patternTask = null;
1910
- if (canvas.bounds.hit(ui.__nowWorld)) createPattern(ui, paint, pixelRatio);
1911
- ui.forceUpdate("surface");
1912
- }), 300);
1913
- }
1914
- }
1882
+ if (!paint.style || paint.sync || exporting) PaintImage.createPattern(paint, ui, canvas, renderOptions); else PaintImage.createPatternTask(paint, ui, canvas, renderOptions);
1915
1883
  return false;
1916
1884
  }
1917
1885
  }
1918
1886
  }
1919
1887
 
1920
- function drawImage(ui, canvas, paint, data) {
1921
- canvas.save();
1922
- canvas.clipUI(ui);
1923
- if (paint.blendMode) canvas.blendMode = paint.blendMode;
1924
- if (data.opacity) canvas.opacity *= data.opacity;
1925
- if (data.transform) canvas.transform(data.transform);
1926
- canvas.drawImage(paint.image.getFull(data.filters), 0, 0, data.width, data.height);
1927
- canvas.restore();
1888
+ function drawImage(paint, _imageScaleX, _imageScaleY, ui, canvas, _renderOptions) {
1889
+ const {data: data, image: image, blendMode: blendMode} = paint, {opacity: opacity, transform: transform} = data, view = image.getFull(data.filters), u = ui.__;
1890
+ let {width: width, height: height} = image, clipUI;
1891
+ if (transform && !transform.onlyScale || (clipUI = u.path || u.cornerRadius) || opacity || blendMode) {
1892
+ canvas.save();
1893
+ clipUI && canvas.clipUI(ui);
1894
+ blendMode && (canvas.blendMode = blendMode);
1895
+ opacity && (canvas.opacity *= opacity);
1896
+ transform && canvas.transform(transform);
1897
+ canvas.drawImage(view, 0, 0, width, height);
1898
+ canvas.restore();
1899
+ } else {
1900
+ if (data.scaleX) width *= data.scaleX, height *= data.scaleY;
1901
+ canvas.drawImage(view, 0, 0, width, height);
1902
+ }
1903
+ }
1904
+
1905
+ function getImageRenderScaleData(paint, ui, canvas, _renderOptions) {
1906
+ const scaleData = ui.getRenderScaleData(true, paint.scaleFixed), {data: data} = paint;
1907
+ if (canvas) {
1908
+ const {pixelRatio: pixelRatio} = canvas;
1909
+ scaleData.scaleX *= pixelRatio;
1910
+ scaleData.scaleY *= pixelRatio;
1911
+ }
1912
+ if (data && data.scaleX) {
1913
+ scaleData.scaleX *= Math.abs(data.scaleX);
1914
+ scaleData.scaleY *= Math.abs(data.scaleY);
1915
+ }
1916
+ return scaleData;
1928
1917
  }
1929
1918
 
1930
1919
  function recycleImage(attrName, data) {
@@ -1956,8 +1945,12 @@ function recycleImage(attrName, data) {
1956
1945
  const PaintImageModule = {
1957
1946
  image: image,
1958
1947
  checkImage: checkImage,
1959
- createPattern: createPattern,
1948
+ drawImage: drawImage,
1949
+ getImageRenderScaleData: getImageRenderScaleData,
1960
1950
  recycleImage: recycleImage,
1951
+ createPatternTask: createPatternTask,
1952
+ createPattern: createPattern,
1953
+ getPatternFixScale: getPatternFixScale,
1961
1954
  createData: createData,
1962
1955
  getPatternData: getPatternData,
1963
1956
  stretchMode: stretchMode,
@@ -2413,10 +2406,8 @@ function createRows(drawData, content, style) {
2413
2406
  bounds = drawData.bounds;
2414
2407
  findMaxWidth = !bounds.width && !style.autoSizeAlign;
2415
2408
  const {__letterSpacing: __letterSpacing, paraIndent: paraIndent, textCase: textCase} = style;
2416
- const {canvas: canvas} = Platform;
2417
- const {width: width, height: height} = bounds;
2418
- const charMode = width || height || __letterSpacing || textCase !== "none";
2419
- if (charMode) {
2409
+ const {canvas: canvas} = Platform, {width: width} = bounds;
2410
+ if (style.__isCharMode) {
2420
2411
  const wrap = style.textWrap !== "none";
2421
2412
  const breakAll = style.textWrap === "break";
2422
2413
  paraStart = true;
@@ -2545,12 +2536,19 @@ const TextMode = 2;
2545
2536
  function layoutChar(drawData, style, width, _height) {
2546
2537
  const {rows: rows} = drawData;
2547
2538
  const {textAlign: textAlign, paraIndent: paraIndent, letterSpacing: letterSpacing} = style;
2548
- let charX, addWordWidth, indentWidth, mode, wordChar, wordsLength;
2539
+ const justifyLast = width && textAlign.includes("both");
2540
+ const justify = justifyLast || width && textAlign.includes("justify");
2541
+ const justifyLetter = justify && textAlign.includes("letter");
2542
+ let charX, remainingWidth, addWordWidth, addLetterWidth, indentWidth, mode, wordChar, wordsLength, isLastWord, canJustify;
2549
2543
  rows.forEach(row => {
2550
2544
  if (row.words) {
2551
2545
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0, wordsLength = row.words.length;
2552
- addWordWidth = width && (textAlign === "justify" || textAlign === "both") && wordsLength > 1 ? (width - row.width - indentWidth) / (wordsLength - 1) : 0;
2553
- mode = letterSpacing || row.isOverflow ? CharMode : addWordWidth > .01 ? WordMode : TextMode;
2546
+ if (justify) {
2547
+ canJustify = !row.paraEnd || justifyLast;
2548
+ remainingWidth = width - row.width - indentWidth;
2549
+ if (justifyLetter) addLetterWidth = remainingWidth / (row.words.reduce((total, item) => total + item.data.length, 0) - 1); else addWordWidth = wordsLength > 1 ? remainingWidth / (wordsLength - 1) : 0;
2550
+ }
2551
+ mode = letterSpacing || row.isOverflow || justifyLetter ? CharMode : addWordWidth ? WordMode : TextMode;
2554
2552
  if (row.isOverflow && !letterSpacing) row.textMode = true;
2555
2553
  if (mode === TextMode) {
2556
2554
  row.x += indentWidth;
@@ -2568,11 +2566,15 @@ function layoutChar(drawData, style, width, _height) {
2568
2566
  charX = toWordChar(word.data, charX, wordChar);
2569
2567
  if (row.isOverflow || wordChar.char !== " ") row.data.push(wordChar);
2570
2568
  } else {
2571
- charX = toChar(word.data, charX, row.data, row.isOverflow);
2569
+ charX = toChar(word.data, charX, row.data, row.isOverflow, canJustify && addLetterWidth);
2572
2570
  }
2573
- if (addWordWidth && (!row.paraEnd || textAlign === "both") && index !== wordsLength - 1) {
2574
- charX += addWordWidth;
2575
- row.width += addWordWidth;
2571
+ if (canJustify) {
2572
+ isLastWord = index === wordsLength - 1;
2573
+ if (addWordWidth) {
2574
+ if (!isLastWord) charX += addWordWidth, row.width += addWordWidth;
2575
+ } else if (addLetterWidth) {
2576
+ row.width += addLetterWidth * (word.data.length - (isLastWord ? 1 : 0));
2577
+ }
2576
2578
  }
2577
2579
  });
2578
2580
  }
@@ -2598,13 +2600,14 @@ function toWordChar(data, charX, wordChar) {
2598
2600
  return charX;
2599
2601
  }
2600
2602
 
2601
- function toChar(data, charX, rowData, isOverflow) {
2603
+ function toChar(data, charX, rowData, isOverflow, addLetterWidth) {
2602
2604
  data.forEach(char => {
2603
2605
  if (isOverflow || char.char !== " ") {
2604
2606
  char.x = charX;
2605
2607
  rowData.push(char);
2606
2608
  }
2607
2609
  charX += char.width;
2610
+ addLetterWidth && (charX += addLetterWidth);
2608
2611
  });
2609
2612
  return charX;
2610
2613
  }
@@ -2746,10 +2749,10 @@ function getDrawData(content, style) {
2746
2749
  let x = 0, y = 0;
2747
2750
  let width = style.__getInput("width") || 0;
2748
2751
  let height = style.__getInput("height") || 0;
2749
- const {textDecoration: textDecoration, __font: __font, __padding: padding} = style;
2752
+ const {__padding: padding} = style;
2750
2753
  if (padding) {
2751
- if (width) x = padding[left], width -= padding[right] + padding[left]; else if (!style.autoSizeAlign) x = padding[left];
2752
- if (height) y = padding[top], height -= padding[top] + padding[bottom]; else if (!style.autoSizeAlign) y = padding[top];
2754
+ if (width) x = padding[left], width -= padding[right] + padding[left], !width && (width = .01); else if (!style.autoSizeAlign) x = padding[left];
2755
+ if (height) y = padding[top], height -= padding[top] + padding[bottom], !height && (height = .01); else if (!style.autoSizeAlign) y = padding[top];
2753
2756
  }
2754
2757
  const drawData = {
2755
2758
  bounds: {
@@ -2760,14 +2763,14 @@ function getDrawData(content, style) {
2760
2763
  },
2761
2764
  rows: [],
2762
2765
  paraNumber: 0,
2763
- font: Platform.canvas.font = __font
2766
+ font: Platform.canvas.font = style.__font
2764
2767
  };
2765
2768
  createRows(drawData, content, style);
2766
2769
  if (padding) padAutoText(padding, drawData, style, width, height);
2767
2770
  layoutText(drawData, style);
2768
- layoutChar(drawData, style, width);
2771
+ if (style.__isCharMode) layoutChar(drawData, style, width);
2769
2772
  if (drawData.overflow) clipText(drawData, style, x, width);
2770
- if (textDecoration !== "none") decorationText(drawData, style);
2773
+ if (style.textDecoration !== "none") decorationText(drawData, style);
2771
2774
  return drawData;
2772
2775
  }
2773
2776