@leafer-draw/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,8 +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, 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, 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 { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect } from '@leafer-ui/draw';
4
+ import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint as Paint$1, Effect } from '@leafer-ui/draw';
5
5
  export * from '@leafer-ui/draw';
6
+ import { Platform as Platform$1 } from '@leafer-ui/core';
6
7
 
7
8
  class LeaferCanvas extends LeaferCanvasBase {
8
9
  get allowBackgroundColor() { return false; }
@@ -300,17 +301,15 @@ class Watcher {
300
301
  this.target.emitEvent(new WatchEvent(WatchEvent.DATA, { updatedList: this.updatedList }));
301
302
  this.__updatedList = new LeafList();
302
303
  this.totalTimes++;
303
- this.changed = false;
304
- this.hasVisible = false;
305
- this.hasRemove = false;
306
- this.hasAdd = false;
304
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
307
305
  }
308
306
  __listenEvents() {
309
- const { target } = this;
310
307
  this.__eventIds = [
311
- target.on_(PropertyEvent.CHANGE, this.__onAttrChange, this),
312
- target.on_([ChildEvent.ADD, ChildEvent.REMOVE], this.__onChildEvent, this),
313
- 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
+ ])
314
313
  ];
315
314
  }
316
315
  __removeListenEvents() {
@@ -320,8 +319,7 @@ class Watcher {
320
319
  if (this.target) {
321
320
  this.stop();
322
321
  this.__removeListenEvents();
323
- this.target = null;
324
- this.__updatedList = null;
322
+ this.target = this.__updatedList = null;
325
323
  }
326
324
  }
327
325
  }
@@ -426,7 +424,7 @@ class Layouter {
426
424
  this.disabled = true;
427
425
  }
428
426
  layout() {
429
- if (!this.running)
427
+ if (this.layouting || !this.running)
430
428
  return;
431
429
  const { target } = this;
432
430
  this.times = 0;
@@ -509,12 +507,10 @@ class Layouter {
509
507
  }
510
508
  static fullLayout(target) {
511
509
  updateAllMatrix(target, true);
512
- if (target.isBranch) {
510
+ if (target.isBranch)
513
511
  BranchHelper.updateBounds(target);
514
- }
515
- else {
512
+ else
516
513
  LeafHelper.updateBounds(target);
517
- }
518
514
  updateAllChange(target);
519
515
  }
520
516
  addExtra(leaf) {
@@ -537,11 +533,12 @@ class Layouter {
537
533
  this.__updatedList = event.data.updatedList;
538
534
  }
539
535
  __listenEvents() {
540
- const { target } = this;
541
536
  this.__eventIds = [
542
- target.on_(LayoutEvent.REQUEST, this.layout, this),
543
- target.on_(LayoutEvent.AGAIN, this.layoutAgain, this),
544
- 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
+ ])
545
542
  ];
546
543
  }
547
544
  __removeListenEvents() {
@@ -772,12 +769,13 @@ class Renderer {
772
769
  this.target.emitEvent(new RenderEvent(type, this.times, bounds, options));
773
770
  }
774
771
  __listenEvents() {
775
- const { target } = this;
776
772
  this.__eventIds = [
777
- target.on_(RenderEvent.REQUEST, this.update, this),
778
- target.on_(LayoutEvent.END, this.__onLayoutEnd, this),
779
- target.on_(RenderEvent.AGAIN, this.renderAgain, this),
780
- 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
+ ])
781
779
  ];
782
780
  }
