@leafer-ui/node 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/node.cjs CHANGED
@@ -174,17 +174,15 @@ class Watcher {
174
174
  this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
175
175
  this.__updatedList = new core.LeafList();
176
176
  this.totalTimes++;
177
- this.changed = false;
178
- this.hasVisible = false;
179
- this.hasRemove = false;
180
- this.hasAdd = false;
177
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
181
178
  }
182
179
  __listenEvents() {
183
- const { target } = this;
184
180
  this.__eventIds = [
185
- target.on_(core.PropertyEvent.CHANGE, this.__onAttrChange, this),
186
- target.on_([core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this),
187
- target.on_(core.WatchEvent.REQUEST, this.__onRquestData, this)
181
+ this.target.on_([
182
+ [core.PropertyEvent.CHANGE, this.__onAttrChange, this],
183
+ [[core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this],
184
+ [core.WatchEvent.REQUEST, this.__onRquestData, this]
185
+ ])
188
186
  ];
189
187
  }
190
188
  __removeListenEvents() {
@@ -194,8 +192,7 @@ class Watcher {
194
192
  if (this.target) {
195
193
  this.stop();
196
194
  this.__removeListenEvents();
197
- this.target = null;
198
- this.__updatedList = null;
195
+ this.target = this.__updatedList = null;
199
196
  }
200
197
  }
201
198
  }
@@ -300,7 +297,7 @@ class Layouter {
300
297
  this.disabled = true;
301
298
  }
302
299
  layout() {
303
- if (!this.running)
300
+ if (this.layouting || !this.running)
304
301
  return;
305
302
  const { target } = this;
306
303
  this.times = 0;
@@ -383,12 +380,10 @@ class Layouter {
383
380
  }
384
381
  static fullLayout(target) {
385
382
  updateAllMatrix(target, true);
386
- if (target.isBranch) {
383
+ if (target.isBranch)
387
384
  core.BranchHelper.updateBounds(target);
388
- }
389
- else {
385
+ else
390
386
  core.LeafHelper.updateBounds(target);
391
- }
392
387
  updateAllChange(target);
393
388
  }
394
389
  addExtra(leaf) {
@@ -411,11 +406,12 @@ class Layouter {
411
406
  this.__updatedList = event.data.updatedList;
412
407
  }
413
408
  __listenEvents() {
414
- const { target } = this;
415
409
  this.__eventIds = [
416
- target.on_(core.LayoutEvent.REQUEST, this.layout, this),
417
- target.on_(core.LayoutEvent.AGAIN, this.layoutAgain, this),
418
- target.on_(core.WatchEvent.DATA, this.__onReceiveWatchData, this)
410
+ this.target.on_([
411
+ [core.LayoutEvent.REQUEST, this.layout, this],
412
+ [core.LayoutEvent.AGAIN, this.layoutAgain, this],
413
+ [core.WatchEvent.DATA, this.__onReceiveWatchData, this]
414
+ ])
419
415
  ];
420
416
  }
421
417
  __removeListenEvents() {
@@ -646,12 +642,13 @@ class Renderer {
646
642
  this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
647
643
  }
648
644
  __listenEvents() {
649
- const { target } = this;
650
645
  this.__eventIds = [
651
- target.on_(core.RenderEvent.REQUEST, this.update, this),
652
- target.on_(core.LayoutEvent.END, this.__onLayoutEnd, this),
653
- target.on_(core.RenderEvent.AGAIN, this.renderAgain, this),
654
- target.on_(core.ResizeEvent.RESIZE, this.__onResize, this)
646
+ this.target.on_([
647
+ [core.RenderEvent.REQUEST, this.update, this],
648
+ [core.LayoutEvent.END, this.__onLayoutEnd, this],
649
+ [core.RenderEvent.AGAIN, this.renderAgain, this],
650
+ [core.ResizeEvent.RESIZE, this.__onResize, this]
651
+ ])
655
652
  ];
656
653
  }
657
654
  __removeListenEvents() {
@@ -895,35 +892,38 @@ function fillPathOrText(ui, canvas) {
895
892
  }
896
893
 
897
894
  function strokeText(stroke, ui, canvas) {
898
- const { strokeAlign } = ui.__;
899
- const isStrokes = typeof stroke !== 'string';
900
- switch (strokeAlign) {
895
+ switch (ui.__.strokeAlign) {
901
896
  case 'center':
902
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
903
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
897
+ drawCenter$1(stroke, 1, ui, canvas);
904
898
  break;
905
899
  case 'inside':
906
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
900
+ drawAlign(stroke, 'inside', ui, canvas);
907
901
  break;
908
902
  case 'outside':
909
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
903
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
910
904
  break;
911
905
  }
912
906
  }
913
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
914
- const { __strokeWidth, __font } = ui.__;
907
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
908
+ const data = ui.__;
909
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
910
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
911
+ }
912
+ function drawAlign(stroke, align, ui, canvas) {
915
913
  const out = canvas.getSameCanvas(true, true);
916
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
917
- out.font = __font;
918
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
914
+ out.font = ui.__.__font;
915
+ drawCenter$1(stroke, 2, ui, out);
919
916
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
920
917
  fillText(ui, out);
921
918
  out.blendMode = 'normal';
922
- if (ui.__worldFlipped)
919
+ copyWorld(canvas, out, ui);
920
+ out.recycle(ui.__nowWorld);
921
+ }
922
+ function copyWorld(canvas, out, ui) {
923
+ if (ui.__worldFlipped || core.Platform.fullImageShadow)
923
924
  canvas.copyWorldByReset(out, ui.__nowWorld);
924
925
  else
925
926
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
926
- out.recycle(ui.__nowWorld);
927
927
  }
928
928
  function drawTextStroke(ui, canvas) {
929
929
  let row, data = ui.__.__textDrawData;
@@ -961,90 +961,56 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
961
961
  }
962
962
 
963
963
  function stroke(stroke, ui, canvas) {
964
- const options = ui.__;
965
- const { __strokeWidth, strokeAlign, __font } = options;
966
- if (!__strokeWidth)
964
+ const data = ui.__;
965
+ if (!data.__strokeWidth)
967
966
  return;
968
- if (__font) {
967
+ if (data.__font) {
969
968
  strokeText(stroke, ui, canvas);
970
969
  }
971
970
  else {
972
- switch (strokeAlign) {
971
+ switch (data.strokeAlign) {
973
972
  case 'center':
974
- canvas.setStroke(stroke, __strokeWidth, options);
975
- canvas.stroke();
976
- if (options.__useArrow)
977
- strokeArrow(ui, canvas);
973
+ drawCenter(stroke, 1, ui, canvas);
978
974
  break;
979
975
  case 'inside':
980
- canvas.save();
981
- canvas.setStroke(stroke, __strokeWidth * 2, options);
982
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
983
- canvas.stroke();
984
- canvas.restore();
976
+ drawInside(stroke, ui, canvas);
985
977
  break;
986
978
  case 'outside':
987
- const out = canvas.getSameCanvas(true, true);
988
- out.setStroke(stroke, __strokeWidth * 2, options);
989
- ui.__drawRenderPath(out);
990
- out.stroke();
991
- options.windingRule ? out.clip(options.windingRule) : out.clip();
992
- out.clearWorld(ui.__layout.renderBounds);
993
- if (ui.__worldFlipped)
994
- canvas.copyWorldByReset(out, ui.__nowWorld);
995
- else
996
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
997
- out.recycle(ui.__nowWorld);
979
+ drawOutside(stroke, ui, canvas);
998
980
  break;
999
981
  }
1000
982
  }
1001
983
  }
1002
984
  function strokes(strokes, ui, canvas) {
1003
- const options = ui.__;
1004
- const { __strokeWidth, strokeAlign, __font } = options;
1005
- if (!__strokeWidth)
1006
- return;
1007
- if (__font) {
1008
- strokeText(strokes, ui, canvas);
985
+ stroke(strokes, ui, canvas);
986
+ }
987
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
988
+ const data = ui.__;
989
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
990
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
991
+ if (data.__useArrow)
992
+ draw.Paint.strokeArrow(stroke, ui, canvas);
993
+ }
994
+ function drawInside(stroke, ui, canvas) {
995
+ canvas.save();
996
+ canvas.clipUI(ui);
997
+ drawCenter(stroke, 2, ui, canvas);
998
+ canvas.restore();
999
+ }
1000
+ function drawOutside(stroke, ui, canvas) {
1001
+ const data = ui.__;
1002
+ if (data.__fillAfterStroke) {
1003
+ drawCenter(stroke, 2, ui, canvas);
1009
1004
  }
1010
1005
  else {
1011
- switch (strokeAlign) {
1012
- case 'center':
1013
- canvas.setStroke(undefined, __strokeWidth, options);
1014
- drawStrokesStyle(strokes, false, ui, canvas);
1015
- if (options.__useArrow)
1016
- strokeArrow(ui, canvas);
1017
- break;
1018
- case 'inside':
1019
- canvas.save();
1020
- canvas.setStroke(undefined, __strokeWidth * 2, options);
1021
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1022
- drawStrokesStyle(strokes, false, ui, canvas);
1023
- canvas.restore();
1024
- break;
1025
- case 'outside':
1026
- const { renderBounds } = ui.__layout;
1027
- const out = canvas.getSameCanvas(true, true);
1028
- ui.__drawRenderPath(out);
1029
- out.setStroke(undefined, __strokeWidth * 2, options);
1030
- drawStrokesStyle(strokes, false, ui, out);
1031
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1032
- out.clearWorld(renderBounds);
1033
- if (ui.__worldFlipped)
1034
- canvas.copyWorldByReset(out, ui.__nowWorld);
1035
- else
1036
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1037
- out.recycle(ui.__nowWorld);
1038
- break;
1039
- }
1040
- }
1041
- }
1042
- function strokeArrow(ui, canvas) {
1043
- if (ui.__.dashPattern) {
1044
- canvas.beginPath();
1045
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
1046
- canvas.dashPattern = null;
1047
- canvas.stroke();
1006
+ const { renderBounds } = ui.__layout;
1007
+ const out = canvas.getSameCanvas(true, true);
1008
+ ui.__drawRenderPath(out);
1009
+ drawCenter(stroke, 2, ui, out);
1010
+ out.clipUI(data);
1011
+ out.clearWorld(renderBounds);
1012
+ copyWorld(canvas, out, ui);
1013
+ out.recycle(ui.__nowWorld);
1048
1014
  }
1049
1015
  }
1050
1016
 
@@ -1091,41 +1057,66 @@ function shape(ui, current, options) {
1091
1057
  }
1092
1058
 
1093
1059
  let recycleMap;
1060
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
1094
1061
  function compute(attrName, ui) {
1095
1062
  const data = ui.__, leafPaints = [];
1096
- let paints = data.__input[attrName], hasOpacityPixel;
1063
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1097
1064
  if (!(paints instanceof Array))
1098
1065
  paints = [paints];
1099
1066
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
1100
1067
  for (let i = 0, len = paints.length, item; i < len; i++) {
1101
- item = getLeafPaint(attrName, paints[i], ui);
1102
- if (item)
1103
- leafPaints.push(item);
1068
+ (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
1104
1069
  }
1105
1070
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1106
- if (leafPaints.length && leafPaints[0].image)
1107
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1108
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
1071
+ if (leafPaints.length) {
1072
+ if (leafPaints.every(item => item.isTransparent)) {
1073
+ if (leafPaints.some(item => item.image))
1074
+ isAlphaPixel = true;
1075
+ isTransparent = true;
1076
+ }
1077
+ }
1078
+ if (attrName === 'fill') {
1079
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1080
+ stintSet(data, '__isTransparentFill', isTransparent);
1081
+ }
1082
+ else {
1083
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1084
+ stintSet(data, '__isTransparentStroke', isTransparent);
1085
+ }
1109
1086
  }
1110
1087
  function getLeafPaint(attrName, paint, ui) {
1111
1088
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1112
1089
  return undefined;
1090
+ let data;
1113
1091
  const { boxBounds } = ui.__layout;
1114
1092
  switch (paint.type) {
1115
- case 'solid':
1116
- let { type, blendMode, color, opacity } = paint;
1117
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
1118
1093
  case 'image':
1119
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1094
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1095
+ break;
1120
1096
  case 'linear':
1121
- return draw.PaintGradient.linearGradient(paint, boxBounds);
1097
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
1098
+ break;
1122
1099
  case 'radial':
1123
- return draw.PaintGradient.radialGradient(paint, boxBounds);
1100
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
1101
+ break;
1124
1102
  case 'angular':
1125
- return draw.PaintGradient.conicGradient(paint, boxBounds);
1103
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
1104
+ break;
1105
+ case 'solid':
1106
+ const { type, color, opacity } = paint;
1107
+ data = { type, style: draw.ColorConvert.string(color, opacity) };
1108
+ break;
1126
1109
  default:
1127
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
1110
+ if (paint.r !== undefined)
1111
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
1128
1112
  }
1113
+ if (data) {
1114
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1115
+ data.isTransparent = true;
1116
+ if (paint.blendMode)
1117
+ data.blendMode = paint.blendMode;
1118
+ }
1119
+ return data;
1129
1120
  }
1130
1121
 
1131
1122
  const PaintModule = {
@@ -1191,12 +1182,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1191
1182
 
1192
1183
  const { get: get$2, translate } = core.MatrixHelper;
1193
1184
  const tempBox = new core.Bounds();
1194
- const tempPoint = {};
1195
1185
  const tempScaleData = {};
1186
+ const tempImage = {};
1196
1187
  function createData(leafPaint, image, paint, box) {
1197
- const { blendMode, changeful, sync } = paint;
1198
- if (blendMode)
1199
- leafPaint.blendMode = blendMode;
1188
+ const { changeful, sync } = paint;
1200
1189
  if (changeful)
1201
1190
  leafPaint.changeful = changeful;
1202
1191
  if (sync)
@@ -1204,38 +1193,38 @@ function createData(leafPaint, image, paint, box) {
1204
1193
  leafPaint.data = getPatternData(paint, box, image);
1205
1194
  }
1206
1195
  function getPatternData(paint, box, image) {
1207
- let { width, height } = image;
1208
1196
  if (paint.padding)
1209
1197
  box = tempBox.set(box).shrink(paint.padding);
1210
1198
  if (paint.mode === 'strench')
1211
1199
  paint.mode = 'stretch';
1200
+ let { width, height } = image;
1212
1201
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1213
1202
  const sameBox = box.width === width && box.height === height;
1214
1203
  const data = { mode };
1215
1204
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1216
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1217
- let x = 0, y = 0, scaleX, scaleY;
1205
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1206
+ let scaleX, scaleY;
1218
1207
  if (!mode || mode === 'cover' || mode === 'fit') {
1219
1208
  if (!sameBox || rotation) {
1220
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1221
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1222
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1209
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1210
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1211
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1223
1212
  }
1224
1213
  }
1225
- else if (scale || size) {
1226
- core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1227
- scaleX = tempScaleData.scaleX;
1228
- scaleY = tempScaleData.scaleY;
1229
- }
1230
- if (align) {
1231
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1232
- if (scaleX)
1233
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1234
- core.AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1235
- x += tempPoint.x, y += tempPoint.y;
1214
+ else {
1215
+ if (scale || size) {
1216
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1217
+ scaleX = tempScaleData.scaleX;
1218
+ scaleY = tempScaleData.scaleY;
1219
+ }
1220
+ if (align) {
1221
+ if (scaleX)
1222
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1223
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1224
+ }
1236
1225
  }
1237
1226
  if (offset)
1238
- x += offset.x, y += offset.y;
1227
+ core.PointHelper.move(tempImage, offset);
1239
1228
  switch (mode) {
1240
1229
  case 'stretch':
1241
1230
  if (!sameBox)
@@ -1243,12 +1232,12 @@ function getPatternData(paint, box, image) {
1243
1232
  break;
1244
1233
  case 'normal':
1245
1234
  case 'clip':
1246
- if (x || y || scaleX || rotation)
1247
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1235
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1236
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1248
1237
  break;
1249
1238
  case 'repeat':
1250
1239
  if (!sameBox || scaleX || rotation)
1251
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1240
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1252
1241
  if (!repeat)
1253
1242
  data.repeat = 'repeat';
1254
1243
  break;
@@ -1256,7 +1245,7 @@ function getPatternData(paint, box, image) {
1256
1245
  case 'cover':
1257
1246
  default:
1258
1247
  if (scaleX)
1259
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1248
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1260
1249
  }
1261
1250
  if (!data.transform) {
1262
1251
  if (box.x || box.y) {
@@ -1289,6 +1278,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1289
1278
  }
1290
1279
  else {
1291
1280
  leafPaint = { type: paint.type, image };
1281
+ if (image.hasAlphaPixel)
1282
+ leafPaint.isTransparent = true;
1292
1283
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1293
1284
  }
1294
1285
  if (firstUse || image.loading)
@@ -1313,7 +1304,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1313
1304
  ignoreRender(ui, false);
1314
1305
  if (!ui.destroyed) {
1315
1306
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1316
- if (image.hasOpacityPixel)
1307
+ if (image.hasAlphaPixel)
1317
1308
  ui.__layout.hitCanvasChanged = true;
1318
1309
  ui.forceUpdate('surface');
1319
1310
  }
@@ -1325,13 +1316,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1325
1316
  onLoadError(ui, event, error);
1326
1317
  leafPaint.loadId = null;
1327
1318
  });
1328
- if (ui.placeholderColor)
1329
- setTimeout(() => {
1330
- if (!(image.ready || image.isPlacehold)) {
1331
- image.isPlacehold = true;
1332
- ui.forceUpdate('surface');
1333
- }
1334
- }, 100);
1319
+ if (ui.placeholderColor) {
1320
+ if (!ui.placeholderDelay)
1321
+ image.isPlacehold = true;
1322
+ else
1323
+ setTimeout(() => {
1324
+ if (!image.ready) {
1325
+ image.isPlacehold = true;
1326
+ ui.forceUpdate('surface');
1327
+ }
1328
+ }, ui.placeholderDelay);
1329
+ }
1335
1330
  }
1336
1331
  return leafPaint;
1337
1332
  }
@@ -1486,7 +1481,7 @@ function checkImage(ui, canvas, paint, allowDraw) {
1486
1481
  }
1487
1482
  function drawImage(ui, canvas, paint, data) {
1488
1483
  canvas.save();
1489
- ui.windingRule ? canvas.clip(ui.windingRule) : canvas.clip();
1484
+ canvas.clipUI(ui);
1490
1485
  if (paint.blendMode)
1491
1486
  canvas.blendMode = paint.blendMode;
1492
1487
  if (data.opacity)
@@ -1537,32 +1532,33 @@ const PaintImageModule = {
1537
1532
  repeatMode
1538
1533
  };
1539
1534
 
1540
- const { toPoint: toPoint$2 } = core.AroundHelper;
1535
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1541
1536
  const realFrom$2 = {};
1542
1537
  const realTo$2 = {};
1543
1538
  function linearGradient(paint, box) {
1544
- let { from, to, type, blendMode, opacity } = paint;
1539
+ let { from, to, type, opacity } = paint;
1545
1540
  toPoint$2(from || 'top', box, realFrom$2);
1546
1541
  toPoint$2(to || 'bottom', box, realTo$2);
1547
1542
  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
1543
  const data = { type, style };
1550
- if (blendMode)
1551
- data.blendMode = blendMode;
1544
+ applyStops(data, style, paint.stops, opacity);
1552
1545
  return data;
1553
1546
  }
1554
- function applyStops(gradient, stops, opacity) {
1547
+ function applyStops(data, gradient, stops, opacity) {
1555
1548
  if (stops) {
1556
- let stop;
1549
+ let stop, color, offset, isTransparent;
1557
1550
  for (let i = 0, len = stops.length; i < len; i++) {
1558
1551
  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
- }
1552
+ if (typeof stop === 'string')
1553
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1554
+ else
1555
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1556
+ gradient.addColorStop(offset, color);
1557
+ if (!isTransparent && hasTransparent(color))
1558
+ isTransparent = true;
1565
1559
  }
1560
+ if (isTransparent)
1561
+ data.isTransparent = true;
1566
1562
  }
1567
1563
  }
1568
1564
 
@@ -1572,17 +1568,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1572
1568
  const realFrom$1 = {};
1573
1569
  const realTo$1 = {};
1574
1570
  function radialGradient(paint, box) {
1575
- let { from, to, type, opacity, blendMode, stretch } = paint;
1571
+ let { from, to, type, opacity, stretch } = paint;
1576
1572
  toPoint$1(from || 'center', box, realFrom$1);
1577
1573
  toPoint$1(to || 'bottom', box, realTo$1);
1578
1574
  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
1575
  const data = { type, style };
1576
+ applyStops(data, style, paint.stops, opacity);
1581
1577
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1582
1578
  if (transform)
1583
1579
  data.transform = transform;
1584
- if (blendMode)
1585
- data.blendMode = blendMode;
1586
1580
  return data;
1587
1581
  }
1588
1582
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1608,17 +1602,15 @@ const { toPoint } = core.AroundHelper;
1608
1602
  const realFrom = {};
1609
1603
  const realTo = {};
1610
1604
  function conicGradient(paint, box) {
1611
- let { from, to, type, opacity, blendMode, stretch } = paint;
1605
+ let { from, to, type, opacity, stretch } = paint;
1612
1606
  toPoint(from || 'center', box, realFrom);
1613
1607
  toPoint(to || 'bottom', box, realTo);
1614
1608
  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
1609
  const data = { type, style };
1610
+ applyStops(data, style, paint.stops, opacity);
1617
1611
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1618
1612
  if (transform)
1619
1613
  data.transform = transform;
1620
- if (blendMode)
1621
- data.blendMode = blendMode;
1622
1614
  return data;
1623
1615
  }
1624
1616
 
@@ -1654,12 +1646,10 @@ function shadow(ui, current, shape) {
1654
1646
  }
1655
1647
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1656
1648
  }
1657
- if (ui.__worldFlipped) {
1649
+ if (ui.__worldFlipped)
1658
1650
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1659
- }
1660
- else {
1651
+ else
1661
1652
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1662
- }
1663
1653
  if (end && index < end)
1664
1654
  other.clearWorld(copyBounds, true);
1665
1655
  });
@@ -1718,12 +1708,10 @@ function innerShadow(ui, current, shape) {
1718
1708
  copyBounds = bounds;
1719
1709
  }
1720
1710
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), 'source-in');
1721
- if (ui.__worldFlipped) {
1711
+ if (ui.__worldFlipped)
1722
1712
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1723
- }
1724
- else {
1713
+ else
1725
1714
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1726
- }
1727
1715
  if (end && index < end)
1728
1716
  other.clearWorld(copyBounds, true);
1729
1717
  });
@@ -1951,6 +1939,8 @@ function createRows(drawData, content, style) {
1951
1939
  lastCharType = null;
1952
1940
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1953
1941
  word = { data: [] }, row = { words: [] };
1942
+ if (__letterSpacing)
1943
+ content = [...content];
1954
1944
  for (let i = 0, len = content.length; i < len; i++) {
1955
1945
  char = content[i];
1956
1946
  if (char === '\n') {
@@ -2400,10 +2390,9 @@ const ExportModule = {
2400
2390
  else {
2401
2391
  let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2402
2392
  const { worldTransform, isLeafer, leafer, isFrame } = leaf;
2403
- const { slice, clip, trim, padding, onCanvas } = options;
2393
+ const { slice, clip, trim, screenshot, padding, onCanvas } = options;
2404
2394
  const smooth = options.smooth === undefined ? (leafer ? leafer.config.smooth : true) : options.smooth;
2405
2395
  const contextSettings = options.contextSettings || (leafer ? leafer.config.contextSettings : undefined);
2406
- const screenshot = options.screenshot || leaf.isApp;
2407
2396
  const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
2408
2397
  const needFill = draw.FileHelper.isOpaqueImage(filename) || fill, matrix = new draw.Matrix();
2409
2398
  if (screenshot) {
@@ -2439,11 +2428,6 @@ const ExportModule = {
2439
2428
  const scaleData = { scaleX: 1, scaleY: 1 };
2440
2429
  draw.MathHelper.getScaleData(options.scale, options.size, renderBounds, scaleData);
2441
2430
  let pixelRatio = options.pixelRatio || 1;
2442
- if (leaf.isApp) {
2443
- scaleData.scaleX *= pixelRatio;
2444
- scaleData.scaleY *= pixelRatio;
2445
- pixelRatio = leaf.app.pixelRatio;
2446
- }
2447
2431
  let { x, y, width, height } = new draw.Bounds(renderBounds).scale(scaleData.scaleX, scaleData.scaleY);
2448
2432
  if (clip)
2449
2433
  x += clip.x, y += clip.y, width = clip.width, height = clip.height;