leafer-draw 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/web.cjs CHANGED
@@ -341,17 +341,15 @@ class Watcher {
341
341
  this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
342
342
  this.__updatedList = new core.LeafList();
343
343
  this.totalTimes++;
344
- this.changed = false;
345
- this.hasVisible = false;
346
- this.hasRemove = false;
347
- this.hasAdd = false;
344
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
348
345
  }
349
346
  __listenEvents() {
350
- const { target } = this;
351
347
  this.__eventIds = [
352
- target.on_(core.PropertyEvent.CHANGE, this.__onAttrChange, this),
353
- target.on_([core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this),
354
- target.on_(core.WatchEvent.REQUEST, this.__onRquestData, this)
348
+ this.target.on_([
349
+ [core.PropertyEvent.CHANGE, this.__onAttrChange, this],
350
+ [[core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this],
351
+ [core.WatchEvent.REQUEST, this.__onRquestData, this]
352
+ ])
355
353
  ];
356
354
  }
357
355
  __removeListenEvents() {
@@ -361,8 +359,7 @@ class Watcher {
361
359
  if (this.target) {
362
360
  this.stop();
363
361
  this.__removeListenEvents();
364
- this.target = null;
365
- this.__updatedList = null;
362
+ this.target = this.__updatedList = null;
366
363
  }
367
364
  }
368
365
  }
@@ -467,7 +464,7 @@ class Layouter {
467
464
  this.disabled = true;
468
465
  }
469
466
  layout() {
470
- if (!this.running)
467
+ if (this.layouting || !this.running)
471
468
  return;
472
469
  const { target } = this;
473
470
  this.times = 0;
@@ -550,12 +547,10 @@ class Layouter {
550
547
  }
551
548
  static fullLayout(target) {
552
549
  updateAllMatrix(target, true);
553
- if (target.isBranch) {
550
+ if (target.isBranch)
554
551
  core.BranchHelper.updateBounds(target);
555
- }
556
- else {
552
+ else
557
553
  core.LeafHelper.updateBounds(target);
558
- }
559
554
  updateAllChange(target);
560
555
  }
561
556
  addExtra(leaf) {
@@ -578,11 +573,12 @@ class Layouter {
578
573
  this.__updatedList = event.data.updatedList;
579
574
  }
580
575
  __listenEvents() {
581
- const { target } = this;
582
576
  this.__eventIds = [
583
- target.on_(core.LayoutEvent.REQUEST, this.layout, this),
584
- target.on_(core.LayoutEvent.AGAIN, this.layoutAgain, this),
585
- target.on_(core.WatchEvent.DATA, this.__onReceiveWatchData, this)
577
+ this.target.on_([
578
+ [core.LayoutEvent.REQUEST, this.layout, this],
579
+ [core.LayoutEvent.AGAIN, this.layoutAgain, this],
580
+ [core.WatchEvent.DATA, this.__onReceiveWatchData, this]
581
+ ])
586
582
  ];
587
583
  }
588
584
  __removeListenEvents() {
@@ -813,12 +809,13 @@ class Renderer {
813
809
  this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
814
810
  }
815
811
  __listenEvents() {
816
- const { target } = this;
817
812
  this.__eventIds = [
818
- target.on_(core.RenderEvent.REQUEST, this.update, this),
819
- target.on_(core.LayoutEvent.END, this.__onLayoutEnd, this),
820
- target.on_(core.RenderEvent.AGAIN, this.renderAgain, this),
821
- target.on_(core.ResizeEvent.RESIZE, this.__onResize, this)
813
+ this.target.on_([
814
+ [core.RenderEvent.REQUEST, this.update, this],
815
+ [core.LayoutEvent.END, this.__onLayoutEnd, this],
816
+ [core.RenderEvent.AGAIN, this.renderAgain, this],
817
+ [core.ResizeEvent.RESIZE, this.__onResize, this]
818
+ ])
822
819
  ];
823
820
  }
824
821
  __removeListenEvents() {
@@ -905,35 +902,38 @@ function fillPathOrText(ui, canvas) {
905
902
  }
906
903
 
907
904
  function strokeText(stroke, ui, canvas) {
908
- const { strokeAlign } = ui.__;
909
- const isStrokes = typeof stroke !== 'string';
910
- switch (strokeAlign) {
905
+ switch (ui.__.strokeAlign) {
911
906
  case 'center':
912
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
913
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
907
+ drawCenter$1(stroke, 1, ui, canvas);
914
908
  break;
915
909
  case 'inside':
916
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
910
+ drawAlign(stroke, 'inside', ui, canvas);
917
911
  break;
918
912
  case 'outside':
919
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
913
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
920
914
  break;
921
915
  }
922
916
  }
923
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
924
- const { __strokeWidth, __font } = ui.__;
917
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
918
+ const data = ui.__;
919
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
920
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
921
+ }
922
+ function drawAlign(stroke, align, ui, canvas) {
925
923
  const out = canvas.getSameCanvas(true, true);
926
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
927
- out.font = __font;
928
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
924
+ out.font = ui.__.__font;
925
+ drawCenter$1(stroke, 2, ui, out);
929
926
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
930
927
  fillText(ui, out);
931
928
  out.blendMode = 'normal';
932
- if (ui.__worldFlipped)
929
+ copyWorld(canvas, out, ui);
930
+ out.recycle(ui.__nowWorld);
931
+ }
932
+ function copyWorld(canvas, out, ui) {
933
+ if (ui.__worldFlipped || core.Platform.fullImageShadow)
933
934
  canvas.copyWorldByReset(out, ui.__nowWorld);
934
935
  else
935
936
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
936
- out.recycle(ui.__nowWorld);
937
937
  }
938
938
  function drawTextStroke(ui, canvas) {
939
939
  let row, data = ui.__.__textDrawData;
@@ -971,90 +971,56 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
971
971
  }
972
972
 
973
973
  function stroke(stroke, ui, canvas) {
974
- const options = ui.__;
975
- const { __strokeWidth, strokeAlign, __font } = options;
976
- if (!__strokeWidth)
974
+ const data = ui.__;
975
+ if (!data.__strokeWidth)
977
976
  return;
978
- if (__font) {
977
+ if (data.__font) {
979
978
  strokeText(stroke, ui, canvas);
980
979
  }
981
980
  else {
982
- switch (strokeAlign) {
981
+ switch (data.strokeAlign) {
983
982
  case 'center':
984
- canvas.setStroke(stroke, __strokeWidth, options);
985
- canvas.stroke();
986
- if (options.__useArrow)
987
- strokeArrow(ui, canvas);
983
+ drawCenter(stroke, 1, ui, canvas);
988
984
  break;
989
985
  case 'inside':
990
- canvas.save();
991
- canvas.setStroke(stroke, __strokeWidth * 2, options);
992
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
993
- canvas.stroke();
994
- canvas.restore();
986
+ drawInside(stroke, ui, canvas);
995
987
  break;
996
988
  case 'outside':
997
- const out = canvas.getSameCanvas(true, true);
998
- out.setStroke(stroke, __strokeWidth * 2, options);
999
- ui.__drawRenderPath(out);
1000
- out.stroke();
1001
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1002
- out.clearWorld(ui.__layout.renderBounds);
1003
- if (ui.__worldFlipped)
1004
- canvas.copyWorldByReset(out, ui.__nowWorld);
1005
- else
1006
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1007
- out.recycle(ui.__nowWorld);
989
+ drawOutside(stroke, ui, canvas);
1008
990
  break;
1009
991
  }
1010
992
  }
1011
993
  }
1012
994
  function strokes(strokes, ui, canvas) {
1013
- const options = ui.__;
1014
- const { __strokeWidth, strokeAlign, __font } = options;
1015
- if (!__strokeWidth)
1016
- return;
1017
- if (__font) {
1018
- strokeText(strokes, ui, canvas);
995
+ stroke(strokes, ui, canvas);
996
+ }
997
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
998
+ const data = ui.__;
999
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
1000
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
1001
+ if (data.__useArrow)
1002
+ draw.Paint.strokeArrow(stroke, ui, canvas);
1003
+ }
1004
+ function drawInside(stroke, ui, canvas) {
1005
+ canvas.save();
1006
+ canvas.clipUI(ui);
1007
+ drawCenter(stroke, 2, ui, canvas);
1008
+ canvas.restore();
1009
+ }
1010
+ function drawOutside(stroke, ui, canvas) {
1011
+ const data = ui.__;
1012
+ if (data.__fillAfterStroke) {
1013
+ drawCenter(stroke, 2, ui, canvas);
1019
1014
  }
1020
1015
  else {
1021
- switch (strokeAlign) {
1022
- case 'center':
1023
- canvas.setStroke(undefined, __strokeWidth, options);
1024
- drawStrokesStyle(strokes, false, ui, canvas);
1025
- if (options.__useArrow)
1026
- strokeArrow(ui, canvas);
1027
- break;
1028
- case 'inside':
1029
- canvas.save();
1030
- canvas.setStroke(undefined, __strokeWidth * 2, options);
1031
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1032
- drawStrokesStyle(strokes, false, ui, canvas);
1033
- canvas.restore();
1034
- break;
1035
- case 'outside':
1036
- const { renderBounds } = ui.__layout;
1037
- const out = canvas.getSameCanvas(true, true);
1038
- ui.__drawRenderPath(out);
1039
- out.setStroke(undefined, __strokeWidth * 2, options);
1040
- drawStrokesStyle(strokes, false, ui, out);
1041
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1042
- out.clearWorld(renderBounds);
1043
- if (ui.__worldFlipped)
1044
- canvas.copyWorldByReset(out, ui.__nowWorld);
1045
- else
1046
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1047
- out.recycle(ui.__nowWorld);
1048
- break;
1049
- }
1050
- }
1051
- }
1052
- function strokeArrow(ui, canvas) {
1053
- if (ui.__.dashPattern) {
1054
- canvas.beginPath();
1055
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
1056
- canvas.dashPattern = null;
1057
- canvas.stroke();
1016
+ const { renderBounds } = ui.__layout;
1017
+ const out = canvas.getSameCanvas(true, true);
1018
+ ui.__drawRenderPath(out);
1019
+ drawCenter(stroke, 2, ui, out);
1020
+ out.clipUI(data);
1021
+ out.clearWorld(renderBounds);
1022
+ copyWorld(canvas, out, ui);
1023
+ out.recycle(ui.__nowWorld);
1058
1024
  }
1059
1025
  }
1060
1026
 
@@ -1101,41 +1067,66 @@ function shape(ui, current, options) {
1101
1067
  }
1102
1068
 
1103
1069
  let recycleMap;
1070
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
1104
1071
  function compute(attrName, ui) {
1105
1072
  const data = ui.__, leafPaints = [];
1106
- let paints = data.__input[attrName], hasOpacityPixel;
1073
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1107
1074
  if (!(paints instanceof Array))
1108
1075
  paints = [paints];
1109
1076
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
1110
1077
  for (let i = 0, len = paints.length, item; i < len; i++) {
1111
- item = getLeafPaint(attrName, paints[i], ui);
1112
- if (item)
1113
- leafPaints.push(item);
1078
+ (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
1114
1079
  }
1115
1080
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1116
- if (leafPaints.length && leafPaints[0].image)
1117
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1118
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
1081
+ if (leafPaints.length) {
1082
+ if (leafPaints.every(item => item.isTransparent)) {
1083
+ if (leafPaints.some(item => item.image))
1084
+ isAlphaPixel = true;
1085
+ isTransparent = true;
1086
+ }
1087
+ }
1088
+ if (attrName === 'fill') {
1089
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1090
+ stintSet(data, '__isTransparentFill', isTransparent);
1091
+ }
1092
+ else {
1093
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1094
+ stintSet(data, '__isTransparentStroke', isTransparent);
1095
+ }
1119
1096
  }
1120
1097
  function getLeafPaint(attrName, paint, ui) {
1121
1098
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1122
1099
  return undefined;
1100
+ let data;
1123
1101
  const { boxBounds } = ui.__layout;
1124
1102
  switch (paint.type) {
1125
- case 'solid':
1126
- let { type, blendMode, color, opacity } = paint;
1127
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
1128
1103
  case 'image':
1129
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1104
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1105
+ break;
1130
1106
  case 'linear':
1131
- return draw.PaintGradient.linearGradient(paint, boxBounds);
1107
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
1108
+ break;
1132
1109
  case 'radial':
1133
- return draw.PaintGradient.radialGradient(paint, boxBounds);
1110
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
1111
+ break;
1134
1112
  case 'angular':
1135
- return draw.PaintGradient.conicGradient(paint, boxBounds);
1113
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
1114
+ break;
1115
+ case 'solid':
1116
+ const { type, color, opacity } = paint;
1117
+ data = { type, style: draw.ColorConvert.string(color, opacity) };
1118
+ break;
1136
1119
  default:
1137
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
1120
+ if (paint.r !== undefined)
1121
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
1122
+ }
1123
+ if (data) {
1124
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1125
+ data.isTransparent = true;
1126
+ if (paint.blendMode)
1127
+ data.blendMode = paint.blendMode;
1138
1128
  }
1129
+ return data;
1139
1130
  }
1140
1131
 
1141
1132
  const PaintModule = {
@@ -1201,12 +1192,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1201
1192
 
1202
1193
  const { get: get$2, translate } = core.MatrixHelper;
1203
1194
  const tempBox = new core.Bounds();
1204
- const tempPoint = {};
1205
1195
  const tempScaleData = {};
1196
+ const tempImage = {};
1206
1197
  function createData(leafPaint, image, paint, box) {
1207
- const { blendMode, changeful, sync } = paint;
1208
- if (blendMode)
1209
- leafPaint.blendMode = blendMode;
1198
+ const { changeful, sync } = paint;
1210
1199
  if (changeful)
1211
1200
  leafPaint.changeful = changeful;
1212
1201
  if (sync)
@@ -1214,38 +1203,38 @@ function createData(leafPaint, image, paint, box) {
1214
1203
  leafPaint.data = getPatternData(paint, box, image);
1215
1204
  }
1216
1205
  function getPatternData(paint, box, image) {
1217
- let { width, height } = image;
1218
1206
  if (paint.padding)
1219
1207
  box = tempBox.set(box).shrink(paint.padding);
1220
1208
  if (paint.mode === 'strench')
1221
1209
  paint.mode = 'stretch';
1210
+ let { width, height } = image;
1222
1211
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1223
1212
  const sameBox = box.width === width && box.height === height;
1224
1213
  const data = { mode };
1225
1214
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1226
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1227
- let x = 0, y = 0, scaleX, scaleY;
1215
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1216
+ let scaleX, scaleY;
1228
1217
  if (!mode || mode === 'cover' || mode === 'fit') {
1229
1218
  if (!sameBox || rotation) {
1230
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1231
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1232
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1219
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1220
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1221
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1233
1222
  }
1234
1223
  }
1235
- else if (scale || size) {
1236
- core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1237
- scaleX = tempScaleData.scaleX;
1238
- scaleY = tempScaleData.scaleY;
1239
- }
1240
- if (align) {
1241
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1242
- if (scaleX)
1243
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1244
- core.AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1245
- x += tempPoint.x, y += tempPoint.y;
1224
+ else {
1225
+ if (scale || size) {
1226
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1227
+ scaleX = tempScaleData.scaleX;
1228
+ scaleY = tempScaleData.scaleY;
1229
+ }
1230
+ if (align) {
1231
+ if (scaleX)
1232
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1233
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1234
+ }
1246
1235
  }
1247
1236
  if (offset)
1248
- x += offset.x, y += offset.y;
1237
+ core.PointHelper.move(tempImage, offset);
1249
1238
  switch (mode) {
1250
1239
  case 'stretch':
1251
1240
  if (!sameBox)
@@ -1253,12 +1242,12 @@ function getPatternData(paint, box, image) {
1253
1242
  break;
1254
1243
  case 'normal':
1255
1244
  case 'clip':
1256
- if (x || y || scaleX || rotation)
1257
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1245
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1246
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1258
1247
  break;
1259
1248
  case 'repeat':
1260
1249
  if (!sameBox || scaleX || rotation)
1261
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1250
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1262
1251
  if (!repeat)
1263
1252
  data.repeat = 'repeat';
1264
1253
  break;
@@ -1266,7 +1255,7 @@ function getPatternData(paint, box, image) {
1266
1255
  case 'cover':
1267
1256
  default:
1268
1257
  if (scaleX)
1269
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1258
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1270
1259
  }
1271
1260
  if (!data.transform) {
1272
1261
  if (box.x || box.y) {
@@ -1299,6 +1288,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1299
1288
  }
1300
1289
  else {
1301
1290
  leafPaint = { type: paint.type, image };
1291
+ if (image.hasAlphaPixel)
1292
+ leafPaint.isTransparent = true;
1302
1293
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1303
1294
  }
1304
1295
  if (firstUse || image.loading)
@@ -1323,7 +1314,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1323
1314
  ignoreRender(ui, false);
1324
1315
  if (!ui.destroyed) {
1325
1316
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1326
- if (image.hasOpacityPixel)
1317
+ if (image.hasAlphaPixel)
1327
1318
  ui.__layout.hitCanvasChanged = true;
1328
1319
  ui.forceUpdate('surface');
1329
1320
  }
@@ -1335,13 +1326,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1335
1326
  onLoadError(ui, event, error);
1336
1327
  leafPaint.loadId = null;
1337
1328
  });
1338
- if (ui.placeholderColor)
1339
- setTimeout(() => {
1340
- if (!(image.ready || image.isPlacehold)) {
1341
- image.isPlacehold = true;
1342
- ui.forceUpdate('surface');
1343
- }
1344
- }, 100);
1329
+ if (ui.placeholderColor) {
1330
+ if (!ui.placeholderDelay)
1331
+ image.isPlacehold = true;
1332
+ else
1333
+ setTimeout(() => {
1334
+ if (!image.ready) {
1335
+ image.isPlacehold = true;
1336
+ ui.forceUpdate('surface');
1337
+ }
1338
+ }, ui.placeholderDelay);
1339
+ }
1345
1340
  }
1346
1341
  return leafPaint;
1347
1342
  }
@@ -1528,7 +1523,7 @@ function checkImage(ui, canvas, paint, allowDraw) {
1528
1523
  }
1529
1524
  function drawImage(ui, canvas, paint, data) {
1530
1525
  canvas.save();
1531
- ui.windingRule ? canvas.clip(ui.windingRule) : canvas.clip();
1526
+ canvas.clipUI(ui);
1532
1527
  if (paint.blendMode)
1533
1528
  canvas.blendMode = paint.blendMode;
1534
1529
  if (data.opacity)
@@ -1579,32 +1574,33 @@ const PaintImageModule = {
1579
1574
  repeatMode
1580
1575
  };
1581
1576
 
1582
- const { toPoint: toPoint$2 } = core.AroundHelper;
1577
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1583
1578
  const realFrom$2 = {};
1584
1579
  const realTo$2 = {};
1585
1580
  function linearGradient(paint, box) {
1586
- let { from, to, type, blendMode, opacity } = paint;
1581
+ let { from, to, type, opacity } = paint;
1587
1582
  toPoint$2(from || 'top', box, realFrom$2);
1588
1583
  toPoint$2(to || 'bottom', box, realTo$2);
1589
1584
  const style = core.Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1590
- applyStops(style, paint.stops, opacity);
1591
1585
  const data = { type, style };
1592
- if (blendMode)
1593
- data.blendMode = blendMode;
1586
+ applyStops(data, style, paint.stops, opacity);
1594
1587
  return data;
1595
1588
  }
1596
- function applyStops(gradient, stops, opacity) {
1589
+ function applyStops(data, gradient, stops, opacity) {
1597
1590
  if (stops) {
1598
- let stop;
1591
+ let stop, color, offset, isTransparent;
1599
1592
  for (let i = 0, len = stops.length; i < len; i++) {
1600
1593
  stop = stops[i];
1601
- if (typeof stop === 'string') {
1602
- gradient.addColorStop(i / (len - 1), draw.ColorConvert.string(stop, opacity));
1603
- }
1604
- else {
1605
- gradient.addColorStop(stop.offset, draw.ColorConvert.string(stop.color, opacity));
1606
- }
1594
+ if (typeof stop === 'string')
1595
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1596
+ else
1597
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1598
+ gradient.addColorStop(offset, color);
1599
+ if (!isTransparent && hasTransparent(color))
1600
+ isTransparent = true;
1607
1601
  }
1602
+ if (isTransparent)
1603
+ data.isTransparent = true;
1608
1604
  }
1609
1605
  }
1610
1606
 
@@ -1614,17 +1610,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1614
1610
  const realFrom$1 = {};
1615
1611
  const realTo$1 = {};
1616
1612
  function radialGradient(paint, box) {
1617
- let { from, to, type, opacity, blendMode, stretch } = paint;
1613
+ let { from, to, type, opacity, stretch } = paint;
1618
1614
  toPoint$1(from || 'center', box, realFrom$1);
1619
1615
  toPoint$1(to || 'bottom', box, realTo$1);
1620
1616
  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));
1621
- applyStops(style, paint.stops, opacity);
1622
1617
  const data = { type, style };
1618
+ applyStops(data, style, paint.stops, opacity);
1623
1619
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1624
1620
  if (transform)
1625
1621
  data.transform = transform;
1626
- if (blendMode)
1627
- data.blendMode = blendMode;
1628
1622
  return data;
1629
1623
  }
1630
1624
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1650,17 +1644,15 @@ const { toPoint } = core.AroundHelper;
1650
1644
  const realFrom = {};
1651
1645
  const realTo = {};
1652
1646
  function conicGradient(paint, box) {
1653
- let { from, to, type, opacity, blendMode, stretch } = paint;
1647
+ let { from, to, type, opacity, stretch } = paint;
1654
1648
  toPoint(from || 'center', box, realFrom);
1655
1649
  toPoint(to || 'bottom', box, realTo);
1656
1650
  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));
1657
- applyStops(style, paint.stops, opacity);
1658
1651
  const data = { type, style };
1652
+ applyStops(data, style, paint.stops, opacity);
1659
1653
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1660
1654
  if (transform)
1661
1655
  data.transform = transform;
1662
- if (blendMode)
1663
- data.blendMode = blendMode;
1664
1656
  return data;
1665
1657
  }
1666
1658
 
@@ -1696,12 +1688,10 @@ function shadow(ui, current, shape) {
1696
1688
  }
1697
1689
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1698
1690
  }
1699
- if (ui.__worldFlipped) {
1691
+ if (ui.__worldFlipped)
1700
1692
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1701
- }
1702
- else {
1693
+ else
1703
1694
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1704
- }
1705
1695
  if (end && index < end)
1706
1696
  other.clearWorld(copyBounds, true);
1707
1697
  });
@@ -1760,12 +1750,10 @@ function innerShadow(ui, current, shape) {
1760
1750
  copyBounds = bounds;
1761
1751
  }
1762
1752
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), 'source-in');
1763
- if (ui.__worldFlipped) {
1753
+ if (ui.__worldFlipped)
1764
1754
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1765
- }
1766
- else {
1755
+ else
1767
1756
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1768
- }
1769
1757
  if (end && index < end)
1770
1758
  other.clearWorld(copyBounds, true);
1771
1759
  });
@@ -1993,6 +1981,8 @@ function createRows(drawData, content, style) {
1993
1981
  lastCharType = null;
1994
1982
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1995
1983
  word = { data: [] }, row = { words: [] };
1984
+ if (__letterSpacing)
1985
+ content = [...content];
1996
1986
  for (let i = 0, len = content.length; i < len; i++) {
1997
1987
  char = content[i];
1998
1988
  if (char === '\n') {