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