783
781
  __removeListenEvents() {
@@ -863,32 +861,34 @@ function fillPathOrText(ui, canvas) {
863
861
  ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
864
862
  }
865
863
 
864
+ const Paint = {};
865
+
866
866
  function strokeText(stroke, ui, canvas) {
867
- const { strokeAlign } = ui.__;
868
- const isStrokes = typeof stroke !== 'string';
869
- switch (strokeAlign) {
867
+ switch (ui.__.strokeAlign) {
870
868
  case 'center':
871
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
872
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
869
+ drawCenter$1(stroke, 1, ui, canvas);
873
870
  break;
874
871
  case 'inside':
875
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
872
+ drawAlign(stroke, 'inside', ui, canvas);
876
873
  break;
877
874
  case 'outside':
878
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
875
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
879
876
  break;
880
877
  }
881
878
  }
882
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
883
- const { __strokeWidth, __font } = ui.__;
879
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
880
+ const data = ui.__;
881
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
882
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
883
+ }
884
+ function drawAlign(stroke, align, ui, canvas) {
884
885
  const out = canvas.getSameCanvas(true, true);
885
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
886
- out.font = __font;
887
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
886
+ out.font = ui.__.__font;
887
+ drawCenter$1(stroke, 2, ui, out);
888
888
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
889
889
  fillText(ui, out);
890
890
  out.blendMode = 'normal';
891
- if (ui.__worldFlipped)
891
+ if (ui.__worldFlipped || Platform$1.fullImageShadow)
892
892
  canvas.copyWorldByReset(out, ui.__nowWorld);
893
893
  else
894
894
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
@@ -930,90 +930,60 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
930
930
  }
931
931
 
932
932
  function stroke(stroke, ui, canvas) {
933
- const options = ui.__;
934
- const { __strokeWidth, strokeAlign, __font } = options;
935
- if (!__strokeWidth)
933
+ const data = ui.__;
934
+ if (!data.__strokeWidth)
936
935
  return;
937
- if (__font) {
936
+ if (data.__font) {
938
937
  strokeText(stroke, ui, canvas);
939
938
  }
940
939
  else {
941
- switch (strokeAlign) {
940
+ switch (data.strokeAlign) {
942
941
  case 'center':
943
- canvas.setStroke(stroke, __strokeWidth, options);
944
- canvas.stroke();
945
- if (options.__useArrow)
946
- strokeArrow(ui, canvas);
942
+ drawCenter(stroke, 1, ui, canvas);
947
943
  break;
948
944
  case 'inside':
949
- canvas.save();
950
- canvas.setStroke(stroke, __strokeWidth * 2, options);
951
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
952
- canvas.stroke();
953
- canvas.restore();
945
+ drawInside(stroke, ui, canvas);
954
946
  break;
955
947
  case 'outside':
956
- const out = canvas.getSameCanvas(true, true);
957
- out.setStroke(stroke, __strokeWidth * 2, options);
958
- ui.__drawRenderPath(out);
959
- out.stroke();
960
- options.windingRule ? out.clip(options.windingRule) : out.clip();
961
- out.clearWorld(ui.__layout.renderBounds);
962
- if (ui.__worldFlipped)
963
- canvas.copyWorldByReset(out, ui.__nowWorld);
964
- else
965
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
966
- out.recycle(ui.__nowWorld);
948
+ drawOutside(stroke, ui, canvas);
967
949
  break;
968
950
  }
969
951
  }
970
952
  }
971
953
  function strokes(strokes, ui, canvas) {
972
- const options = ui.__;
973
- const { __strokeWidth, strokeAlign, __font } = options;
974
- if (!__strokeWidth)
975
- return;
976
- if (__font) {
977
- strokeText(strokes, ui, canvas);
954
+ stroke(strokes, ui, canvas);
955
+ }
956
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
957
+ const data = ui.__;
958
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
959
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
960
+ if (data.__useArrow)
961
+ Paint.strokeArrow(stroke, ui, canvas);
962
+ }
963
+ function drawInside(stroke, ui, canvas) {
964
+ const data = ui.__;
965
+ canvas.save();
966
+ data.windingRule ? canvas.clip(data.windingRule) : canvas.clip();
967
+ drawCenter(stroke, 2, ui, canvas);
968
+ canvas.restore();
969
+ }
970
+ function drawOutside(stroke, ui, canvas) {
971
+ const data = ui.__;
972
+ if (data.__fillAfterStroke) {
973
+ drawCenter(stroke, 2, ui, canvas);
978
974
  }
979
975
  else {
980
- switch (strokeAlign) {
981
- case 'center':
982
- canvas.setStroke(undefined, __strokeWidth, options);
983
- drawStrokesStyle(strokes, false, ui, canvas);
984
- if (options.__useArrow)
985
- strokeArrow(ui, canvas);
986
- break;
987
- case 'inside':
988
- canvas.save();
989
- canvas.setStroke(undefined, __strokeWidth * 2, options);
990
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
991
- drawStrokesStyle(strokes, false, ui, canvas);
992
- canvas.restore();
993
- break;
994
- case 'outside':
995
- const { renderBounds } = ui.__layout;
996
- const out = canvas.getSameCanvas(true, true);
997
- ui.__drawRenderPath(out);
998
- out.setStroke(undefined, __strokeWidth * 2, options);
999
- drawStrokesStyle(strokes, false, ui, out);
1000
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1001
- out.clearWorld(renderBounds);
1002
- if (ui.__worldFlipped)
1003
- canvas.copyWorldByReset(out, ui.__nowWorld);
1004
- else
1005
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1006
- out.recycle(ui.__nowWorld);
1007
- break;
1008
- }
1009
- }
1010
- }
1011
- function strokeArrow(ui, canvas) {
1012
- if (ui.__.dashPattern) {
1013
- canvas.beginPath();
1014
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
1015
- canvas.dashPattern = null;
1016
- canvas.stroke();
976
+ const { renderBounds } = ui.__layout;
977
+ const out = canvas.getSameCanvas(true, true);
978
+ ui.__drawRenderPath(out);
979
+ drawCenter(stroke, 2, ui, out);
980
+ data.windingRule ? out.clip(data.windingRule) : out.clip();
981
+ out.clearWorld(renderBounds);
982
+ if (ui.__worldFlipped || Platform$1.fullImageShadow)
983
+ canvas.copyWorldByReset(out, ui.__nowWorld);
984
+ else
985
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
986
+ out.recycle(ui.__nowWorld);
1017
987
  }
1018
988
  }
1019
989
 
@@ -1060,9 +1030,10 @@ function shape(ui, current, options) {
1060
1030
  }
1061
1031
 
1062
1032
  let recycleMap;
1033
+ const { stintSet } = DataHelper, { hasTransparent: hasTransparent$1 } = ColorConvert;
1063
1034
  function compute(attrName, ui) {
1064
1035
  const data = ui.__, leafPaints = [];
1065
- let paints = data.__input[attrName], hasOpacityPixel;
1036
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1066
1037
  if (!(paints instanceof Array))
1067
1038
  paints = [paints];
1068
1039
  recycleMap = PaintImage.recycleImage(attrName, data);
@@ -1072,29 +1043,55 @@ function compute(attrName, ui) {
1072
1043
  leafPaints.push(item);
1073
1044
  }
1074
1045
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1075
- if (leafPaints.length && leafPaints[0].image)
1076
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1077
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
1046
+ if (leafPaints.length) {
1047
+ if (leafPaints.every(item => item.isTransparent)) {
1048
+ if (leafPaints.some(item => item.image))
1049
+ isAlphaPixel = true;
1050
+ isTransparent = true;
1051
+ }
1052
+ }
1053
+ if (attrName === 'fill') {
1054
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1055
+ stintSet(data, '__isTransparentFill', isTransparent);
1056
+ }
1057
+ else {
1058
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1059
+ stintSet(data, '__isTransparentStroke', isTransparent);
1060
+ }
1078
1061
  }
1079
1062
  function getLeafPaint(attrName, paint, ui) {
1080
1063
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1081
1064
  return undefined;
1065
+ let data;
1082
1066
  const { boxBounds } = ui.__layout;
1083
1067
  switch (paint.type) {
1084
- case 'solid':
1085
- let { type, blendMode, color, opacity } = paint;
1086
- return { type, blendMode, style: ColorConvert.string(color, opacity) };
1087
1068
  case 'image':
1088
- return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1069
+ data = PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1070
+ break;
1089
1071
  case 'linear':
1090
- return PaintGradient.linearGradient(paint, boxBounds);
1072
+ data = PaintGradient.linearGradient(paint, boxBounds);
1073
+ break;
1091
1074
  case 'radial':
1092
- return PaintGradient.radialGradient(paint, boxBounds);
1075
+ data = PaintGradient.radialGradient(paint, boxBounds);
1076
+ break;
1093
1077
  case 'angular':
1094
- return PaintGradient.conicGradient(paint, boxBounds);
1078
+ data = PaintGradient.conicGradient(paint, boxBounds);
1079
+ break;
1080
+ case 'solid':
1081
+ const { type, blendMode, color, opacity } = paint;
1082
+ data = { type, blendMode, style: ColorConvert.string(color, opacity) };
1083
+ break;
1095
1084
  default:
1096
- return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
1085
+ if (paint.r !== undefined)
1086
+ data = { type: 'solid', style: ColorConvert.string(paint) };
1087
+ }
1088
+ if (data) {
1089
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1090
+ data.isTransparent = true;
1091
+ if (paint.blendMode)
1092
+ data.blendMode = paint.blendMode;
1097
1093
  }
1094
+ return data;
1098
1095
  }
1099
1096
 
1100
1097
  const PaintModule = {
@@ -1160,12 +1157,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1160
1157
 
1161
1158
  const { get: get$2, translate } = MatrixHelper;
1162
1159
  const tempBox = new Bounds();
1163
- const tempPoint = {};
1164
1160
  const tempScaleData = {};
1161
+ const tempImage = {};
1165
1162
  function createData(leafPaint, image, paint, box) {
1166
- const { blendMode, changeful, sync } = paint;
1167
- if (blendMode)
1168
- leafPaint.blendMode = blendMode;
1163
+ const { changeful, sync } = paint;
1169
1164
  if (changeful)
1170
1165
  leafPaint.changeful = changeful;
1171
1166
  if (sync)
@@ -1173,38 +1168,38 @@ function createData(leafPaint, image, paint, box) {
1173
1168
  leafPaint.data = getPatternData(paint, box, image);
1174
1169
  }
1175
1170
  function getPatternData(paint, box, image) {
1176
- let { width, height } = image;
1177
1171
  if (paint.padding)
1178
1172
  box = tempBox.set(box).shrink(paint.padding);
1179
1173
  if (paint.mode === 'strench')
1180
1174
  paint.mode = 'stretch';
1175
+ let { width, height } = image;
1181
1176
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1182
1177
  const sameBox = box.width === width && box.height === height;
1183
1178
  const data = { mode };
1184
1179
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1185
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1186
- let x = 0, y = 0, scaleX, scaleY;
1180
+ BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1181
+ let scaleX, scaleY;
1187
1182
  if (!mode || mode === 'cover' || mode === 'fit') {
1188
1183
  if (!sameBox || rotation) {
1189
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1190
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1191
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1184
+ scaleX = scaleY = BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1185
+ BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1186
+ BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1192
1187
  }
1193
1188
  }
1194
- else if (scale || size) {
1195
- MathHelper.getScaleData(scale, size, image, tempScaleData);
1196
- scaleX = tempScaleData.scaleX;
1197
- scaleY = tempScaleData.scaleY;
1198
- }
1199
- if (align) {
1200
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1201
- if (scaleX)
1202
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1203
- AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1204
- x += tempPoint.x, y += tempPoint.y;
1189
+ else {
1190
+ if (scale || size) {
1191
+ MathHelper.getScaleData(scale, size, image, tempScaleData);
1192
+ scaleX = tempScaleData.scaleX;
1193
+ scaleY = tempScaleData.scaleY;
1194
+ }
1195
+ if (align) {
1196
+ if (scaleX)
1197
+ BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1198
+ AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1199
+ }
1205
1200
  }
1206
1201
  if (offset)
1207
- x += offset.x, y += offset.y;
1202
+ PointHelper.move(tempImage, offset);
1208
1203
  switch (mode) {
1209
1204
  case 'stretch':
1210
1205
  if (!sameBox)
@@ -1212,12 +1207,12 @@ function getPatternData(paint, box, image) {
1212
1207
  break;
1213
1208
  case 'normal':
1214
1209
  case 'clip':
1215
- if (x || y || scaleX || rotation)
1216
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1210
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1211
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1217
1212
  break;
1218
1213
  case 'repeat':
1219
1214
  if (!sameBox || scaleX || rotation)
1220
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1215
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1221
1216
  if (!repeat)
1222
1217
  data.repeat = 'repeat';
1223
1218
  break;
@@ -1225,7 +1220,7 @@ function getPatternData(paint, box, image) {
1225
1220
  case 'cover':
1226
1221
  default:
1227
1222
  if (scaleX)
1228
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1223
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1229
1224
  }
1230
1225
  if (!data.transform) {
1231
1226
  if (box.x || box.y) {
@@ -1258,6 +1253,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1258
1253
  }
1259
1254
  else {
1260
1255
  leafPaint = { type: paint.type, image };
1256
+ if (image.hasAlphaPixel)
1257
+ leafPaint.isTransparent = true;
1261
1258
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1262
1259
  }
1263
1260
  if (firstUse || image.loading)
@@ -1282,7 +1279,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1282
1279
  ignoreRender(ui, false);
1283
1280
  if (!ui.destroyed) {
1284
1281
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1285
- if (image.hasOpacityPixel)
1282
+ if (image.hasAlphaPixel)
1286
1283
  ui.__layout.hitCanvasChanged = true;
1287
1284
  ui.forceUpdate('surface');
1288
1285
  }
@@ -1294,13 +1291,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1294
1291
  onLoadError(ui, event, error);
1295
1292
  leafPaint.loadId = null;
1296
1293
  });
1297
- if (ui.placeholderColor)
1298
- setTimeout(() => {
1299
- if (!(image.ready || image.isPlacehold)) {
1300
- image.isPlacehold = true;
1301
- ui.forceUpdate('surface');
1302
- }
1303
- }, 100);
1294
+ if (ui.placeholderColor) {
1295
+ if (!ui.placeholderDelay)
1296
+ image.isPlacehold = true;
1297
+ else
1298
+ setTimeout(() => {
1299
+ if (!image.ready) {
1300
+ image.isPlacehold = true;
1301
+ ui.forceUpdate('surface');
1302
+ }
1303
+ }, ui.placeholderDelay);
1304
+ }
1304
1305
  }
1305
1306
  return leafPaint;
1306
1307
  }
@@ -1538,32 +1539,33 @@ const PaintImageModule = {
1538
1539
  repeatMode
1539
1540
  };
1540
1541
 
1541
- const { toPoint: toPoint$2 } = AroundHelper;
1542
+ const { toPoint: toPoint$2 } = AroundHelper, { hasTransparent } = ColorConvert;
1542
1543
  const realFrom$2 = {};
1543
1544
  const realTo$2 = {};
1544
1545
  function linearGradient(paint, box) {
1545
- let { from, to, type, blendMode, opacity } = paint;
1546
+ let { from, to, type, opacity } = paint;
1546
1547
  toPoint$2(from || 'top', box, realFrom$2);
1547
1548
  toPoint$2(to || 'bottom', box, realTo$2);
1548
1549
  const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1549
- applyStops(style, paint.stops, opacity);
1550
1550
  const data = { type, style };
1551
- if (blendMode)
1552
- data.blendMode = blendMode;
1551
+ applyStops(data, style, paint.stops, opacity);
1553
1552
  return data;
1554
1553
  }
1555
- function applyStops(gradient, stops, opacity) {
1554
+ function applyStops(data, gradient, stops, opacity) {
1556
1555
  if (stops) {
1557
- let stop;
1556
+ let stop, color, offset, isTransparent;
1558
1557
  for (let i = 0, len = stops.length; i < len; i++) {
1559
1558
  stop = stops[i];
1560
- if (typeof stop === 'string') {
1561
- gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
1562
- }
1563
- else {
1564
- gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
1565
- }
1559
+ if (typeof stop === 'string')
1560
+ offset = i / (len - 1), color = ColorConvert.string(stop, opacity);
1561
+ else
1562
+ offset = stop.offset, color = ColorConvert.string(stop.color, opacity);
1563
+ gradient.addColorStop(offset, color);
1564
+ if (!isTransparent && hasTransparent(color))
1565
+ isTransparent = true;
1566
1566
  }
1567
+ if (isTransparent)
1568
+ data.isTransparent = true;
1567
1569
  }
1568
1570
  }
1569
1571
 
@@ -1573,17 +1575,15 @@ const { toPoint: toPoint$1 } = AroundHelper;
1573
1575
  const realFrom$1 = {};
1574
1576
  const realTo$1 = {};
1575
1577
  function radialGradient(paint, box) {
1576
- let { from, to, type, opacity, blendMode, stretch } = paint;
1578
+ let { from, to, type, opacity, stretch } = paint;
1577
1579
  toPoint$1(from || 'center', box, realFrom$1);
1578
1580
  toPoint$1(to || 'bottom', box, realTo$1);
1579
1581
  const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1580
- applyStops(style, paint.stops, opacity);
1581
1582
  const data = { type, style };
1583
+ applyStops(data, style, paint.stops, opacity);
1582
1584
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1583
1585
  if (transform)
1584
1586
  data.transform = transform;
1585
- if (blendMode)
1586
- data.blendMode = blendMode;
1587
1587
  return data;
1588
1588
  }
1589
1589
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1609,17 +1609,15 @@ const { toPoint } = AroundHelper;
1609
1609
  const realFrom = {};
1610
1610
  const realTo = {};
1611
1611
  function conicGradient(paint, box) {
1612
- let { from, to, type, opacity, blendMode, stretch } = paint;
1612
+ let { from, to, type, opacity, stretch } = paint;
1613
1613
  toPoint(from || 'center', box, realFrom);
1614
1614
  toPoint(to || 'bottom', box, realTo);
1615
1615
  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));
1616
- applyStops(style, paint.stops, opacity);
1617
1616
  const data = { type, style };
1617
+ applyStops(data, style, paint.stops, opacity);
1618
1618
  const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
1619
1619
  if (transform)
1620
1620
  data.transform = transform;
1621
- if (blendMode)
1622
- data.blendMode = blendMode;
1623
1621
  return data;
1624
1622
  }
1625
1623
 
@@ -1952,6 +1950,8 @@ function createRows(drawData, content, style) {
1952
1950
  lastCharType = null;
1953
1951
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1954
1952
  word = { data: [] }, row = { words: [] };
1953
+ if (__letterSpacing)
1954
+ content = [...content];
1955
1955
  for (let i = 0, len = content.length; i < len; i++) {
1956
1956
  char = content[i];
1957
1957
  if (char === '\n') {
@@ -2358,7 +2358,7 @@ const ColorConvertModule = {
2358
2358
 
2359
2359
  Object.assign(TextConvert, TextConvertModule);
2360
2360
  Object.assign(ColorConvert, ColorConvertModule);
2361
- Object.assign(Paint, PaintModule);
2361
+ Object.assign(Paint$1, PaintModule);
2362
2362
  Object.assign(PaintImage, PaintImageModule);
2363
2363
  Object.assign(PaintGradient, PaintGradientModule);
2364
2364
  Object.assign(Effect, EffectModule);