@leafer-ui/miniapp 1.6.2 → 1.6.3

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() {
@@ -1125,32 +1122,34 @@ function fillPathOrText(ui, canvas) {
1125
1122
  ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1126
1123
  }
1127
1124
 
1125
+ const Paint = {};
1126
+
1128
1127
  function strokeText(stroke, ui, canvas) {
1129
- const { strokeAlign } = ui.__;
1130
- const isStrokes = typeof stroke !== 'string';
1131
- switch (strokeAlign) {
1128
+ switch (ui.__.strokeAlign) {
1132
1129
  case 'center':
1133
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1134
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1130
+ drawCenter$1(stroke, 1, ui, canvas);
1135
1131
  break;
1136
1132
  case 'inside':
1137
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
1133
+ drawAlign(stroke, 'inside', ui, canvas);
1138
1134
  break;
1139
1135
  case 'outside':
1140
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
1136
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
1141
1137
  break;
1142
1138
  }
1143
1139
  }
1144
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
1145
- const { __strokeWidth, __font } = ui.__;
1140
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1141
+ const data = ui.__;
1142
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
1143
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1144
+ }
1145
+ function drawAlign(stroke, align, ui, canvas) {
1146
1146
  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);
1147
+ out.font = ui.__.__font;
1148
+ drawCenter$1(stroke, 2, ui, out);
1150
1149
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1151
1150
  fillText(ui, out);
1152
1151
  out.blendMode = 'normal';
1153
- if (ui.__worldFlipped)
1152
+ if (ui.__worldFlipped || core$1.Platform.fullImageShadow)
1154
1153
  canvas.copyWorldByReset(out, ui.__nowWorld);
1155
1154
  else
1156
1155
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
@@ -1192,90 +1191,60 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
1192
1191
  }
1193
1192
 
1194
1193
  function stroke(stroke, ui, canvas) {
1195
- const options = ui.__;
1196
- const { __strokeWidth, strokeAlign, __font } = options;
1197
- if (!__strokeWidth)
1194
+ const data = ui.__;
1195
+ if (!data.__strokeWidth)
1198
1196
  return;
1199
- if (__font) {
1197
+ if (data.__font) {
1200
1198
  strokeText(stroke, ui, canvas);
1201
1199
  }
1202
1200
  else {
1203
- switch (strokeAlign) {
1201
+ switch (data.strokeAlign) {
1204
1202
  case 'center':
1205
- canvas.setStroke(stroke, __strokeWidth, options);
1206
- canvas.stroke();
1207
- if (options.__useArrow)
1208
- strokeArrow(ui, canvas);
1203
+ drawCenter(stroke, 1, ui, canvas);
1209
1204
  break;
1210
1205
  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();
1206
+ drawInside(stroke, ui, canvas);
1216
1207
  break;
1217
1208
  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);
1209
+ drawOutside(stroke, ui, canvas);
1229
1210
  break;
1230
1211
  }
1231
1212
  }
1232
1213
  }
1233
1214
  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);
1215
+ stroke(strokes, ui, canvas);
1216
+ }
1217
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
1218
+ const data = ui.__;
1219
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
1220
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
1221
+ if (data.__useArrow)
1222
+ Paint.strokeArrow(stroke, ui, canvas);
1223
+ }
1224
+ function drawInside(stroke, ui, canvas) {
1225
+ const data = ui.__;
1226
+ canvas.save();
1227
+ data.windingRule ? canvas.clip(data.windingRule) : canvas.clip();
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
+ data.windingRule ? out.clip(data.windingRule) : out.clip();
1242
+ out.clearWorld(renderBounds);
1243
+ if (ui.__worldFlipped || core$1.Platform.fullImageShadow)
1244
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1245
+ else
1246
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1247
+ out.recycle(ui.__nowWorld);
1279
1248
  }
1280
1249
  }
1281
1250
 
@@ -1322,9 +1291,10 @@ function shape(ui, current, options) {
1322
1291
  }
1323
1292
 
1324
1293
  let recycleMap;
1294
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
1325
1295
  function compute(attrName, ui) {
1326
1296
  const data = ui.__, leafPaints = [];
1327
- let paints = data.__input[attrName], hasOpacityPixel;
1297
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1328
1298
  if (!(paints instanceof Array))
1329
1299
  paints = [paints];
1330
1300
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
@@ -1334,29 +1304,55 @@ function compute(attrName, ui) {
1334
1304
  leafPaints.push(item);
1335
1305
  }
1336
1306
  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;
1307
+ if (leafPaints.length) {
1308
+ if (leafPaints.every(item => item.isTransparent)) {
1309
+ if (leafPaints.some(item => item.image))
1310
+ isAlphaPixel = true;
1311
+ isTransparent = true;
1312
+ }
1313
+ }
1314
+ if (attrName === 'fill') {
1315
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1316
+ stintSet(data, '__isTransparentFill', isTransparent);
1317
+ }
1318
+ else {
1319
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1320
+ stintSet(data, '__isTransparentStroke', isTransparent);
1321
+ }
1340
1322
  }
