@leafer-ui/miniapp 1.6.2 → 1.6.4

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
@@ -300,17 +300,15 @@ class Watcher {
300
300
  this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
301
301
  this.__updatedList = new core.LeafList();
302
302
  this.totalTimes++;
303
- this.changed = false;
304
- this.hasVisible = false;
305
- this.hasRemove = false;
306
- this.hasAdd = false;
303
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
307
304
  }
308
305
  __listenEvents() {
309
- const { target } = this;
310
306
  this.__eventIds = [
311
- target.on_(core.PropertyEvent.CHANGE, this.__onAttrChange, this),
312
- target.on_([core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this),
313
- target.on_(core.WatchEvent.REQUEST, this.__onRquestData, this)
307
+ this.target.on_([
308
+ [core.PropertyEvent.CHANGE, this.__onAttrChange, this],
309
+ [[core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this],
310
+ [core.WatchEvent.REQUEST, this.__onRquestData, this]
311
+ ])
314
312
  ];
315
313
  }
316
314
  __removeListenEvents() {
@@ -320,8 +318,7 @@ class Watcher {
320
318
  if (this.target) {
321
319
  this.stop();
322
320
  this.__removeListenEvents();
323
- this.target = null;
324
- this.__updatedList = null;
321
+ this.target = this.__updatedList = null;
325
322
  }
326
323
  }
327
324
  }
@@ -426,7 +423,7 @@ class Layouter {
426
423
  this.disabled = true;
427
424
  }
428
425
  layout() {
429
- if (!this.running)
426
+ if (this.layouting || !this.running)
430
427
  return;
431
428
  const { target } = this;
432
429
  this.times = 0;
@@ -509,12 +506,10 @@ class Layouter {
509
506
  }
510
507
  static fullLayout(target) {
511
508
  updateAllMatrix(target, true);
512
- if (target.isBranch) {
509
+ if (target.isBranch)
513
510
  core.BranchHelper.updateBounds(target);
514
- }
515
- else {
511
+ else
516
512
  core.LeafHelper.updateBounds(target);
517
- }
518
513
  updateAllChange(target);
519
514
  }
520
515
  addExtra(leaf) {
@@ -537,11 +532,12 @@ class Layouter {
537
532
  this.__updatedList = event.data.updatedList;
538
533
  }
539
534
  __listenEvents() {
540
- const { target } = this;
541
535
  this.__eventIds = [
542
- target.on_(core.LayoutEvent.REQUEST, this.layout, this),
543
- target.on_(core.LayoutEvent.AGAIN, this.layoutAgain, this),
544
- target.on_(core.WatchEvent.DATA, this.__onReceiveWatchData, this)
536
+ this.target.on_([
537
+ [core.LayoutEvent.REQUEST, this.layout, this],
538
+ [core.LayoutEvent.AGAIN, this.layoutAgain, this],
539
+ [core.WatchEvent.DATA, this.__onReceiveWatchData, this]
540
+ ])
545
541
  ];
546
542
  }
547
543
  __removeListenEvents() {
@@ -772,12 +768,13 @@ class Renderer {
772
768
  this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
773
769
  }
774
770
  __listenEvents() {
775
- const { target } = this;
776
771
  this.__eventIds = [
777
- target.on_(core.RenderEvent.REQUEST, this.update, this),
778
- target.on_(core.LayoutEvent.END, this.__onLayoutEnd, this),
779
- target.on_(core.RenderEvent.AGAIN, this.renderAgain, this),
780
- target.on_(core.ResizeEvent.RESIZE, this.__onResize, this)
772
+ this.target.on_([
773
+ [core.RenderEvent.REQUEST, this.update, this],
774
+ [core.LayoutEvent.END, this.__onLayoutEnd, this],
775
+ [core.RenderEvent.AGAIN, this.renderAgain, this],
776
+ [core.ResizeEvent.RESIZE, this.__onResize, this]
777
+ ])
781
778
  ];
782
779
  }
783
780
  __removeListenEvents() {
@@ -1126,35 +1123,38 @@ function fillPathOrText(ui, canvas) {
1126
1123
  }
1127
1124
 
1128
1125
  function strokeText(stroke, ui, canvas) {
1129
- const { strokeAlign } = ui.__;
1130
- const isStrokes = typeof stroke !== 'string';
1131
- switch (strokeAlign) {
1126
+ switch (ui.__.strokeAlign) {
1132
1127
  case 'center':
1133
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1134
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1128
+ drawCenter$1(stroke, 1, ui, canvas);
1135
1129
  break;
1136
1130
  case 'inside':
1137
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
1131
+ drawAlign(stroke, 'inside', ui, canvas);
1138
1132
  break;
1139
1133
  case 'outside':
1140
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
1134
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
1141
1135
  break;
1142
1136
  }
1143
1137
  }
1144
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
1145
- const { __strokeWidth, __font } = ui.__;
1138
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1139
+ const data = ui.__;
1140
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
1141
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1142
+ }
1143
+ function drawAlign(stroke, align, ui, canvas) {
1146
1144
  const out = canvas.getSameCanvas(true, true);
1147
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
1148
- out.font = __font;
1149
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1145
+ out.font = ui.__.__font;
1146
+ drawCenter$1(stroke, 2, ui, out);
1150
1147
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1151
1148
  fillText(ui, out);
1152
1149
  out.blendMode = 'normal';
1153
- if (ui.__worldFlipped)
1150
+ copyWorld(canvas, out, ui);
1151
+ out.recycle(ui.__nowWorld);
1152
+ }
1153
+ function copyWorld(canvas, out, ui) {
1154
+ if (ui.__worldFlipped || core.Platform.fullImageShadow)
1154
1155
  canvas.copyWorldByReset(out, ui.__nowWorld);
1155
1156
  else
1156
1157
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1157
- out.recycle(ui.__nowWorld);
1158
1158
  }
1159
1159
  function drawTextStroke(ui, canvas) {
1160
1160
  let row, data = ui.__.__textDrawData;
@@ -1192,90 +1192,56 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
1192
1192
  }
1193
1193
 
1194
1194
  function stroke(stroke, ui, canvas) {
1195
- const options = ui.__;
1196
- const { __strokeWidth, strokeAlign, __font } = options;
1197
- if (!__strokeWidth)
1195
+ const data = ui.__;
1196
+ if (!data.__strokeWidth)
1198
1197
  return;
1199
- if (__font) {
1198
+ if (data.__font) {
1200
1199
  strokeText(stroke, ui, canvas);
1201
1200
  }
1202
1201
  else {
1203
- switch (strokeAlign) {
1202
+ switch (data.strokeAlign) {
1204
1203
  case 'center':
1205
- canvas.setStroke(stroke, __strokeWidth, options);
1206
- canvas.stroke();
1207
- if (options.__useArrow)
1208
- strokeArrow(ui, canvas);
1204
+ drawCenter(stroke, 1, ui, canvas);
1209
1205
  break;
1210
1206
  case 'inside':
1211
- canvas.save();
1212
- canvas.setStroke(stroke, __strokeWidth * 2, options);
1213
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1214
- canvas.stroke();
1215
- canvas.restore();
1207
+ drawInside(stroke, ui, canvas);
1216
1208
  break;
1217
1209
  case 'outside':
1218
- const out = canvas.getSameCanvas(true, true);
1219
- out.setStroke(stroke, __strokeWidth * 2, options);
1220
- ui.__drawRenderPath(out);
1221
- out.stroke();
1222
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1223
- out.clearWorld(ui.__layout.renderBounds);
1224
- if (ui.__worldFlipped)
1225
- canvas.copyWorldByReset(out, ui.__nowWorld);
1226
- else
1227
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1228
- out.recycle(ui.__nowWorld);
1210
+ drawOutside(stroke, ui, canvas);
1229
1211
  break;
1230
1212
  }
1231
1213
  }
1232
1214
  }
1233
1215
  function strokes(strokes, ui, canvas) {
1234
- const options = ui.__;
1235
- const { __strokeWidth, strokeAlign, __font } = options;
1236
- if (!__strokeWidth)
1237
- return;
1238
- if (__font) {
1239
- strokeText(strokes, ui, canvas);
1216
+ stroke(strokes, ui, canvas);
1217
+ }
1218
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
1219
+ const data = ui.__;
1220
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
1221
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
1222
+ if (data.__useArrow)
1223
+ draw.Paint.strokeArrow(stroke, ui, canvas);
1224
+ }
1225
+ function drawInside(stroke, ui, canvas) {
1226
+ canvas.save();
1227
+ canvas.clipUI(ui);
1228
+ drawCenter(stroke, 2, ui, canvas);
1229
+ canvas.restore();
1230
+ }
1231
+ function drawOutside(stroke, ui, canvas) {
1232
+ const data = ui.__;
1233
+ if (data.__fillAfterStroke) {
1234
+ drawCenter(stroke, 2, ui, canvas);
1240
1235
  }
1241
1236
  else {
1242
- switch (strokeAlign) {
1243
- case 'center':
1244
- canvas.setStroke(undefined, __strokeWidth, options);
1245
- drawStrokesStyle(strokes, false, ui, canvas);
1246
- if (options.__useArrow)
1247
- strokeArrow(ui, canvas);
1248
- break;
1249
- case 'inside':
1250
- canvas.save();
1251
- canvas.setStroke(undefined, __strokeWidth * 2, options);
1252
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1253
- drawStrokesStyle(strokes, false, ui, canvas);
1254
- canvas.restore();
1255
- break;
1256
- case 'outside':
1257
- const { renderBounds } = ui.__layout;
1258
- const out = canvas.getSameCanvas(true, true);
1259
- ui.__drawRenderPath(out);
1260
- out.setStroke(undefined, __strokeWidth * 2, options);
1261
- drawStrokesStyle(strokes, false, ui, out);
1262
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1263
- out.clearWorld(renderBounds);
1264
- if (ui.__worldFlipped)
1265
- canvas.copyWorldByReset(out, ui.__nowWorld);
1266
- else
1267
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1268
- out.recycle(ui.__nowWorld);
1269
- break;
1270
- }
1271
- }
1272
- }
1273
- function strokeArrow(ui, canvas) {
1274
- if (ui.__.dashPattern) {
1275
- canvas.beginPath();
1276
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
1277
- canvas.dashPattern = null;
1278
- canvas.stroke();
1237
+ const { renderBounds } = ui.__layout;
1238
+ const out = canvas.getSameCanvas(true, true);
1239
+ ui.__drawRenderPath(out);
1240
+ drawCenter(stroke, 2, ui, out);
1241
+ out.clipUI(data);
1242
+ out.clearWorld(renderBounds);
1243
+ copyWorld(canvas, out, ui);
1244
+ out.recycle(ui.__nowWorld);
1279
1245
  }
1280
1246
  }
1281
1247
 
@@ -1322,41 +1288,66 @@ function shape(ui, current, options) {
1322
1288
  }
1323
1289
 
1324
1290
  let recycleMap;
1291
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
1325
1292
  function compute(attrName, ui) {
1326
1293
  const data = ui.__, leafPaints = [];
1327
- let paints = data.__input[attrName], hasOpacityPixel;
1294
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1328
1295
  if (!(paints instanceof Array))
1329
1296
  paints = [paints];
1330
1297
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
1331
1298
  for (let i = 0, len = paints.length, item; i < len; i++) {
1332
- item = getLeafPaint(attrName, paints[i], ui);
1333
- if (item)
1334
- leafPaints.push(item);
1299
+ (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
1335
1300
  }
1336
1301
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1337
- if (leafPaints.length && leafPaints[0].image)
1338
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1339
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
1302
+ if (leafPaints.length) {
1303
+ if (leafPaints.every(item => item.isTransparent)) {
1304
+ if (leafPaints.some(item => item.image))
1305
+ isAlphaPixel = true;
1306
+ isTransparent = true;
1307
+ }
1308
+ }
1309
+ if (attrName === 'fill') {
1310
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1311
+ stintSet(data, '__isTransparentFill', isTransparent);
1312
+ }
1313
+ else {
1314
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1315
+ stintSet(data, '__isTransparentStroke', isTransparent);
1316
+ }
1340
1317
  }
1341
1318
  function getLeafPaint(attrName, paint, ui) {
1342
1319
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1343
1320
  return undefined;
1321
+ let data;
1344
1322
  const { boxBounds } = ui.__layout;
1345
1323
  switch (paint.type) {
1346
- case 'solid':
1347
- let { type, blendMode, color, opacity } = paint;
1348
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
1349
1324
  case 'image':
1350
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1325
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1326
+ break;
1351
1327
  case 'linear':
1352
- return draw.PaintGradient.linearGradient(paint, boxBounds);
1328
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
1329
+ break;
1353
1330
  case 'radial':
1354
- return draw.PaintGradient.radialGradient(paint, boxBounds);
1331
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
1332
+ break;
1355
1333
  case 'angular':
1356
- return draw.PaintGradient.conicGradient(paint, boxBounds);
1334
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
1335
+ break;
1336
+ case 'solid':
1337
+ const { type, color, opacity } = paint;
1338
+ data = { type, style: draw.ColorConvert.string(color, opacity) };
1339
+ break;
1357
1340
  default:
1358
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
1341
+ if (paint.r !== undefined)
1342
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
1359
1343
  }
1344
+ if (data) {
1345
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1346
+ data.isTransparent = true;
1347
+ if (paint.blendMode)
1348
+ data.blendMode = paint.blendMode;
1349
+ }
1350
+ return data;
1360
1351
  }
1361
1352
 
1362
1353
  const PaintModule = {
@@ -1422,12 +1413,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1422
1413
 
1423
1414
  const { get: get$2, translate } = core.MatrixHelper;
1424
1415
  const tempBox = new core.Bounds();
1425
- const tempPoint = {};
1426
1416
  const tempScaleData = {};
1417
+ const tempImage = {};
1427
1418
  function createData(leafPaint, image, paint, box) {
1428
- const { blendMode, changeful, sync } = paint;
1429
- if (blendMode)
1430
- leafPaint.blendMode = blendMode;
1419
+ const { changeful, sync } = paint;
1431
1420
  if (changeful)
1432
1421
  leafPaint.changeful = changeful;
1433
1422
  if (sync)
@@ -1435,38 +1424,38 @@ function createData(leafPaint, image, paint, box) {
1435
1424
  leafPaint.data = getPatternData(paint, box, image);
1436
1425
  }
1437
1426
  function getPatternData(paint, box, image) {
1438
- let { width, height } = image;
1439
1427
  if (paint.padding)
1440
1428
  box = tempBox.set(box).shrink(paint.padding);
1441
1429
  if (paint.mode === 'strench')
1442
1430
  paint.mode = 'stretch';
1431
+ let { width, height } = image;
1443
1432
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1444
1433
  const sameBox = box.width === width && box.height === height;
1445
1434
  const data = { mode };
1446
1435
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1447
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1448
- let x = 0, y = 0, scaleX, scaleY;
1436
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1437
+ let scaleX, scaleY;
1449
1438
  if (!mode || mode === 'cover' || mode === 'fit') {
1450
1439
  if (!sameBox || rotation) {
1451
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1452
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1453
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1440
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1441
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1442
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1454
1443
  }
1455
1444
  }
1456
- else if (scale || size) {
1457
- core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1458
- scaleX = tempScaleData.scaleX;
1459
- scaleY = tempScaleData.scaleY;
1460
- }
1461
- if (align) {
1462
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1463
- if (scaleX)
1464
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1465
- core.AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1466
- x += tempPoint.x, y += tempPoint.y;
1445
+ else {
1446
+ if (scale || size) {
1447
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1448
+ scaleX = tempScaleData.scaleX;
1449
+ scaleY = tempScaleData.scaleY;
1450
+ }
1451
+ if (align) {
1452
+ if (scaleX)
1453
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1454
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1455
+ }
1467
1456
  }
1468
1457
  if (offset)
1469
- x += offset.x, y += offset.y;
1458
+ core.PointHelper.move(tempImage, offset);
1470
1459
  switch (mode) {
1471
1460
  case 'stretch':
1472
1461
  if (!sameBox)
@@ -1474,12 +1463,12 @@ function getPatternData(paint, box, image) {
1474
1463
  break;
1475
1464
  case 'normal':
1476
1465
  case 'clip':
1477
- if (x || y || scaleX || rotation)
1478
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1466
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1467
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1479
1468
  break;
1480
1469
  case 'repeat':
1481
1470
  if (!sameBox || scaleX || rotation)
1482
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1471
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1483
1472
  if (!repeat)
1484
1473
  data.repeat = 'repeat';
1485
1474
  break;
@@ -1487,7 +1476,7 @@ function getPatternData(paint, box, image) {
1487
1476
  case 'cover':
1488
1477
  default:
1489
1478
  if (scaleX)
1490
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1479
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1491
1480
  }
1492
1481
  if (!data.transform) {
1493
1482
  if (box.x || box.y) {
@@ -1520,6 +1509,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1520
1509
  }
1521
1510
  else {
1522
1511
  leafPaint = { type: paint.type, image };
1512
+ if (image.hasAlphaPixel)
1513
+ leafPaint.isTransparent = true;
1523
1514
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1524
1515
  }
1525
1516
  if (firstUse || image.loading)
@@ -1544,7 +1535,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1544
1535
  ignoreRender(ui, false);
1545
1536
  if (!ui.destroyed) {
1546
1537
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1547
- if (image.hasOpacityPixel)
1538
+ if (image.hasAlphaPixel)
1548
1539
  ui.__layout.hitCanvasChanged = true;
1549
1540
  ui.forceUpdate('surface');
1550
1541
  }
@@ -1556,13 +1547,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1556
1547
  onLoadError(ui, event, error);
1557
1548
  leafPaint.loadId = null;
1558
1549
  });
1559
- if (ui.placeholderColor)
1560
- setTimeout(() => {
1561
- if (!(image.ready || image.isPlacehold)) {
1562
- image.isPlacehold = true;
1563
- ui.forceUpdate('surface');
1564
- }
1565
- }, 100);
1550
+ if (ui.placeholderColor) {
1551
+ if (!ui.placeholderDelay)
1552
+ image.isPlacehold = true;
1553
+ else
1554
+ setTimeout(() => {
1555
+ if (!image.ready) {
1556
+ image.isPlacehold = true;
1557
+ ui.forceUpdate('surface');
1558
+ }
1559
+ }, ui.placeholderDelay);
1560
+ }
1566
1561
  }
1567
1562
  return leafPaint;
1568
1563
  }
@@ -1749,7 +1744,7 @@ function checkImage(ui, canvas, paint, allowDraw) {
1749
1744
  }
1750
1745
  function drawImage(ui, canvas, paint, data) {
1751
1746
  canvas.save();
1752
- ui.windingRule ? canvas.clip(ui.windingRule) : canvas.clip();
1747
+ canvas.clipUI(ui);
1753
1748
  if (paint.blendMode)
1754
1749
  canvas.blendMode = paint.blendMode;
1755
1750
  if (data.opacity)
@@ -1800,32 +1795,33 @@ const PaintImageModule = {
1800
1795
  repeatMode
1801
1796
  };
1802
1797
 
1803
- const { toPoint: toPoint$2 } = core.AroundHelper;
1798
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1804
1799
  const realFrom$2 = {};
1805
1800
  const realTo$2 = {};
1806
1801
  function linearGradient(paint, box) {
1807
- let { from, to, type, blendMode, opacity } = paint;
1802
+ let { from, to, type, opacity } = paint;
1808
1803
  toPoint$2(from || 'top', box, realFrom$2);
1809
1804
  toPoint$2(to || 'bottom', box, realTo$2);
1810
1805
  const style = core.Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1811
- applyStops(style, paint.stops, opacity);
1812
1806
  const data = { type, style };
1813
- if (blendMode)
1814
- data.blendMode = blendMode;
1807
+ applyStops(data, style, paint.stops, opacity);
1815
1808
  return data;
1816
1809
  }
1817
- function applyStops(gradient, stops, opacity) {
1810
+ function applyStops(data, gradient, stops, opacity) {
1818
1811
  if (stops) {
1819
- let stop;
1812
+ let stop, color, offset, isTransparent;
1820
1813
  for (let i = 0, len = stops.length; i < len; i++) {
1821
1814
  stop = stops[i];
1822
- if (typeof stop === 'string') {
1823
- gradient.addColorStop(i / (len - 1), draw.ColorConvert.string(stop, opacity));
1824
- }
1825
- else {
1826
- gradient.addColorStop(stop.offset, draw.ColorConvert.string(stop.color, opacity));
1827
- }
1815
+ if (typeof stop === 'string')
1816
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1817
+ else
1818
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1819
+ gradient.addColorStop(offset, color);
1820
+ if (!isTransparent && hasTransparent(color))
1821
+ isTransparent = true;
1828
1822
  }
1823
+ if (isTransparent)
1824
+ data.isTransparent = true;
1829
1825
  }
1830
1826
  }
1831
1827
 
@@ -1835,17 +1831,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1835
1831
  const realFrom$1 = {};
1836
1832
  const realTo$1 = {};
1837
1833
  function radialGradient(paint, box) {
1838
- let { from, to, type, opacity, blendMode, stretch } = paint;
1834
+ let { from, to, type, opacity, stretch } = paint;
1839
1835
  toPoint$1(from || 'center', box, realFrom$1);
1840
1836
  toPoint$1(to || 'bottom', box, realTo$1);
1841
1837
  const style = core.Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1842
- applyStops(style, paint.stops, opacity);
1843
1838
  const data = { type, style };
1839
+ applyStops(data, style, paint.stops, opacity);
1844
1840
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1845
1841
  if (transform)
1846
1842
  data.transform = transform;
1847
- if (blendMode)
1848
- data.blendMode = blendMode;
1849
1843
  return data;
1850
1844
  }
1851
1845
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1871,17 +1865,15 @@ const { toPoint } = core.AroundHelper;
1871
1865
  const realFrom = {};
1872
1866
  const realTo = {};
1873
1867
  function conicGradient(paint, box) {
1874
- let { from, to, type, opacity, blendMode, stretch } = paint;
1868
+ let { from, to, type, opacity, stretch } = paint;
1875
1869
  toPoint(from || 'center', box, realFrom);
1876
1870
  toPoint(to || 'bottom', box, realTo);
1877
1871
  const style = core.Platform.conicGradientSupport ? core.Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : core.Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo));
1878
- applyStops(style, paint.stops, opacity);
1879
1872
  const data = { type, style };
1873
+ applyStops(data, style, paint.stops, opacity);
1880
1874
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1881
1875
  if (transform)
1882
1876
  data.transform = transform;
1883
- if (blendMode)
1884
- data.blendMode = blendMode;
1885
1877
  return data;
1886
1878
  }
1887
1879
 
@@ -1917,12 +1909,10 @@ function shadow(ui, current, shape) {
1917
1909
  }
1918
1910
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1919
1911
  }
1920
- if (ui.__worldFlipped) {
1912
+ if (ui.__worldFlipped)
1921
1913
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1922
- }
1923
- else {
1914
+ else
1924
1915
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1925
- }
1926
1916
  if (end && index < end)
1927
1917
  other.clearWorld(copyBounds, true);
1928
1918
  });
@@ -1981,12 +1971,10 @@ function innerShadow(ui, current, shape) {
1981
1971
  copyBounds = bounds;
1982
1972
  }
1983
1973
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), 'source-in');
1984
- if (ui.__worldFlipped) {
1974
+ if (ui.__worldFlipped)
1985
1975
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1986
- }
1987
- else {
1976
+ else
1988
1977
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1989
- }
1990
1978
  if (end && index < end)
1991
1979
  other.clearWorld(copyBounds, true);
1992
1980
  });
@@ -2214,6 +2202,8 @@ function createRows(drawData, content, style) {
2214
2202
  lastCharType = null;
2215
2203
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
2216
2204
  word = { data: [] }, row = { words: [] };
2205
+ if (__letterSpacing)
2206
+ content = [...content];
2217
2207
  for (let i = 0, len = content.length; i < len; i++) {
2218
2208
  char = content[i];
2219
2209
  if (char === '\n') {