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