1341
1323
  function getLeafPaint(attrName, paint, ui) {
1342
1324
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1343
1325
  return undefined;
1326
+ let data;
1344
1327
  const { boxBounds } = ui.__layout;
1345
1328
  switch (paint.type) {
1346
- case 'solid':
1347
- let { type, blendMode, color, opacity } = paint;
1348
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
1349
1329
  case 'image':
1350
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1330
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1331
+ break;
1351
1332
  case 'linear':
1352
- return draw.PaintGradient.linearGradient(paint, boxBounds);
1333
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
1334
+ break;
1353
1335
  case 'radial':
1354
- return draw.PaintGradient.radialGradient(paint, boxBounds);
1336
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
1337
+ break;
1355
1338
  case 'angular':
1356
- return draw.PaintGradient.conicGradient(paint, boxBounds);
1339
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
1340
+ break;
1341
+ case 'solid':
1342
+ const { type, blendMode, color, opacity } = paint;
1343
+ data = { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
1344
+ break;
1357
1345
  default:
1358
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
1346
+ if (paint.r !== undefined)
1347
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
1348
+ }
1349
+ if (data) {
1350
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1351
+ data.isTransparent = true;
1352
+ if (paint.blendMode)
1353
+ data.blendMode = paint.blendMode;
1359
1354
  }
1355
+ return data;
1360
1356
  }
1361
1357
 
1362
1358
  const PaintModule = {
@@ -1422,12 +1418,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1422
1418
 
1423
1419
  const { get: get$2, translate } = core.MatrixHelper;
1424
1420
  const tempBox = new core.Bounds();
1425
- const tempPoint = {};
1426
1421
  const tempScaleData = {};
1422
+ const tempImage = {};
1427
1423
  function createData(leafPaint, image, paint, box) {
1428
- const { blendMode, changeful, sync } = paint;
1429
- if (blendMode)
1430
- leafPaint.blendMode = blendMode;
1424
+ const { changeful, sync } = paint;
1431
1425
  if (changeful)
1432
1426
  leafPaint.changeful = changeful;
1433
1427
  if (sync)
@@ -1435,38 +1429,38 @@ function createData(leafPaint, image, paint, box) {
1435
1429
  leafPaint.data = getPatternData(paint, box, image);
1436
1430
  }
1437
1431
  function getPatternData(paint, box, image) {
1438
- let { width, height } = image;
1439
1432
  if (paint.padding)
1440
1433
  box = tempBox.set(box).shrink(paint.padding);
1441
1434
  if (paint.mode === 'strench')
1442
1435
  paint.mode = 'stretch';
1436
+ let { width, height } = image;
1443
1437
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1444
1438
  const sameBox = box.width === width && box.height === height;
1445
1439
  const data = { mode };
1446
1440
  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;
1441
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1442
+ let scaleX, scaleY;
1449
1443
  if (!mode || mode === 'cover' || mode === 'fit') {
1450
1444
  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;
1445
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1446
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1447
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1454
1448
  }
1455
1449
  }
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;
1450
+ else {
1451
+ if (scale || size) {
1452
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1453
+ scaleX = tempScaleData.scaleX;
1454
+ scaleY = tempScaleData.scaleY;
1455
+ }
1456
+ if (align) {
1457
+ if (scaleX)
1458
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1459
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1460
+ }
1467
1461
  }
1468
1462
  if (offset)
1469
- x += offset.x, y += offset.y;
1463
+ core.PointHelper.move(tempImage, offset);
1470
1464
  switch (mode) {
1471
1465
  case 'stretch':
1472
1466
  if (!sameBox)
@@ -1474,12 +1468,12 @@ function getPatternData(paint, box, image) {
1474
1468
  break;
1475
1469
  case 'normal':
1476
1470
  case 'clip':
1477
- if (x || y || scaleX || rotation)
1478
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1471
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1472
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1479
1473
  break;
1480
1474
  case 'repeat':
1481
1475
  if (!sameBox || scaleX || rotation)
1482
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1476
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1483
1477
  if (!repeat)
1484
1478
  data.repeat = 'repeat';
1485
1479
  break;
@@ -1487,7 +1481,7 @@ function getPatternData(paint, box, image) {
1487
1481
  case 'cover':
1488
1482
  default:
1489
1483
  if (scaleX)
1490
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1484
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1491
1485
  }
1492
1486
  if (!data.transform) {
1493
1487
  if (box.x || box.y) {
@@ -1520,6 +1514,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1520
1514
  }
1521
1515
  else {
1522
1516
  leafPaint = { type: paint.type, image };
1517
+ if (image.hasAlphaPixel)
1518
+ leafPaint.isTransparent = true;
1523
1519
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1524
1520
  }
1525
1521
  if (firstUse || image.loading)
@@ -1544,7 +1540,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1544
1540
  ignoreRender(ui, false);
1545
1541
  if (!ui.destroyed) {
1546
1542
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1547
- if (image.hasOpacityPixel)
1543
+ if (image.hasAlphaPixel)
1548
1544
  ui.__layout.hitCanvasChanged = true;
1549
1545
  ui.forceUpdate('surface');
1550
1546
  }
@@ -1556,13 +1552,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1556
1552
  onLoadError(ui, event, error);
1557
1553
  leafPaint.loadId = null;
1558
1554
  });
1559
- if (ui.placeholderColor)
1560
- setTimeout(() => {
1561
- if (!(image.ready || image.isPlacehold)) {
1562
- image.isPlacehold = true;
1563
- ui.forceUpdate('surface');
1564
- }
1565
- }, 100);
1555
+ if (ui.placeholderColor) {
1556
+ if (!ui.placeholderDelay)
1557
+ image.isPlacehold = true;
1558
+ else
1559
+ setTimeout(() => {
1560
+ if (!image.ready) {
1561
+ image.isPlacehold = true;
1562
+ ui.forceUpdate('surface');
1563
+ }
1564
+ }, ui.placeholderDelay);
1565
+ }
1566
1566
  }
1567
1567
  return leafPaint;
1568
1568
  }
@@ -1800,32 +1800,33 @@ const PaintImageModule = {
1800
1800
  repeatMode
1801
1801
  };
1802
1802
 
1803
- const { toPoint: toPoint$2 } = core.AroundHelper;
1803
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1804
1804
  const realFrom$2 = {};
1805
1805
  const realTo$2 = {};
1806
1806
  function linearGradient(paint, box) {
1807
- let { from, to, type, blendMode, opacity } = paint;
1807
+ let { from, to, type, opacity } = paint;
1808
1808
  toPoint$2(from || 'top', box, realFrom$2);
1809
1809
  toPoint$2(to || 'bottom', box, realTo$2);
1810
1810
  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
1811
  const data = { type, style };
1813
- if (blendMode)
1814
- data.blendMode = blendMode;
1812
+ applyStops(data, style, paint.stops, opacity);
1815
1813
  return data;
1816
1814
  }
1817
- function applyStops(gradient, stops, opacity) {
1815
+ function applyStops(data, gradient, stops, opacity) {
1818
1816
  if (stops) {
1819
- let stop;
1817
+ let stop, color, offset, isTransparent;
1820
1818
  for (let i = 0, len = stops.length; i < len; i++) {
1821
1819
  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
- }
1820
+ if (typeof stop === 'string')
1821
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1822
+ else
1823
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1824
+ gradient.addColorStop(offset, color);
1825
+ if (!isTransparent && hasTransparent(color))
1826
+ isTransparent = true;
1828
1827
  }
1828
+ if (isTransparent)
1829
+ data.isTransparent = true;
1829
1830
  }
1830
1831
  }
1831
1832
 
@@ -1835,17 +1836,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1835
1836
  const realFrom$1 = {};
1836
1837
  const realTo$1 = {};
1837
1838
  function radialGradient(paint, box) {
1838
- let { from, to, type, opacity, blendMode, stretch } = paint;
1839
+ let { from, to, type, opacity, stretch } = paint;
1839
1840
  toPoint$1(from || 'center', box, realFrom$1);
1840
1841
  toPoint$1(to || 'bottom', box, realTo$1);
1841
1842
  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
1843
  const data = { type, style };
1844
+ applyStops(data, style, paint.stops, opacity);
1844
1845
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1845
1846
  if (transform)
1846
1847
  data.transform = transform;
1847
- if (blendMode)
1848
- data.blendMode = blendMode;
1849
1848
  return data;
1850
1849
  }
1851
1850
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1871,17 +1870,15 @@ const { toPoint } = core.AroundHelper;
1871
1870
  const realFrom = {};
1872
1871
  const realTo = {};
1873
1872
  function conicGradient(paint, box) {
1874
- let { from, to, type, opacity, blendMode, stretch } = paint;
1873
+ let { from, to, type, opacity, stretch } = paint;
1875
1874
  toPoint(from || 'center', box, realFrom);
1876
1875
  toPoint(to || 'bottom', box, realTo);
1877
1876
  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
1877
  const data = { type, style };
1878
+ applyStops(data, style, paint.stops, opacity);
1880
1879
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1881
1880
  if (transform)
1882
1881
  data.transform = transform;
1883
- if (blendMode)
1884
- data.blendMode = blendMode;
1885
1882
  return data;
1886
1883
  }
1887
1884
 
@@ -2214,6 +2211,8 @@ function createRows(drawData, content, style) {
2214
2211
  lastCharType = null;
2215
2212
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
2216
2213
  word = { data: [] }, row = { words: [] };
2214
+ if (__letterSpacing)
2215
+ content = [...content];
2217
2216
  for (let i = 0, len = content.length; i < len; i++) {
2218
2217
  char = content[i];
2219
2218
  if (char === '\n') {