@leafer-ui/node 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/node.esm.js CHANGED
@@ -1,10 +1,10 @@
1
- import { LeaferCanvasBase, Platform, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, ResizeEvent, BoundsHelper, Plugin, MatrixHelper, MathHelper, AlignHelper, ImageEvent, AroundHelper, PointHelper, Direction4 } from '@leafer/core';
1
+ import { LeaferCanvasBase, Platform, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, ResizeEvent, BoundsHelper, Plugin, MatrixHelper, MathHelper, AlignHelper, PointHelper, ImageEvent, AroundHelper, Direction4 } from '@leafer/core';
2
2
  export * from '@leafer/core';
3
3
  export { LeaferImage } from '@leafer/core';
4
4
  import { writeFileSync } from 'fs';
5
- import { HitCanvasManager, InteractionBase } from '@leafer-ui/core';
5
+ import { Platform as Platform$1, HitCanvasManager, InteractionBase } from '@leafer-ui/core';
6
6
  export * from '@leafer-ui/core';
7
- import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect, TwoPointBoundsHelper, Bounds as Bounds$1, FileHelper as FileHelper$1, Platform as Platform$1, Matrix, MathHelper as MathHelper$1, Creator as Creator$1, TaskProcessor, Resource, LeaferCanvasBase as LeaferCanvasBase$1, Debug as Debug$1, Plugin as Plugin$1, UI } from '@leafer-ui/draw';
7
+ import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint as Paint$1, Effect, TwoPointBoundsHelper, Bounds as Bounds$1, FileHelper as FileHelper$1, Platform as Platform$2, Matrix, MathHelper as MathHelper$1, Creator as Creator$1, TaskProcessor, Resource, LeaferCanvasBase as LeaferCanvasBase$1, Debug as Debug$1, Plugin as Plugin$1, UI } from '@leafer-ui/draw';
8
8
 
