@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.
@@ -1,9 +1,9 @@
1
- import { LeaferCanvasBase, Platform, canvasPatch, DataHelper, canvasSizeAttrs, ResizeEvent, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, BoundsHelper, Plugin, MatrixHelper, MathHelper, AlignHelper, ImageEvent, AroundHelper, PointHelper, Direction4 } from '@leafer/core';
1
+ import { LeaferCanvasBase, Platform, canvasPatch, DataHelper, canvasSizeAttrs, ResizeEvent, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, BoundsHelper, Plugin, MatrixHelper, MathHelper, AlignHelper, PointHelper, ImageEvent, AroundHelper, Direction4 } from '@leafer/core';
2
2
  export * from '@leafer/core';
3
3
  export { LeaferImage } from '@leafer/core';
4
- import { InteractionHelper, InteractionBase, HitCanvasManager } from '@leafer-ui/core';
4
+ import { InteractionHelper, InteractionBase, Platform as Platform$1, HitCanvasManager } from '@leafer-ui/core';
5
5
  export * from '@leafer-ui/core';
6
- import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect, Leafer } from '@leafer-ui/draw';
6
+ import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint as Paint$1, Effect, Leafer } from '@leafer-ui/draw';
7
7
 
8
8
  class LeaferCanvas extends LeaferCanvasBase {
9
9
  get allowBackgroundColor() { return false; }
@@ -301,17 +301,15 @@ class Watcher {
301
301
  this.target.emitEvent(new WatchEvent(WatchEvent.DATA, { updatedList: this.updatedList }));
302
302
  this.__updatedList = new LeafList();
303
303
  this.totalTimes++;
304
- this.changed = false;
305
- this.hasVisible = false;
306
- this.hasRemove = false;
307
- this.hasAdd = false;
304
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
308
305
  }
309
306
  __listenEvents() {
310
- const { target } = this;
311
307
  this.__eventIds = [
312
- target.on_(PropertyEvent.CHANGE, this.__onAttrChange, this),
313
- target.on_([ChildEvent.ADD, ChildEvent.REMOVE], this.__onChildEvent, this),
314
- target.on_(WatchEvent.REQUEST, this.__onRquestData, this)
308
+ this.target.on_([
309
+ [PropertyEvent.CHANGE, this.__onAttrChange, this],
310
+ [[ChildEvent.ADD, ChildEvent.REMOVE], this.__onChildEvent, this],
311
+ [WatchEvent.REQUEST, this.__onRquestData, this]
312
+ ])
315
313
  ];
316
314
  }
317
315
  __removeListenEvents() {
@@ -321,8 +319,7 @@ class Watcher {
321
319
  if (this.target) {
322
320
  this.stop();
323
321
  this.__removeListenEvents();
324
- this.target = null;
325
- this.__updatedList = null;
322
+ this.target = this.__updatedList = null;
326
323
  }
327
324
  }
328
325
  }
@@ -427,7 +424,7 @@ class Layouter {
427
424
  this.disabled = true;
428
425
  }
429
426
  layout() {
430
- if (!this.running)
427
+ if (this.layouting || !this.running)
431
428
  return;
432
429
  const { target } = this;
433
430
  this.times = 0;
@@ -510,12 +507,10 @@ class Layouter {
510
507
  }
511
508
  static fullLayout(target) {
512
509
  updateAllMatrix(target, true);
513
- if (target.isBranch) {
510
+ if (target.isBranch)
514
511
  BranchHelper.updateBounds(target);
515
- }
516
- else {
512
+ else
517
513
  LeafHelper.updateBounds(target);
518
- }
519
514
  updateAllChange(target);
520
515
  }
521
516
  addExtra(leaf) {
@@ -538,11 +533,12 @@ class Layouter {
538
533
  this.__updatedList = event.data.updatedList;
539
534
  }
540
535
  __listenEvents() {
541
- const { target } = this;
542
536
  this.__eventIds = [
543
- target.on_(LayoutEvent.REQUEST, this.layout, this),
544
- target.on_(LayoutEvent.AGAIN, this.layoutAgain, this),
545
- target.on_(WatchEvent.DATA, this.__onReceiveWatchData, this)
537
+ this.target.on_([
538
+ [LayoutEvent.REQUEST, this.layout, this],
539
+ [LayoutEvent.AGAIN, this.layoutAgain, this],
540
+ [WatchEvent.DATA, this.__onReceiveWatchData, this]
541
+ ])
546
542
  ];
547
543
  }
548
544
  __removeListenEvents() {
@@ -773,12 +769,13 @@ class Renderer {
773
769
  this.target.emitEvent(new RenderEvent(type, this.times, bounds, options));
774
770
  }
775
771
  __listenEvents() {
776
- const { target } = this;
777
772
  this.__eventIds = [
778
- target.on_(RenderEvent.REQUEST, this.update, this),
779
- target.on_(LayoutEvent.END, this.__onLayoutEnd, this),
780
- target.on_(RenderEvent.AGAIN, this.renderAgain, this),
781
- target.on_(ResizeEvent.RESIZE, this.__onResize, this)
773
+ this.target.on_([
774
+ [RenderEvent.REQUEST, this.update, this],
775
+ [LayoutEvent.END, this.__onLayoutEnd, this],
776
+ [RenderEvent.AGAIN, this.renderAgain, this],
777
+ [ResizeEvent.RESIZE, this.__onResize, this]
778
+ ])
782
779
  ];
783
780
  }
784
781
  __removeListenEvents() {
@@ -1126,32 +1123,34 @@ function fillPathOrText(ui, canvas) {
1126
1123
  ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1127
1124
  }
1128
1125
 
1126
+ const Paint = {};
1127
+
1129
1128
  function strokeText(stroke, ui, canvas) {
1130
- const { strokeAlign } = ui.__;
1131
- const isStrokes = typeof stroke !== 'string';
1132
- switch (strokeAlign) {
1129
+ switch (ui.__.strokeAlign) {
1133
1130
  case 'center':
1134
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1135
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1131
+ drawCenter$1(stroke, 1, ui, canvas);
1136
1132
  break;
1137
1133
  case 'inside':
1138
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
1134
+ drawAlign(stroke, 'inside', ui, canvas);
1139
1135
  break;
1140
1136
  case 'outside':
1141
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
1137
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
1142
1138
  break;
1143
1139
  }
1144
1140
  }
1145
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
1146
- const { __strokeWidth, __font } = ui.__;
1141
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1142
+ const data = ui.__;
1143
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
1144
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1145
+ }
1146
+ function drawAlign(stroke, align, ui, canvas) {
1147
1147
  const out = canvas.getSameCanvas(true, true);
1148
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
1149
- out.font = __font;
1150
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1148
+ out.font = ui.__.__font;
1149
+ drawCenter$1(stroke, 2, ui, out);
1151
1150
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1152
1151
  fillText(ui, out);
1153
1152
  out.blendMode = 'normal';
1154
- if (ui.__worldFlipped)
1153
+ if (ui.__worldFlipped || Platform$1.fullImageShadow)
1155
1154
  canvas.copyWorldByReset(out, ui.__nowWorld);
1156
1155
  else
1157
1156
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
@@ -1193,90 +1192,60 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
1193
1192
  }
1194
1193
 
1195
1194
  function stroke(stroke, ui, canvas) {
1196
- const options = ui.__;
1197
- const { __strokeWidth, strokeAlign, __font } = options;
1198
- if (!__strokeWidth)
1195
+ const data = ui.__;
1196
+ if (!data.__strokeWidth)
1199
1197
  return;
1200
- if (__font) {
1198
+ if (data.__font) {
1201
1199
  strokeText(stroke, ui, canvas);
1202
1200
  }
1203
1201
  else {
1204
- switch (strokeAlign) {
1202
+ switch (data.strokeAlign) {
1205
1203
  case 'center':
1206
- canvas.setStroke(stroke, __strokeWidth, options);
1207
- canvas.stroke();
1208
- if (options.__useArrow)
1209
- strokeArrow(ui, canvas);
1204
+ drawCenter(stroke, 1, ui, canvas);
1210
1205
  break;
1211
1206
  case 'inside':
1212
- canvas.save();
1213
- canvas.setStroke(stroke, __strokeWidth * 2, options);
1214
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1215
- canvas.stroke();
1216
- canvas.restore();
1207
+ drawInside(stroke, ui, canvas);
1217
1208
  break;
1218
1209
  case 'outside':
1219
- const out = canvas.getSameCanvas(true, true);
1220
- out.setStroke(stroke, __strokeWidth * 2, options);
1221
- ui.__drawRenderPath(out);
1222
- out.stroke();
1223
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1224
- out.clearWorld(ui.__layout.renderBounds);
1225
- if (ui.__worldFlipped)
1226
- canvas.copyWorldByReset(out, ui.__nowWorld);
1227
- else
1228
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1229
- out.recycle(ui.__nowWorld);
1210
+ drawOutside(stroke, ui, canvas);
1230
1211
  break;
1231
1212
  }
1232
1213
  }
1233
1214
  }
1234
1215
  function strokes(strokes, ui, canvas) {
1235
- const options = ui.__;
1236
- const { __strokeWidth, strokeAlign, __font } = options;
1237
- if (!__strokeWidth)
1238
- return;
1239
- if (__font) {
1240
- 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
+ Paint.strokeArrow(stroke, ui, canvas);
1224
+ }
1225
+ function drawInside(stroke, ui, canvas) {
1226
+ const data = ui.__;
1227
+ canvas.save();
1228
+ data.windingRule ? canvas.clip(data.windingRule) : canvas.clip();
1229
+ drawCenter(stroke, 2, ui, canvas);
1230
+ canvas.restore();
1231
+ }
1232
+ function drawOutside(stroke, ui, canvas) {
1233
+ const data = ui.__;
1234
+ if (data.__fillAfterStroke) {
1235
+ drawCenter(stroke, 2, ui, canvas);
1241
1236
  }
1242
1237
  else {
1243
- switch (strokeAlign) {
1244
- case 'center':
1245
- canvas.setStroke(undefined, __strokeWidth, options);
1246
- drawStrokesStyle(strokes, false, ui, canvas);
1247
- if (options.__useArrow)
1248
- strokeArrow(ui, canvas);
1249
- break;
1250
- case 'inside':
1251
- canvas.save();
1252
- canvas.setStroke(undefined, __strokeWidth * 2, options);
1253
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1254
- drawStrokesStyle(strokes, false, ui, canvas);
1255
- canvas.restore();
1256
- break;
1257
- case 'outside':
1258
- const { renderBounds } = ui.__layout;
1259
- const out = canvas.getSameCanvas(true, true);
1260
- ui.__drawRenderPath(out);
1261
- out.setStroke(undefined, __strokeWidth * 2, options);
1262
- drawStrokesStyle(strokes, false, ui, out);
1263
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1264
- out.clearWorld(renderBounds);
1265
- if (ui.__worldFlipped)
1266
- canvas.copyWorldByReset(out, ui.__nowWorld);
1267
- else
1268
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1269
- out.recycle(ui.__nowWorld);
1270
- break;
1271
- }
1272
- }
1273
- }
1274
- function strokeArrow(ui, canvas) {
1275
- if (ui.__.dashPattern) {
1276
- canvas.beginPath();
1277
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
1278
- canvas.dashPattern = null;
1279
- canvas.stroke();
1238
+ const { renderBounds } = ui.__layout;
1239
+ const out = canvas.getSameCanvas(true, true);
1240
+ ui.__drawRenderPath(out);
1241
+ drawCenter(stroke, 2, ui, out);
1242
+ data.windingRule ? out.clip(data.windingRule) : out.clip();
1243
+ out.clearWorld(renderBounds);
1244
+ if (ui.__worldFlipped || Platform$1.fullImageShadow)
1245
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1246
+ else
1247
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1248
+ out.recycle(ui.__nowWorld);
1280
1249
  }
1281
1250
  }
1282
1251
 
@@ -1323,9 +1292,10 @@ function shape(ui, current, options) {
1323
1292
  }
1324
1293
 
1325
1294
  let recycleMap;
1295
+ const { stintSet } = DataHelper, { hasTransparent: hasTransparent$1 } = ColorConvert;
1326
1296
  function compute(attrName, ui) {
1327
1297
  const data = ui.__, leafPaints = [];
1328
- let paints = data.__input[attrName], hasOpacityPixel;
1298
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1329
1299
  if (!(paints instanceof Array))
1330
1300
  paints = [paints];
1331
1301
  recycleMap = PaintImage.recycleImage(attrName, data);
@@ -1335,29 +1305,55 @@ function compute(attrName, ui) {
1335
1305
  leafPaints.push(item);
1336
1306
  }
1337
1307
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1338
- if (leafPaints.length && leafPaints[0].image)
1339
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1340
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
1308
+ if (leafPaints.length) {
1309
+ if (leafPaints.every(item => item.isTransparent)) {
1310
+ if (leafPaints.some(item => item.image))
1311
+ isAlphaPixel = true;
1312
+ isTransparent = true;
1313
+ }
1314
+ }
1315
+ if (attrName === 'fill') {
1316
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1317
+ stintSet(data, '__isTransparentFill', isTransparent);
1318
+ }
1319
+ else {
1320
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1321
+ stintSet(data, '__isTransparentStroke', isTransparent);
1322
+ }
1341
1323
  }
1342
1324
  function getLeafPaint(attrName, paint, ui) {
1343
1325
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1344
1326
  return undefined;
1327
+ let data;
1345
1328
  const { boxBounds } = ui.__layout;
1346
1329
  switch (paint.type) {
1347
- case 'solid':
1348
- let { type, blendMode, color, opacity } = paint;
1349
- return { type, blendMode, style: ColorConvert.string(color, opacity) };
1350
1330
  case 'image':
1351
- return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1331
+ data = PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1332
+ break;
1352
1333
  case 'linear':
1353
- return PaintGradient.linearGradient(paint, boxBounds);
1334
+ data = PaintGradient.linearGradient(paint, boxBounds);
1335
+ break;
1354
1336
  case 'radial':
1355
- return PaintGradient.radialGradient(paint, boxBounds);
1337
+ data = PaintGradient.radialGradient(paint, boxBounds);
1338
+ break;
1356
1339
  case 'angular':
1357
- return PaintGradient.conicGradient(paint, boxBounds);
1340
+ data = PaintGradient.conicGradient(paint, boxBounds);
1341
+ break;
1342
+ case 'solid':
1343
+ const { type, blendMode, color, opacity } = paint;
1344
+ data = { type, blendMode, style: ColorConvert.string(color, opacity) };
1345
+ break;
1358
1346
  default:
1359
- return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
1347
+ if (paint.r !== undefined)
1348
+ data = { type: 'solid', style: ColorConvert.string(paint) };
1349
+ }
1350
+ if (data) {
1351
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1352
+ data.isTransparent = true;
1353
+ if (paint.blendMode)
1354
+ data.blendMode = paint.blendMode;
1360
1355
  }
1356
+ return data;
1361
1357
  }
1362
1358
 
1363
1359
  const PaintModule = {
@@ -1423,12 +1419,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1423
1419
 
1424
1420
  const { get: get$2, translate } = MatrixHelper;
1425
1421
  const tempBox = new Bounds();
1426
- const tempPoint = {};
1427
1422
  const tempScaleData = {};
1423
+ const tempImage = {};
1428
1424
  function createData(leafPaint, image, paint, box) {
1429
- const { blendMode, changeful, sync } = paint;
1430
- if (blendMode)
1431
- leafPaint.blendMode = blendMode;
1425
+ const { changeful, sync } = paint;
1432
1426
  if (changeful)
1433
1427
  leafPaint.changeful = changeful;
1434
1428
  if (sync)
@@ -1436,38 +1430,38 @@ function createData(leafPaint, image, paint, box) {
1436
1430
  leafPaint.data = getPatternData(paint, box, image);
1437
1431
  }
1438
1432
  function getPatternData(paint, box, image) {
1439
- let { width, height } = image;
1440
1433
  if (paint.padding)
1441
1434
  box = tempBox.set(box).shrink(paint.padding);
1442
1435
  if (paint.mode === 'strench')
1443
1436
  paint.mode = 'stretch';
1437
+ let { width, height } = image;
1444
1438
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1445
1439
  const sameBox = box.width === width && box.height === height;
1446
1440
  const data = { mode };
1447
1441
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1448
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1449
- let x = 0, y = 0, scaleX, scaleY;
1442
+ BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1443
+ let scaleX, scaleY;
1450
1444
  if (!mode || mode === 'cover' || mode === 'fit') {
1451
1445
  if (!sameBox || rotation) {
1452
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1453
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1454
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1446
+ scaleX = scaleY = BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1447
+ BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1448
+ BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1455
1449
  }
1456
1450
  }
1457
- else if (scale || size) {
1458
- MathHelper.getScaleData(scale, size, image, tempScaleData);
1459
- scaleX = tempScaleData.scaleX;
1460
- scaleY = tempScaleData.scaleY;
1461
- }
1462
- if (align) {
1463
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1464
- if (scaleX)
1465
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1466
- AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1467
- x += tempPoint.x, y += tempPoint.y;
1451
+ else {
1452
+ if (scale || size) {
1453
+ MathHelper.getScaleData(scale, size, image, tempScaleData);
1454
+ scaleX = tempScaleData.scaleX;
1455
+ scaleY = tempScaleData.scaleY;
1456
+ }
1457
+ if (align) {
1458
+ if (scaleX)
1459
+ BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1460
+ AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1461
+ }
1468
1462
  }
1469
1463
  if (offset)
1470
- x += offset.x, y += offset.y;
1464
+ PointHelper.move(tempImage, offset);
1471
1465
  switch (mode) {
1472
1466
  case 'stretch':
1473
1467
  if (!sameBox)
@@ -1475,12 +1469,12 @@ function getPatternData(paint, box, image) {
1475
1469
  break;
1476
1470
  case 'normal':
1477
1471
  case 'clip':
1478
- if (x || y || scaleX || rotation)
1479
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1472
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1473
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1480
1474
  break;
1481
1475
  case 'repeat':
1482
1476
  if (!sameBox || scaleX || rotation)
1483
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1477
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1484
1478
  if (!repeat)
1485
1479
  data.repeat = 'repeat';
1486
1480
  break;
@@ -1488,7 +1482,7 @@ function getPatternData(paint, box, image) {
1488
1482
  case 'cover':
1489
1483
  default:
1490
1484
  if (scaleX)
1491
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1485
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1492
1486
  }
1493
1487
  if (!data.transform) {
1494
1488
  if (box.x || box.y) {
@@ -1521,6 +1515,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1521
1515
  }
1522
1516
  else {
1523
1517
  leafPaint = { type: paint.type, image };
1518
+ if (image.hasAlphaPixel)
1519
+ leafPaint.isTransparent = true;
1524
1520
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1525
1521
  }
1526
1522
  if (firstUse || image.loading)
@@ -1545,7 +1541,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1545
1541
  ignoreRender(ui, false);
1546
1542
  if (!ui.destroyed) {
1547
1543
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1548
- if (image.hasOpacityPixel)
1544
+ if (image.hasAlphaPixel)
1549
1545
  ui.__layout.hitCanvasChanged = true;
1550
1546
  ui.forceUpdate('surface');
1551
1547
  }
@@ -1557,13 +1553,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1557
1553
  onLoadError(ui, event, error);
1558
1554
  leafPaint.loadId = null;
1559
1555
  });
1560
- if (ui.placeholderColor)
1561
- setTimeout(() => {
1562
- if (!(image.ready || image.isPlacehold)) {
1563
- image.isPlacehold = true;
1564
- ui.forceUpdate('surface');
1565
- }
1566
- }, 100);
1556
+ if (ui.placeholderColor) {
1557
+ if (!ui.placeholderDelay)
1558
+ image.isPlacehold = true;
1559
+ else
1560
+ setTimeout(() => {
1561
+ if (!image.ready) {
1562
+ image.isPlacehold = true;
1563
+ ui.forceUpdate('surface');
1564
+ }
1565
+ }, ui.placeholderDelay);
1566
+ }
1567
1567
  }
1568
1568
  return leafPaint;
1569
1569
  }
@@ -1801,32 +1801,33 @@ const PaintImageModule = {
1801
1801
  repeatMode
1802
1802
  };
1803
1803
 
1804
- const { toPoint: toPoint$2 } = AroundHelper;
1804
+ const { toPoint: toPoint$2 } = AroundHelper, { hasTransparent } = ColorConvert;
1805
1805
  const realFrom$2 = {};
1806
1806
  const realTo$2 = {};
1807
1807
  function linearGradient(paint, box) {
1808
- let { from, to, type, blendMode, opacity } = paint;
1808
+ let { from, to, type, opacity } = paint;
1809
1809
  toPoint$2(from || 'top', box, realFrom$2);
1810
1810
  toPoint$2(to || 'bottom', box, realTo$2);
1811
1811
  const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1812
- applyStops(style, paint.stops, opacity);
1813
1812
  const data = { type, style };
1814
- if (blendMode)
1815
- data.blendMode = blendMode;
1813
+ applyStops(data, style, paint.stops, opacity);
1816
1814
  return data;
1817
1815
  }
1818
- function applyStops(gradient, stops, opacity) {
1816
+ function applyStops(data, gradient, stops, opacity) {
1819
1817
  if (stops) {
1820
- let stop;
1818
+ let stop, color, offset, isTransparent;
1821
1819
  for (let i = 0, len = stops.length; i < len; i++) {
1822
1820
  stop = stops[i];
1823
- if (typeof stop === 'string') {
1824
- gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
1825
- }
1826
- else {
1827
- gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
1828
- }
1821
+ if (typeof stop === 'string')
1822
+ offset = i / (len - 1), color = ColorConvert.string(stop, opacity);
1823
+ else
1824
+ offset = stop.offset, color = ColorConvert.string(stop.color, opacity);
1825
+ gradient.addColorStop(offset, color);
1826
+ if (!isTransparent && hasTransparent(color))
1827
+ isTransparent = true;
1829
1828
  }
1829
+ if (isTransparent)
1830
+ data.isTransparent = true;
1830
1831
  }
1831
1832
  }
1832
1833
 
@@ -1836,17 +1837,15 @@ const { toPoint: toPoint$1 } = AroundHelper;
1836
1837
  const realFrom$1 = {};
1837
1838
  const realTo$1 = {};
1838
1839
  function radialGradient(paint, box) {
1839
- let { from, to, type, opacity, blendMode, stretch } = paint;
1840
+ let { from, to, type, opacity, stretch } = paint;
1840
1841
  toPoint$1(from || 'center', box, realFrom$1);
1841
1842
  toPoint$1(to || 'bottom', box, realTo$1);
1842
1843
  const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1843
- applyStops(style, paint.stops, opacity);
1844
1844
  const data = { type, style };
1845
+ applyStops(data, style, paint.stops, opacity);
1845
1846
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1846
1847
  if (transform)
1847
1848
  data.transform = transform;
1848
- if (blendMode)
1849
- data.blendMode = blendMode;
1850
1849
  return data;
1851
1850
  }
1852
1851
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1872,17 +1871,15 @@ const { toPoint } = AroundHelper;
1872
1871
  const realFrom = {};
1873
1872
  const realTo = {};
1874
1873
  function conicGradient(paint, box) {
1875
- let { from, to, type, opacity, blendMode, stretch } = paint;
1874
+ let { from, to, type, opacity, stretch } = paint;
1876
1875
  toPoint(from || 'center', box, realFrom);
1877
1876
  toPoint(to || 'bottom', box, realTo);
1878
1877
  const style = Platform.conicGradientSupport ? Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo));
1879
- applyStops(style, paint.stops, opacity);
1880
1878
  const data = { type, style };
1879
+ applyStops(data, style, paint.stops, opacity);
1881
1880
  const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
1882
1881
  if (transform)
1883
1882
  data.transform = transform;
1884
- if (blendMode)
1885
- data.blendMode = blendMode;
1886
1883
  return data;
1887
1884
  }
1888
1885
 
@@ -2215,6 +2212,8 @@ function createRows(drawData, content, style) {
2215
2212
  lastCharType = null;
2216
2213
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
2217
2214
  word = { data: [] }, row = { words: [] };
2215
+ if (__letterSpacing)
2216
+ content = [...content];
2218
2217
  for (let i = 0, len = content.length; i < len; i++) {
2219
2218
  char = content[i];
2220
2219
  if (char === '\n') {
@@ -2621,7 +2620,7 @@ const ColorConvertModule = {
2621
2620
 
2622
2621
  Object.assign(TextConvert, TextConvertModule);
2623
2622
  Object.assign(ColorConvert, ColorConvertModule);
2624
- Object.assign(Paint, PaintModule);
2623
+ Object.assign(Paint$1, PaintModule);
2625
2624
  Object.assign(PaintImage, PaintImageModule);
2626
2625
  Object.assign(PaintGradient, PaintGradientModule);
2627
2626
  Object.assign(Effect, EffectModule);