@leafer-ui/worker 1.6.2 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.cjs CHANGED
@@ -161,17 +161,15 @@ class Watcher {
161
161
  this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
162
162
  this.__updatedList = new core.LeafList();
163
163
  this.totalTimes++;
164
- this.changed = false;
165
- this.hasVisible = false;
166
- this.hasRemove = false;
167
- this.hasAdd = false;
164
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
168
165
  }
169
166
  __listenEvents() {
170
- const { target } = this;
171
167
  this.__eventIds = [
172
- target.on_(core.PropertyEvent.CHANGE, this.__onAttrChange, this),
173
- target.on_([core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this),
174
- target.on_(core.WatchEvent.REQUEST, this.__onRquestData, this)
168
+ this.target.on_([
169
+ [core.PropertyEvent.CHANGE, this.__onAttrChange, this],
170
+ [[core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this],
171
+ [core.WatchEvent.REQUEST, this.__onRquestData, this]
172
+ ])
175
173
  ];
176
174
  }
177
175
  __removeListenEvents() {
@@ -181,8 +179,7 @@ class Watcher {
181
179
  if (this.target) {
182
180
  this.stop();
183
181
  this.__removeListenEvents();
184
- this.target = null;
185
- this.__updatedList = null;
182
+ this.target = this.__updatedList = null;
186
183
  }
187
184
  }
188
185
  }
@@ -287,7 +284,7 @@ class Layouter {
287
284
  this.disabled = true;
288
285
  }
289
286
  layout() {
290
- if (!this.running)
287
+ if (this.layouting || !this.running)
291
288
  return;
292
289
  const { target } = this;
293
290
  this.times = 0;
@@ -370,12 +367,10 @@ class Layouter {
370
367
  }
371
368
  static fullLayout(target) {
372
369
  updateAllMatrix(target, true);
373
- if (target.isBranch) {
370
+ if (target.isBranch)
374
371
  core.BranchHelper.updateBounds(target);
375
- }
376
- else {
372
+ else
377
373
  core.LeafHelper.updateBounds(target);
378
- }
379
374
  updateAllChange(target);
380
375
  }
381
376
  addExtra(leaf) {
@@ -398,11 +393,12 @@ class Layouter {
398
393
  this.__updatedList = event.data.updatedList;
399
394
  }
400
395
  __listenEvents() {
401
- const { target } = this;
402
396
  this.__eventIds = [
403
- target.on_(core.LayoutEvent.REQUEST, this.layout, this),
404
- target.on_(core.LayoutEvent.AGAIN, this.layoutAgain, this),
405
- target.on_(core.WatchEvent.DATA, this.__onReceiveWatchData, this)
397
+ this.target.on_([
398
+ [core.LayoutEvent.REQUEST, this.layout, this],
399
+ [core.LayoutEvent.AGAIN, this.layoutAgain, this],
400
+ [core.WatchEvent.DATA, this.__onReceiveWatchData, this]
401
+ ])
406
402
  ];
407
403
  }
408
404
  __removeListenEvents() {
@@ -633,12 +629,13 @@ class Renderer {
633
629
  this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
634
630
  }
635
631
  __listenEvents() {
636
- const { target } = this;
637
632
  this.__eventIds = [
638
- target.on_(core.RenderEvent.REQUEST, this.update, this),
639
- target.on_(core.LayoutEvent.END, this.__onLayoutEnd, this),
640
- target.on_(core.RenderEvent.AGAIN, this.renderAgain, this),
641
- target.on_(core.ResizeEvent.RESIZE, this.__onResize, this)
633
+ this.target.on_([
634
+ [core.RenderEvent.REQUEST, this.update, this],
635
+ [core.LayoutEvent.END, this.__onLayoutEnd, this],
636
+ [core.RenderEvent.AGAIN, this.renderAgain, this],
637
+ [core.ResizeEvent.RESIZE, this.__onResize, this]
638
+ ])
642
639
  ];
643
640
  }
644
641
  __removeListenEvents() {
@@ -882,35 +879,38 @@ function fillPathOrText(ui, canvas) {
882
879
  }
883
880
 
884
881
  function strokeText(stroke, ui, canvas) {
885
- const { strokeAlign } = ui.__;
886
- const isStrokes = typeof stroke !== 'string';
887
- switch (strokeAlign) {
882
+ switch (ui.__.strokeAlign) {
888
883
  case 'center':
889
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
890
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
884
+ drawCenter$1(stroke, 1, ui, canvas);
891
885
  break;
892
886
  case 'inside':
893
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
887
+ drawAlign(stroke, 'inside', ui, canvas);
894
888
  break;
895
889
  case 'outside':
896
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
890
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
897
891
  break;
898
892
  }
899
893
  }
900
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
901
- const { __strokeWidth, __font } = ui.__;
894
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
895
+ const data = ui.__;
896
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
897
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
898
+ }
899
+ function drawAlign(stroke, align, ui, canvas) {
902
900
  const out = canvas.getSameCanvas(true, true);
903
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
904
- out.font = __font;
905
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
901
+ out.font = ui.__.__font;
902
+ drawCenter$1(stroke, 2, ui, out);
906
903
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
907
904
  fillText(ui, out);
908
905
  out.blendMode = 'normal';
909
- if (ui.__worldFlipped)
906
+ copyWorld(canvas, out, ui);
907
+ out.recycle(ui.__nowWorld);
908
+ }
909
+ function copyWorld(canvas, out, ui) {
910
+ if (ui.__worldFlipped || core.Platform.fullImageShadow)
910
911
  canvas.copyWorldByReset(out, ui.__nowWorld);
911
912
  else
912
913
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
913
- out.recycle(ui.__nowWorld);
914
914
  }
915
915
  function drawTextStroke(ui, canvas) {
916
916
  let row, data = ui.__.__textDrawData;
@@ -948,90 +948,56 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
948
948
  }
949
949
 
950
950
  function stroke(stroke, ui, canvas) {
951
- const options = ui.__;
952
- const { __strokeWidth, strokeAlign, __font } = options;
953
- if (!__strokeWidth)
951
+ const data = ui.__;
952
+ if (!data.__strokeWidth)
954
953
  return;
955
- if (__font) {
954
+ if (data.__font) {
956
955
  strokeText(stroke, ui, canvas);
957
956
  }
958
957
  else {
959
- switch (strokeAlign) {
958
+ switch (data.strokeAlign) {
960
959
  case 'center':
961
- canvas.setStroke(stroke, __strokeWidth, options);
962
- canvas.stroke();
963
- if (options.__useArrow)
964
- strokeArrow(ui, canvas);
960
+ drawCenter(stroke, 1, ui, canvas);
965
961
  break;
966
962
  case 'inside':
967
- canvas.save();
968
- canvas.setStroke(stroke, __strokeWidth * 2, options);
969
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
970
- canvas.stroke();
971
- canvas.restore();
963
+ drawInside(stroke, ui, canvas);
972
964
  break;
973
965
  case 'outside':
974
- const out = canvas.getSameCanvas(true, true);
975
- out.setStroke(stroke, __strokeWidth * 2, options);
976
- ui.__drawRenderPath(out);
977
- out.stroke();
978
- options.windingRule ? out.clip(options.windingRule) : out.clip();
979
- out.clearWorld(ui.__layout.renderBounds);
980
- if (ui.__worldFlipped)
981
- canvas.copyWorldByReset(out, ui.__nowWorld);
982
- else
983
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
984
- out.recycle(ui.__nowWorld);
966
+ drawOutside(stroke, ui, canvas);
985
967
  break;
986
968
  }
987
969
  }
988
970
  }
989
971
  function strokes(strokes, ui, canvas) {
990
- const options = ui.__;
991
- const { __strokeWidth, strokeAlign, __font } = options;
992
- if (!__strokeWidth)
993
- return;
994
- if (__font) {
995
- strokeText(strokes, ui, canvas);
972
+ stroke(strokes, ui, canvas);
973
+ }
974
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
975
+ const data = ui.__;
976
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
977
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
978
+ if (data.__useArrow)
979
+ draw.Paint.strokeArrow(stroke, ui, canvas);
980
+ }
981
+ function drawInside(stroke, ui, canvas) {
982
+ canvas.save();
983
+ canvas.clipUI(ui);
984
+ drawCenter(stroke, 2, ui, canvas);
985
+ canvas.restore();
986
+ }
987
+ function drawOutside(stroke, ui, canvas) {
988
+ const data = ui.__;
989
+ if (data.__fillAfterStroke) {
990
+ drawCenter(stroke, 2, ui, canvas);
996
991
  }
997
992
  else {
998
- switch (strokeAlign) {
999
- case 'center':
1000
- canvas.setStroke(undefined, __strokeWidth, options);
1001
- drawStrokesStyle(strokes, false, ui, canvas);
1002
- if (options.__useArrow)
1003
- strokeArrow(ui, canvas);
1004
- break;
1005
- case 'inside':
1006
- canvas.save();
1007
- canvas.setStroke(undefined, __strokeWidth * 2, options);
1008
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1009
- drawStrokesStyle(strokes, false, ui, canvas);
1010
- canvas.restore();
1011
- break;
1012
- case 'outside':
1013
- const { renderBounds } = ui.__layout;
1014
- const out = canvas.getSameCanvas(true, true);
1015
- ui.__drawRenderPath(out);
1016
- out.setStroke(undefined, __strokeWidth * 2, options);
1017
- drawStrokesStyle(strokes, false, ui, out);
1018
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1019
- out.clearWorld(renderBounds);
1020
- if (ui.__worldFlipped)
1021
- canvas.copyWorldByReset(out, ui.__nowWorld);
1022
- else
1023
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1024
- out.recycle(ui.__nowWorld);
1025
- break;
1026
- }
1027
- }
1028
- }
1029
- function strokeArrow(ui, canvas) {
1030
- if (ui.__.dashPattern) {
1031
- canvas.beginPath();
1032
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
1033
- canvas.dashPattern = null;
1034
- canvas.stroke();
993
+ const { renderBounds } = ui.__layout;
994
+ const out = canvas.getSameCanvas(true, true);
995
+ ui.__drawRenderPath(out);
996
+ drawCenter(stroke, 2, ui, out);
997
+ out.clipUI(data);
998
+ out.clearWorld(renderBounds);
999
+ copyWorld(canvas, out, ui);
1000
+ out.recycle(ui.__nowWorld);
1035
1001
  }
1036
1002
  }
1037
1003
 
@@ -1078,41 +1044,66 @@ function shape(ui, current, options) {
1078
1044
  }
1079
1045
 
1080
1046
  let recycleMap;
1047
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
1081
1048
  function compute(attrName, ui) {
1082
1049
  const data = ui.__, leafPaints = [];
1083
- let paints = data.__input[attrName], hasOpacityPixel;
1050
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1084
1051
  if (!(paints instanceof Array))
1085
1052
  paints = [paints];
1086
1053
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
1087
1054
  for (let i = 0, len = paints.length, item; i < len; i++) {
1088
- item = getLeafPaint(attrName, paints[i], ui);
1089
- if (item)
1090
- leafPaints.push(item);
1055
+ (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
1091
1056
  }
1092
1057
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1093
- if (leafPaints.length && leafPaints[0].image)
1094
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1095
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
1058
+ if (leafPaints.length) {
1059
+ if (leafPaints.every(item => item.isTransparent)) {
1060
+ if (leafPaints.some(item => item.image))
1061
+ isAlphaPixel = true;
1062
+ isTransparent = true;
1063
+ }
1064
+ }
1065
+ if (attrName === 'fill') {
1066
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1067
+ stintSet(data, '__isTransparentFill', isTransparent);
1068
+ }
1069
+ else {
1070
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1071
+ stintSet(data, '__isTransparentStroke', isTransparent);
1072
+ }
1096
1073
  }
1097
1074
  function getLeafPaint(attrName, paint, ui) {
1098
1075
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1099
1076
  return undefined;
1077
+ let data;
1100
1078
  const { boxBounds } = ui.__layout;
1101
1079
  switch (paint.type) {
1102
- case 'solid':
1103
- let { type, blendMode, color, opacity } = paint;
1104
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
1105
1080
  case 'image':
1106
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1081
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1082
+ break;
1107
1083
  case 'linear':
1108
- return draw.PaintGradient.linearGradient(paint, boxBounds);
1084
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
1085
+ break;
1109
1086
  case 'radial':
1110
- return draw.PaintGradient.radialGradient(paint, boxBounds);
1087
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
1088
+ break;
1111
1089
  case 'angular':
1112
- return draw.PaintGradient.conicGradient(paint, boxBounds);
1090
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
1091
+ break;
1092
+ case 'solid':
1093
+ const { type, color, opacity } = paint;
1094
+ data = { type, style: draw.ColorConvert.string(color, opacity) };
1095
+ break;
1113
1096
  default:
1114
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
1097
+ if (paint.r !== undefined)
1098
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
1099
+ }
1100
+ if (data) {
1101
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1102
+ data.isTransparent = true;
1103
+ if (paint.blendMode)
1104
+ data.blendMode = paint.blendMode;
1115
1105
  }
1106
+ return data;
1116
1107
  }
1117
1108
 
1118
1109
  const PaintModule = {
@@ -1178,12 +1169,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1178
1169
 
1179
1170
  const { get: get$2, translate } = core.MatrixHelper;
1180
1171
  const tempBox = new core.Bounds();
1181
- const tempPoint = {};
1182
1172
  const tempScaleData = {};
1173
+ const tempImage = {};
1183
1174
  function createData(leafPaint, image, paint, box) {
1184
- const { blendMode, changeful, sync } = paint;
1185
- if (blendMode)
1186
- leafPaint.blendMode = blendMode;
1175
+ const { changeful, sync } = paint;
1187
1176
  if (changeful)
1188
1177
  leafPaint.changeful = changeful;
1189
1178
  if (sync)
@@ -1191,38 +1180,38 @@ function createData(leafPaint, image, paint, box) {
1191
1180
  leafPaint.data = getPatternData(paint, box, image);
1192
1181
  }
1193
1182
  function getPatternData(paint, box, image) {
1194
- let { width, height } = image;
1195
1183
  if (paint.padding)
1196
1184
  box = tempBox.set(box).shrink(paint.padding);
1197
1185
  if (paint.mode === 'strench')
1198
1186
  paint.mode = 'stretch';
1187
+ let { width, height } = image;
1199
1188
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1200
1189
  const sameBox = box.width === width && box.height === height;
1201
1190
  const data = { mode };
1202
1191
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1203
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1204
- let x = 0, y = 0, scaleX, scaleY;
1192
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1193
+ let scaleX, scaleY;
1205
1194
  if (!mode || mode === 'cover' || mode === 'fit') {
1206
1195
  if (!sameBox || rotation) {
1207
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1208
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1209
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1196
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1197
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1198
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1210
1199
  }
1211
1200
  }
1212
- else if (scale || size) {
1213
- core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1214
- scaleX = tempScaleData.scaleX;
1215
- scaleY = tempScaleData.scaleY;
1216
- }
1217
- if (align) {
1218
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1219
- if (scaleX)
1220
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1221
- core.AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1222
- x += tempPoint.x, y += tempPoint.y;
1201
+ else {
1202
+ if (scale || size) {
1203
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1204
+ scaleX = tempScaleData.scaleX;
1205
+ scaleY = tempScaleData.scaleY;
1206
+ }
1207
+ if (align) {
1208
+ if (scaleX)
1209
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1210
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1211
+ }
1223
1212
  }
1224
1213
  if (offset)
1225
- x += offset.x, y += offset.y;
1214
+ core.PointHelper.move(tempImage, offset);
1226
1215
  switch (mode) {
1227
1216
  case 'stretch':
1228
1217
  if (!sameBox)
@@ -1230,12 +1219,12 @@ function getPatternData(paint, box, image) {
1230
1219
  break;
1231
1220
  case 'normal':
1232
1221
  case 'clip':
1233
- if (x || y || scaleX || rotation)
1234
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1222
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1223
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1235
1224
  break;
1236
1225
  case 'repeat':
1237
1226
  if (!sameBox || scaleX || rotation)
1238
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1227
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1239
1228
  if (!repeat)
1240
1229
  data.repeat = 'repeat';
1241
1230
  break;
@@ -1243,7 +1232,7 @@ function getPatternData(paint, box, image) {
1243
1232
  case 'cover':
1244
1233
  default:
1245
1234
  if (scaleX)
1246
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1235
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1247
1236
  }
1248
1237
  if (!data.transform) {
1249
1238
  if (box.x || box.y) {
@@ -1276,6 +1265,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1276
1265
  }
1277
1266
  else {
1278
1267
  leafPaint = { type: paint.type, image };
1268
+ if (image.hasAlphaPixel)
1269
+ leafPaint.isTransparent = true;
1279
1270
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1280
1271
  }
1281
1272
  if (firstUse || image.loading)
@@ -1300,7 +1291,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1300
1291
  ignoreRender(ui, false);
1301
1292
  if (!ui.destroyed) {
1302
1293
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1303
- if (image.hasOpacityPixel)
1294
+ if (image.hasAlphaPixel)
1304
1295
  ui.__layout.hitCanvasChanged = true;
1305
1296
  ui.forceUpdate('surface');
1306
1297
  }
@@ -1312,13 +1303,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1312
1303
  onLoadError(ui, event, error);
1313
1304
  leafPaint.loadId = null;
1314
1305
  });
1315
- if (ui.placeholderColor)
1316
- setTimeout(() => {
1317
- if (!(image.ready || image.isPlacehold)) {
1318
- image.isPlacehold = true;
1319
- ui.forceUpdate('surface');
1320
- }
1321
- }, 100);
1306
+ if (ui.placeholderColor) {
1307
+ if (!ui.placeholderDelay)
1308
+ image.isPlacehold = true;
1309
+ else
1310
+ setTimeout(() => {
1311
+ if (!image.ready) {
1312
+ image.isPlacehold = true;
1313
+ ui.forceUpdate('surface');
1314
+ }
1315
+ }, ui.placeholderDelay);
1316
+ }
1322
1317
  }
1323
1318
  return leafPaint;
1324
1319
  }
@@ -1505,7 +1500,7 @@ function checkImage(ui, canvas, paint, allowDraw) {
1505
1500
  }
1506
1501
  function drawImage(ui, canvas, paint, data) {
1507
1502
  canvas.save();
1508
- ui.windingRule ? canvas.clip(ui.windingRule) : canvas.clip();
1503
+ canvas.clipUI(ui);
1509
1504
  if (paint.blendMode)
1510
1505
  canvas.blendMode = paint.blendMode;
1511
1506
  if (data.opacity)
@@ -1556,32 +1551,33 @@ const PaintImageModule = {
1556
1551
  repeatMode
1557
1552
  };
1558
1553
 
1559
- const { toPoint: toPoint$2 } = core.AroundHelper;
1554
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1560
1555
  const realFrom$2 = {};
1561
1556
  const realTo$2 = {};
1562
1557
  function linearGradient(paint, box) {
1563
- let { from, to, type, blendMode, opacity } = paint;
1558
+ let { from, to, type, opacity } = paint;
1564
1559
  toPoint$2(from || 'top', box, realFrom$2);
1565
1560
  toPoint$2(to || 'bottom', box, realTo$2);
1566
1561
  const style = core.Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1567
- applyStops(style, paint.stops, opacity);
1568
1562
  const data = { type, style };
1569
- if (blendMode)
1570
- data.blendMode = blendMode;
1563
+ applyStops(data, style, paint.stops, opacity);
1571
1564
  return data;
1572
1565
  }
1573
- function applyStops(gradient, stops, opacity) {
1566
+ function applyStops(data, gradient, stops, opacity) {
1574
1567
  if (stops) {
1575
- let stop;
1568
+ let stop, color, offset, isTransparent;
1576
1569
  for (let i = 0, len = stops.length; i < len; i++) {
1577
1570
  stop = stops[i];
1578
- if (typeof stop === 'string') {
1579
- gradient.addColorStop(i / (len - 1), draw.ColorConvert.string(stop, opacity));
1580
- }
1581
- else {
1582
- gradient.addColorStop(stop.offset, draw.ColorConvert.string(stop.color, opacity));
1583
- }
1571
+ if (typeof stop === 'string')
1572
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1573
+ else
1574
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1575
+ gradient.addColorStop(offset, color);
1576
+ if (!isTransparent && hasTransparent(color))
1577
+ isTransparent = true;
1584
1578
  }
1579
+ if (isTransparent)
1580
+ data.isTransparent = true;
1585
1581
  }
1586
1582
  }
1587
1583
 
@@ -1591,17 +1587,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1591
1587
  const realFrom$1 = {};
1592
1588
  const realTo$1 = {};
1593
1589
  function radialGradient(paint, box) {
1594
- let { from, to, type, opacity, blendMode, stretch } = paint;
1590
+ let { from, to, type, opacity, stretch } = paint;
1595
1591
  toPoint$1(from || 'center', box, realFrom$1);
1596
1592
  toPoint$1(to || 'bottom', box, realTo$1);
1597
1593
  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));
1598
- applyStops(style, paint.stops, opacity);
1599
1594
  const data = { type, style };
1595
+ applyStops(data, style, paint.stops, opacity);
1600
1596
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1601
1597
  if (transform)
1602
1598
  data.transform = transform;
1603
- if (blendMode)
1604
- data.blendMode = blendMode;
1605
1599
  return data;
1606
1600
  }
1607
1601
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1627,17 +1621,15 @@ const { toPoint } = core.AroundHelper;
1627
1621
  const realFrom = {};
1628
1622
  const realTo = {};
1629
1623
  function conicGradient(paint, box) {
1630
- let { from, to, type, opacity, blendMode, stretch } = paint;
1624
+ let { from, to, type, opacity, stretch } = paint;
1631
1625
  toPoint(from || 'center', box, realFrom);
1632
1626
  toPoint(to || 'bottom', box, realTo);
1633
1627
  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));
1634
- applyStops(style, paint.stops, opacity);
1635
1628
  const data = { type, style };
1629
+ applyStops(data, style, paint.stops, opacity);
1636
1630
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1637
1631
  if (transform)
1638
1632
  data.transform = transform;
1639
- if (blendMode)
1640
- data.blendMode = blendMode;
1641
1633
  return data;
1642
1634
  }
1643
1635
 
@@ -1673,12 +1665,10 @@ function shadow(ui, current, shape) {
1673
1665
  }
1674
1666
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1675
1667
  }
1676
- if (ui.__worldFlipped) {
1668
+ if (ui.__worldFlipped)
1677
1669
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1678
- }
1679
- else {
1670
+ else
1680
1671
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1681
- }
1682
1672
  if (end && index < end)
1683
1673
  other.clearWorld(copyBounds, true);
1684
1674
  });
@@ -1737,12 +1727,10 @@ function innerShadow(ui, current, shape) {
1737
1727
  copyBounds = bounds;
1738
1728
  }
1739
1729
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), 'source-in');
1740
- if (ui.__worldFlipped) {
1730
+ if (ui.__worldFlipped)
1741
1731
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1742
- }
1743
- else {
1732
+ else
1744
1733
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1745
- }
1746
1734
  if (end && index < end)
1747
1735
  other.clearWorld(copyBounds, true);
1748
1736
  });
@@ -1970,6 +1958,8 @@ function createRows(drawData, content, style) {
1970
1958
  lastCharType = null;
1971
1959
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1972
1960
  word = { data: [] }, row = { words: [] };
1961
+ if (__letterSpacing)
1962
+ content = [...content];
1973
1963
  for (let i = 0, len = content.length; i < len; i++) {
1974
1964
  char = content[i];
1975
1965
  if (char === '\n') {