9
9
  /******************************************************************************
10
10
  Copyright (c) Microsoft Corporation.
@@ -175,17 +175,15 @@ class Watcher {
175
175
  this.target.emitEvent(new WatchEvent(WatchEvent.DATA, { updatedList: this.updatedList }));
176
176
  this.__updatedList = new LeafList();
177
177
  this.totalTimes++;
178
- this.changed = false;
179
- this.hasVisible = false;
180
- this.hasRemove = false;
181
- this.hasAdd = false;
178
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
182
179
  }
183
180
  __listenEvents() {
184
- const { target } = this;
185
181
  this.__eventIds = [
186
- target.on_(PropertyEvent.CHANGE, this.__onAttrChange, this),
187
- target.on_([ChildEvent.ADD, ChildEvent.REMOVE], this.__onChildEvent, this),
188
- target.on_(WatchEvent.REQUEST, this.__onRquestData, this)
182
+ this.target.on_([
183
+ [PropertyEvent.CHANGE, this.__onAttrChange, this],
184
+ [[ChildEvent.ADD, ChildEvent.REMOVE], this.__onChildEvent, this],
185
+ [WatchEvent.REQUEST, this.__onRquestData, this]
186
+ ])
189
187
  ];
190
188
  }
191
189
  __removeListenEvents() {
@@ -195,8 +193,7 @@ class Watcher {
195
193
  if (this.target) {
196
194
  this.stop();
197
195
  this.__removeListenEvents();
198
- this.target = null;
199
- this.__updatedList = null;
196
+ this.target = this.__updatedList = null;
200
197
  }
201
198
  }
202
199
  }
@@ -301,7 +298,7 @@ class Layouter {
301
298
  this.disabled = true;
302
299
  }
303
300
  layout() {
304
- if (!this.running)
301
+ if (this.layouting || !this.running)
305
302
  return;
306
303
  const { target } = this;
307
304
  this.times = 0;
@@ -384,12 +381,10 @@ class Layouter {
384
381
  }
385
382
  static fullLayout(target) {
386
383
  updateAllMatrix(target, true);
387
- if (target.isBranch) {
384
+ if (target.isBranch)
388
385
  BranchHelper.updateBounds(target);
389
- }
390
- else {
386
+ else
391
387
  LeafHelper.updateBounds(target);
392
- }
393
388
  updateAllChange(target);
394
389
  }
395
390
  addExtra(leaf) {
@@ -412,11 +407,12 @@ class Layouter {
412
407
  this.__updatedList = event.data.updatedList;
413
408
  }
414
409
  __listenEvents() {
415
- const { target } = this;
416
410
  this.__eventIds = [
417
- target.on_(LayoutEvent.REQUEST, this.layout, this),
418
- target.on_(LayoutEvent.AGAIN, this.layoutAgain, this),
419
- target.on_(WatchEvent.DATA, this.__onReceiveWatchData, this)
411
+ this.target.on_([
412
+ [LayoutEvent.REQUEST, this.layout, this],
413
+ [LayoutEvent.AGAIN, this.layoutAgain, this],
414
+ [WatchEvent.DATA, this.__onReceiveWatchData, this]
415
+ ])
420
416
  ];
421
417
  }
422
418
  __removeListenEvents() {
@@ -647,12 +643,13 @@ class Renderer {
647
643
  this.target.emitEvent(new RenderEvent(type, this.times, bounds, options));
648
644
  }
649
645
  __listenEvents() {
650
- const { target } = this;
651
646
  this.__eventIds = [
652
- target.on_(RenderEvent.REQUEST, this.update, this),
653
- target.on_(LayoutEvent.END, this.__onLayoutEnd, this),
654
- target.on_(RenderEvent.AGAIN, this.renderAgain, this),
655
- target.on_(ResizeEvent.RESIZE, this.__onResize, this)
647
+ this.target.on_([
648
+ [RenderEvent.REQUEST, this.update, this],
649
+ [LayoutEvent.END, this.__onLayoutEnd, this],
650
+ [RenderEvent.AGAIN, this.renderAgain, this],
651
+ [ResizeEvent.RESIZE, this.__onResize, this]
652
+ ])
656
653
  ];
657
654
  }
658
655
  __removeListenEvents() {
@@ -895,32 +892,34 @@ function fillPathOrText(ui, canvas) {
895
892
  ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
896
893
  }
897
894
 
895
+ const Paint = {};
896
+
898
897
  function strokeText(stroke, ui, canvas) {
899
- const { strokeAlign } = ui.__;
900
- const isStrokes = typeof stroke !== 'string';
901
- switch (strokeAlign) {
898
+ switch (ui.__.strokeAlign) {
902
899
  case 'center':
903
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
904
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
900
+ drawCenter$1(stroke, 1, ui, canvas);
905
901
  break;
906
902
  case 'inside':
907
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
903
+ drawAlign(stroke, 'inside', ui, canvas);
908
904
  break;
909
905
  case 'outside':
910
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
906
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
911
907
  break;
912
908
  }
913
909
  }
914
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
915
- const { __strokeWidth, __font } = ui.__;
910
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
911
+ const data = ui.__;
912
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
913
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
914
+ }
915
+ function drawAlign(stroke, align, ui, canvas) {
916
916
  const out = canvas.getSameCanvas(true, true);
917
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
918
- out.font = __font;
919
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
917
+ out.font = ui.__.__font;
918
+ drawCenter$1(stroke, 2, ui, out);
920
919
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
921
920
  fillText(ui, out);
922
921
  out.blendMode = 'normal';
923
- if (ui.__worldFlipped)
922
+ if (ui.__worldFlipped || Platform$1.fullImageShadow)
924
923
  canvas.copyWorldByReset(out, ui.__nowWorld);
925
924
  else
926
925
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
@@ -962,90 +961,60 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
962
961
  }
963
962
 
964
963
  function stroke(stroke, ui, canvas) {
965
- const options = ui.__;
966
- const { __strokeWidth, strokeAlign, __font } = options;
967
- if (!__strokeWidth)
964
+ const data = ui.__;
965
+ if (!data.__strokeWidth)
968
966
  return;
969
- if (__font) {
967
+ if (data.__font) {
970
968
  strokeText(stroke, ui, canvas);
971
969
  }
972
970
  else {
973
- switch (strokeAlign) {
971
+ switch (data.strokeAlign) {
974
972
  case 'center':
975
- canvas.setStroke(stroke, __strokeWidth, options);
976
- canvas.stroke();
977
- if (options.__useArrow)
978
- strokeArrow(ui, canvas);
973
+ drawCenter(stroke, 1, ui, canvas);
979
974
  break;
980
975
  case 'inside':
981
- canvas.save();
982
- canvas.setStroke(stroke, __strokeWidth * 2, options);
983
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
984
- canvas.stroke();
985
- canvas.restore();
976
+ drawInside(stroke, ui, canvas);
986
977
  break;
987
978
  case 'outside':
988
- const out = canvas.getSameCanvas(true, true);
989
- out.setStroke(stroke, __strokeWidth * 2, options);
990
- ui.__drawRenderPath(out);
991
- out.stroke();
992
- options.windingRule ? out.clip(options.windingRule) : out.clip();
993
- out.clearWorld(ui.__layout.renderBounds);
994
- if (ui.__worldFlipped)
995
- canvas.copyWorldByReset(out, ui.__nowWorld);
996
- else
997
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
998
- out.recycle(ui.__nowWorld);
979
+ drawOutside(stroke, ui, canvas);
999
980
  break;
1000
981
  }
1001
982
  }
1002
983
  }
1003
984
  function strokes(strokes, ui, canvas) {
1004
- const options = ui.__;
1005
- const { __strokeWidth, strokeAlign, __font } = options;
1006
- if (!__strokeWidth)
1007
- return;
1008
- if (__font) {
1009
- 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
+ Paint.strokeArrow(stroke, ui, canvas);
993
+ }
994
+ function drawInside(stroke, ui, canvas) {
995
+ const data = ui.__;
996
+ canvas.save();
997
+ data.windingRule ? canvas.clip(data.windingRule) : canvas.clip();
998
+ drawCenter(stroke, 2, ui, canvas);
999
+ canvas.restore();
1000
+ }
1001
+ function drawOutside(stroke, ui, canvas) {
1002
+ const data = ui.__;
1003
+ if (data.__fillAfterStroke) {
1004
+ drawCenter(stroke, 2, ui, canvas);
1010
1005
  }
1011
1006
  else {
1012
- switch (strokeAlign) {
1013
- case 'center':
1014
- canvas.setStroke(undefined, __strokeWidth, options);
1015
- drawStrokesStyle(strokes, false, ui, canvas);
1016
- if (options.__useArrow)
1017
- strokeArrow(ui, canvas);
1018
- break;
1019
- case 'inside':
1020
- canvas.save();
1021
- canvas.setStroke(undefined, __strokeWidth * 2, options);
1022
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1023
- drawStrokesStyle(strokes, false, ui, canvas);
1024
- canvas.restore();
1025
- break;
1026
- case 'outside':
1027
- const { renderBounds } = ui.__layout;
1028
- const out = canvas.getSameCanvas(true, true);
1029
- ui.__drawRenderPath(out);
1030
- out.setStroke(undefined, __strokeWidth * 2, options);
1031
- drawStrokesStyle(strokes, false, ui, out);
1032
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1033
- out.clearWorld(renderBounds);
1034
- if (ui.__worldFlipped)
1035
- canvas.copyWorldByReset(out, ui.__nowWorld);
1036
- else
1037
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1038
- out.recycle(ui.__nowWorld);
1039
- break;
1040
- }
1041
- }
1042
- }
1043
- function strokeArrow(ui, canvas) {
1044
- if (ui.__.dashPattern) {
1045
- canvas.beginPath();
1046
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
1047
- canvas.dashPattern = null;
1048
- canvas.stroke();
1007
+ const { renderBounds } = ui.__layout;
1008
+ const out = canvas.getSameCanvas(true, true);
1009
+ ui.__drawRenderPath(out);
1010
+ drawCenter(stroke, 2, ui, out);
1011
+ data.windingRule ? out.clip(data.windingRule) : out.clip();
1012
+ out.clearWorld(renderBounds);
1013
+ if (ui.__worldFlipped || Platform$1.fullImageShadow)
1014
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1015
+ else
1016
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1017
+ out.recycle(ui.__nowWorld);
1049
1018
  }
1050
1019
  }
1051
1020
 
@@ -1092,9 +1061,10 @@ function shape(ui, current, options) {
1092
1061
  }
1093
1062
 
1094
1063
  let recycleMap;
1064
+ const { stintSet } = DataHelper, { hasTransparent: hasTransparent$1 } = ColorConvert;
1095
1065
  function compute(attrName, ui) {
1096
1066
  const data = ui.__, leafPaints = [];
1097
- let paints = data.__input[attrName], hasOpacityPixel;
1067
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
1098
1068
  if (!(paints instanceof Array))
1099
1069
  paints = [paints];
1100
1070
  recycleMap = PaintImage.recycleImage(attrName, data);
@@ -1104,29 +1074,55 @@ function compute(attrName, ui) {
1104
1074
  leafPaints.push(item);
1105
1075
  }
1106
1076
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1107
- if (leafPaints.length && leafPaints[0].image)
1108
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1109
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
1077
+ if (leafPaints.length) {
1078
+ if (leafPaints.every(item => item.isTransparent)) {
1079
+ if (leafPaints.some(item => item.image))
1080
+ isAlphaPixel = true;
1081
+ isTransparent = true;
1082
+ }
1083
+ }
1084
+ if (attrName === 'fill') {
1085
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
1086
+ stintSet(data, '__isTransparentFill', isTransparent);
1087
+ }
1088
+ else {
1089
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1090
+ stintSet(data, '__isTransparentStroke', isTransparent);
1091
+ }
1110
1092
  }
1111
1093
  function getLeafPaint(attrName, paint, ui) {
1112
1094
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1113
1095
  return undefined;
1096
+ let data;
1114
1097
  const { boxBounds } = ui.__layout;
1115
1098
  switch (paint.type) {
1116
- case 'solid':
1117
- let { type, blendMode, color, opacity } = paint;
1118
- return { type, blendMode, style: ColorConvert.string(color, opacity) };
1119
1099
  case 'image':
1120
- return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1100
+ data = PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1101
+ break;
1121
1102
  case 'linear':
1122
- return PaintGradient.linearGradient(paint, boxBounds);
1103
+ data = PaintGradient.linearGradient(paint, boxBounds);
1104
+ break;
1123
1105
  case 'radial':
1124
- return PaintGradient.radialGradient(paint, boxBounds);
1106
+ data = PaintGradient.radialGradient(paint, boxBounds);
1107
+ break;
1125
1108
  case 'angular':
1126
- return PaintGradient.conicGradient(paint, boxBounds);
1109
+ data = PaintGradient.conicGradient(paint, boxBounds);
1110
+ break;
1111
+ case 'solid':
1112
+ const { type, blendMode, color, opacity } = paint;
1113
+ data = { type, blendMode, style: ColorConvert.string(color, opacity) };
1114
+ break;
1127
1115
  default:
1128
- return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
1116
+ if (paint.r !== undefined)
1117
+ data = { type: 'solid', style: ColorConvert.string(paint) };
1118
+ }
1119
+ if (data) {
1120
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
1121
+ data.isTransparent = true;
1122
+ if (paint.blendMode)
1123
+ data.blendMode = paint.blendMode;
1129
1124
  }
1125
+ return data;
1130
1126
  }
1131
1127
 
1132
1128
  const PaintModule = {
@@ -1192,12 +1188,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1192
1188
 
1193
1189
  const { get: get$2, translate } = MatrixHelper;
1194
1190
  const tempBox = new Bounds();
1195
- const tempPoint = {};
1196
1191
  const tempScaleData = {};
1192
+ const tempImage = {};
1197
1193
  function createData(leafPaint, image, paint, box) {
1198
- const { blendMode, changeful, sync } = paint;
1199
- if (blendMode)
1200
- leafPaint.blendMode = blendMode;
1194
+ const { changeful, sync } = paint;
1201
1195
  if (changeful)
1202
1196
  leafPaint.changeful = changeful;
1203
1197
  if (sync)
@@ -1205,38 +1199,38 @@ function createData(leafPaint, image, paint, box) {
1205
1199
  leafPaint.data = getPatternData(paint, box, image);
1206
1200
  }
1207
1201
  function getPatternData(paint, box, image) {
1208
- let { width, height } = image;
1209
1202
  if (paint.padding)
1210
1203
  box = tempBox.set(box).shrink(paint.padding);
1211
1204
  if (paint.mode === 'strench')
1212
1205
  paint.mode = 'stretch';
1206
+ let { width, height } = image;
1213
1207
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1214
1208
  const sameBox = box.width === width && box.height === height;
1215
1209
  const data = { mode };
1216
1210
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1217
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1218
- let x = 0, y = 0, scaleX, scaleY;
1211
+ BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1212
+ let scaleX, scaleY;
1219
1213
  if (!mode || mode === 'cover' || mode === 'fit') {
1220
1214
  if (!sameBox || rotation) {
1221
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1222
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1223
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1215
+ scaleX = scaleY = BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1216
+ BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1217
+ BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1224
1218
  }
1225
1219
  }
1226
- else if (scale || size) {
1227
- MathHelper.getScaleData(scale, size, image, tempScaleData);
1228
- scaleX = tempScaleData.scaleX;
1229
- scaleY = tempScaleData.scaleY;
1230
- }
1231
- if (align) {
1232
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1233
- if (scaleX)
1234
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1235
- AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1236
- x += tempPoint.x, y += tempPoint.y;
1220
+ else {
1221
+ if (scale || size) {
1222
+ MathHelper.getScaleData(scale, size, image, tempScaleData);
1223
+ scaleX = tempScaleData.scaleX;
1224
+ scaleY = tempScaleData.scaleY;
1225
+ }
1226
+ if (align) {
1227
+ if (scaleX)
1228
+ BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1229
+ AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1230
+ }
1237
1231
  }
1238
1232
  if (offset)
1239
- x += offset.x, y += offset.y;
1233
+ PointHelper.move(tempImage, offset);
1240
1234
  switch (mode) {
1241
1235
  case 'stretch':
1242
1236
  if (!sameBox)
@@ -1244,12 +1238,12 @@ function getPatternData(paint, box, image) {
1244
1238
  break;
1245
1239
  case 'normal':
1246
1240
  case 'clip':
1247
- if (x || y || scaleX || rotation)
1248
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1241
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1242
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1249
1243
  break;
1250
1244
  case 'repeat':
1251
1245
  if (!sameBox || scaleX || rotation)
1252
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1246
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1253
1247
  if (!repeat)
1254
1248
  data.repeat = 'repeat';
1255
1249
  break;
@@ -1257,7 +1251,7 @@ function getPatternData(paint, box, image) {
1257
1251
  case 'cover':
1258
1252
  default:
1259
1253
  if (scaleX)
1260
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1254
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1261
1255
  }
1262
1256
  if (!data.transform) {
1263
1257
  if (box.x || box.y) {
@@ -1290,6 +1284,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1290
1284
  }
1291
1285
  else {
1292
1286
  leafPaint = { type: paint.type, image };
1287
+ if (image.hasAlphaPixel)
1288
+ leafPaint.isTransparent = true;
1293
1289
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1294
1290
  }
1295
1291
  if (firstUse || image.loading)
@@ -1314,7 +1310,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1314
1310
  ignoreRender(ui, false);
1315
1311
  if (!ui.destroyed) {
1316
1312
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1317
- if (image.hasOpacityPixel)
1313
+ if (image.hasAlphaPixel)
1318
1314
  ui.__layout.hitCanvasChanged = true;
1319
1315
  ui.forceUpdate('surface');
1320
1316
  }
@@ -1326,13 +1322,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1326
1322
  onLoadError(ui, event, error);
1327
1323
  leafPaint.loadId = null;
1328
1324
  });
1329
- if (ui.placeholderColor)
1330
- setTimeout(() => {
1331
- if (!(image.ready || image.isPlacehold)) {
1332
- image.isPlacehold = true;
1333
- ui.forceUpdate('surface');
1334
- }
1335
- }, 100);
1325
+ if (ui.placeholderColor) {
1326
+ if (!ui.placeholderDelay)
1327
+ image.isPlacehold = true;
1328
+ else
1329
+ setTimeout(() => {
1330
+ if (!image.ready) {
1331
+ image.isPlacehold = true;
1332
+ ui.forceUpdate('surface');
1333
+ }
1334
+ }, ui.placeholderDelay);
1335
+ }
1336
1336
  }
1337
1337
  return leafPaint;
1338
1338
  }
@@ -1538,32 +1538,33 @@ const PaintImageModule = {
1538
1538
  repeatMode
1539
1539
  };
1540
1540
 
1541
- const { toPoint: toPoint$2 } = AroundHelper;
1541
+ const { toPoint: toPoint$2 } = AroundHelper, { hasTransparent } = ColorConvert;
1542
1542
  const realFrom$2 = {};
1543
1543
  const realTo$2 = {};
1544
1544
  function linearGradient(paint, box) {
1545
- let { from, to, type, blendMode, opacity } = paint;
1545
+ let { from, to, type, opacity } = paint;
1546
1546
  toPoint$2(from || 'top', box, realFrom$2);
1547
1547
  toPoint$2(to || 'bottom', box, realTo$2);
1548
1548
  const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1549
- applyStops(style, paint.stops, opacity);
1550
1549
  const data = { type, style };
1551
- if (blendMode)
1552
- data.blendMode = blendMode;
1550
+ applyStops(data, style, paint.stops, opacity);
1553
1551
  return data;
1554
1552
  }
1555
- function applyStops(gradient, stops, opacity) {
1553
+ function applyStops(data, gradient, stops, opacity) {
1556
1554
  if (stops) {
1557
- let stop;
1555
+ let stop, color, offset, isTransparent;
1558
1556
  for (let i = 0, len = stops.length; i < len; i++) {
1559
1557
  stop = stops[i];
1560
- if (typeof stop === 'string') {
1561
- gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
1562
- }
1563
- else {
1564
- gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
1565
- }
1558
+ if (typeof stop === 'string')
1559
+ offset = i / (len - 1), color = ColorConvert.string(stop, opacity);
1560
+ else
1561
+ offset = stop.offset, color = ColorConvert.string(stop.color, opacity);
1562
+ gradient.addColorStop(offset, color);
1563
+ if (!isTransparent && hasTransparent(color))
1564
+ isTransparent = true;
1566
1565
  }
1566
+ if (isTransparent)
1567
+ data.isTransparent = true;
1567
1568
  }
1568
1569
  }
1569
1570
 
@@ -1573,17 +1574,15 @@ const { toPoint: toPoint$1 } = AroundHelper;
1573
1574
  const realFrom$1 = {};
1574
1575
  const realTo$1 = {};
1575
1576
  function radialGradient(paint, box) {
1576
- let { from, to, type, opacity, blendMode, stretch } = paint;
1577
+ let { from, to, type, opacity, stretch } = paint;
1577
1578
  toPoint$1(from || 'center', box, realFrom$1);
1578
1579
  toPoint$1(to || 'bottom', box, realTo$1);
1579
1580
  const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1580
- applyStops(style, paint.stops, opacity);
1581
1581
  const data = { type, style };
1582
+ applyStops(data, style, paint.stops, opacity);
1582
1583
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1583
1584
  if (transform)
1584
1585
  data.transform = transform;
1585
- if (blendMode)
1586
- data.blendMode = blendMode;
1587
1586
  return data;
1588
1587
  }
1589
1588
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1609,17 +1608,15 @@ const { toPoint } = AroundHelper;
1609
1608
  const realFrom = {};
1610
1609
  const realTo = {};
1611
1610
  function conicGradient(paint, box) {
1612
- let { from, to, type, opacity, blendMode, stretch } = paint;
1611
+ let { from, to, type, opacity, stretch } = paint;
1613
1612
  toPoint(from || 'center', box, realFrom);
1614
1613
  toPoint(to || 'bottom', box, realTo);
1615
1614
  const style = Platform.conicGradientSupport ? Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo));
1616
- applyStops(style, paint.stops, opacity);
1617
1615
  const data = { type, style };
1616
+ applyStops(data, style, paint.stops, opacity);
1618
1617
  const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
1619
1618
  if (transform)
1620
1619
  data.transform = transform;
1621
- if (blendMode)
1622
- data.blendMode = blendMode;
1623
1620
  return data;
1624
1621
  }
1625
1622
 
@@ -1952,6 +1949,8 @@ function createRows(drawData, content, style) {
1952
1949
  lastCharType = null;
1953
1950
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1954
1951
  word = { data: [] }, row = { words: [] };
1952
+ if (__letterSpacing)
1953
+ content = [...content];
1955
1954
  for (let i = 0, len = content.length; i < len; i++) {
1956
1955
  char = content[i];
1957
1956
  if (char === '\n') {
@@ -2358,7 +2357,7 @@ const ColorConvertModule = {
2358
2357
 
2359
2358
  Object.assign(TextConvert, TextConvertModule);
2360
2359
  Object.assign(ColorConvert, ColorConvertModule);
2361
- Object.assign(Paint, PaintModule);
2360
+ Object.assign(Paint$1, PaintModule);
2362
2361
  Object.assign(PaintImage, PaintImageModule);
2363
2362
  Object.assign(PaintGradient, PaintGradientModule);
2364
2363
  Object.assign(Effect, EffectModule);
@@ -2388,8 +2387,8 @@ const ExportModule = {
2388
2387
  const fileType = FileHelper$1.fileType(filename);
2389
2388
  const isDownload = filename.includes('.');
2390
2389
  options = FileHelper$1.getExportOptions(options);
2391
- const { toURL } = Platform$1;
2392
- const { download } = Platform$1.origin;
2390
+ const { toURL } = Platform$2;
2391
+ const { download } = Platform$2.origin;
2393
2392
  if (fileType === 'json') {
2394
2393
  isDownload && download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
2395
2394
  result = { data: isDownload ? true : leaf.toJSON(options.json) };
@@ -2401,10 +2400,9 @@ const ExportModule = {
2401
2400
  else {
2402
2401
  let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2403
2402
  const { worldTransform, isLeafer, leafer, isFrame } = leaf;
2404
- const { slice, clip, trim, padding, onCanvas } = options;
2403
+ const { slice, clip, trim, screenshot, padding, onCanvas } = options;
2405
2404
  const smooth = options.smooth === undefined ? (leafer ? leafer.config.smooth : true) : options.smooth;
2406
2405
  const contextSettings = options.contextSettings || (leafer ? leafer.config.contextSettings : undefined);
2407
- const screenshot = options.screenshot || leaf.isApp;
2408
2406
  const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
2409
2407
  const needFill = FileHelper$1.isOpaqueImage(filename) || fill, matrix = new Matrix();
2410
2408
  if (screenshot) {
@@ -2440,11 +2438,6 @@ const ExportModule = {
2440
2438
  const scaleData = { scaleX: 1, scaleY: 1 };
2441
2439
  MathHelper$1.getScaleData(options.scale, options.size, renderBounds, scaleData);
2442
2440
  let pixelRatio = options.pixelRatio || 1;
2443
- if (leaf.isApp) {
2444
- scaleData.scaleX *= pixelRatio;
2445
- scaleData.scaleY *= pixelRatio;
2446
- pixelRatio = leaf.app.pixelRatio;
2447
- }
2448
2441
  let { x, y, width, height } = new Bounds$1(renderBounds).scale(scaleData.scaleX, scaleData.scaleY);
2449
2442
  if (clip)
2450
2443
  x += clip.x, y += clip.y, width = clip.width, height = clip.height;
@@ -2498,7 +2491,7 @@ const ExportModule = {
2498
2491
  return addTask((success) => new Promise((resolve) => {
2499
2492
  const getResult = () => __awaiter(this, void 0, void 0, function* () {
2500
2493
  if (!Resource.isComplete)
2501
- return Platform$1.requestRender(getResult);
2494
+ return Platform$2.requestRender(getResult);
2502
2495
  const result = ExportModule.syncExport(leaf, filename, options);
2503
2496
  if (result.data instanceof Promise)
2504
2497
  result.data = yield result.data;
@@ -2543,7 +2536,7 @@ canvas.export = function (filename, options) {
2543
2536
  };
2544
2537
  canvas.toBlob = function (type, quality) {
2545
2538
  return new Promise((resolve) => {
2546
- Platform$1.origin.canvasToBolb(this.view, type, quality).then((blob) => {
2539
+ Platform$2.origin.canvasToBolb(this.view, type, quality).then((blob) => {
2547
2540
  resolve(blob);
2548
2541
  }).catch((e) => {
2549
2542
  debug.error(e);
@@ -2552,11 +2545,11 @@ canvas.toBlob = function (type, quality) {
2552
2545
  });
2553
2546
  };
2554
2547
  canvas.toDataURL = function (type, quality) {
2555
- return Platform$1.origin.canvasToDataURL(this.view, type, quality);
2548
+ return Platform$2.origin.canvasToDataURL(this.view, type, quality);
2556
2549
  };
2557
2550
  canvas.saveAs = function (filename, quality) {
2558
2551
  return new Promise((resolve) => {
2559
- Platform$1.origin.canvasSaveAs(this.view, filename, quality).then(() => {
2552
+ Platform$2.origin.canvasSaveAs(this.view, filename, quality).then(() => {
2560
2553
  resolve(true);
2561
2554
  }).catch((e) => {
2562
2555
  debug.error(e);