@leafer-draw/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
@@ -173,17 +173,15 @@ class Watcher {
173
173
  this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
174
174
  this.__updatedList = new core.LeafList();
175
175
  this.totalTimes++;
176
- this.changed = false;
177
- this.hasVisible = false;
178
- this.hasRemove = false;
179
- this.hasAdd = false;
176
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
180
177
  }
181
178
  __listenEvents() {
182
- const { target } = this;
183
179
  this.__eventIds = [
184
- target.on_(core.PropertyEvent.CHANGE, this.__onAttrChange, this),
185
- target.on_([core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this),
186
- target.on_(core.WatchEvent.REQUEST, this.__onRquestData, this)
180
+ this.target.on_([
181
+ [core.PropertyEvent.CHANGE, this.__onAttrChange, this],
182
+ [[core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this],
183
+ [core.WatchEvent.REQUEST, this.__onRquestData, this]
184
+ ])
187
185
  ];
188
186
  }
189
187
  __removeListenEvents() {
@@ -193,8 +191,7 @@ class Watcher {
193
191
  if (this.target) {
194
192
  this.stop();
195
193
  this.__removeListenEvents();
196
- this.target = null;
197
- this.__updatedList = null;
194
+ this.target = this.__updatedList = null;
198
195
  }
199
196
  }
200
197
  }
@@ -299,7 +296,7 @@ class Layouter {
299
296
  this.disabled = true;
300
297
  }
301
298
  layout() {
302
- if (!this.running)
299
+ if (this.layouting || !this.running)
303
300
  return;
304
301
  const { target } = this;
305
302
  this.times = 0;
@@ -382,12 +379,10 @@ class Layouter {
382
379
  }
383
380
  static fullLayout(target) {
384
381
  updateAllMatrix(target, true);
385
- if (target.isBranch) {
382
+ if (target.isBranch)
386
383
  core.BranchHelper.updateBounds(target);
387
- }
388
- else {
384
+ else
389
385
  core.LeafHelper.updateBounds(target);
390
- }
391
386
  updateAllChange(target);
392
387
  }
393
388
  addExtra(leaf) {
@@ -410,11 +405,12 @@ class Layouter {
410
405
  this.__updatedList = event.data.updatedList;
411
406
  }
412
407
  __listenEvents() {
413
- const { target } = this;
414
408
  this.__eventIds = [
415
- target.on_(core.LayoutEvent.REQUEST, this.layout, this),
416
- target.on_(core.LayoutEvent.AGAIN, this.layoutAgain, this),
417
- target.on_(core.WatchEvent.DATA, this.__onReceiveWatchData, this)
409
+ this.target.on_([
410
+ [core.LayoutEvent.REQUEST, this.layout, this],
411
+ [core.LayoutEvent.AGAIN, this.layoutAgain, this],
412
+ [core.WatchEvent.DATA, this.__onReceiveWatchData, this]
413
+ ])
418
414
  ];
419
415
  }
420
416
  __removeListenEvents() {
@@ -645,12 +641,13 @@ class Renderer {
645
641
  this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
646
642
  }
647
643
  __listenEvents() {
648
- const { target } = this;
649
644
  this.__eventIds = [
650
- target.on_(core.RenderEvent.REQUEST, this.update, this),
651
- target.on_(core.LayoutEvent.END, this.__onLayoutEnd, this),
652
- target.on_(core.RenderEvent.AGAIN, this.renderAgain, this),
653
- target.on_(core.ResizeEvent.RESIZE, this.__onResize, this)
645
+ this.target.on_([
646
+ [core.RenderEvent.REQUEST, this.update, this],
647
+ [core.LayoutEvent.END, this.__onLayoutEnd, this],
648
+ [core.RenderEvent.AGAIN, this.renderAgain, this],
649
+ [core.ResizeEvent.RESIZE, this.__onResize, this]
650
+ ])
654
651
  ];
655
652
  }
656
653
  __removeListenEvents() {
@@ -737,35 +734,38 @@ function fillPathOrText(ui, canvas) {
737
734
  }
738
735
 
739
736
  function strokeText(stroke, ui, canvas) {
740
- const { strokeAlign } = ui.__;
741
- const isStrokes = typeof stroke !== 'string';
742
- switch (strokeAlign) {
737
+ switch (ui.__.strokeAlign) {
743
738
  case 'center':
744
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
745
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
739
+ drawCenter$1(stroke, 1, ui, canvas);
746
740
  break;
747
741
  case 'inside':
748
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
742
+ drawAlign(stroke, 'inside', ui, canvas);
749
743
  break;
750
744
  case 'outside':
751
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
745
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
752
746
  break;
753
747
  }
754
748
  }
755
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
756
- const { __strokeWidth, __font } = ui.__;
749
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
750
+ const data = ui.__;
751
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
752
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
753
+ }
754
+ function drawAlign(stroke, align, ui, canvas) {
757
755
  const out = canvas.getSameCanvas(true, true);
758
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
759
- out.font = __font;
760
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
756
+ out.font = ui.__.__font;
757
+ drawCenter$1(stroke, 2, ui, out);
761
758
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
762
759
  fillText(ui, out);
763
760
  out.blendMode = 'normal';
764
- if (ui.__worldFlipped)
761
+ copyWorld(canvas, out, ui);
762
+ out.recycle(ui.__nowWorld);
763
+ }
764
+ function copyWorld(canvas, out, ui) {
765
+ if (ui.__worldFlipped || core.Platform.fullImageShadow)
765
766
  canvas.copyWorldByReset(out, ui.__nowWorld);
766
767
  else
767
768
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
768
- out.recycle(ui.__nowWorld);
769
769
  }
770
770
  function drawTextStroke(ui, canvas) {
771
771
  let row, data = ui.__.__textDrawData;
@@ -803,90 +803,56 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
803
803
  }
804
804
 
805
805
  function stroke(stroke, ui, canvas) {
806
- const options = ui.__;
807
- const { __strokeWidth, strokeAlign, __font } = options;
808
- if (!__strokeWidth)
806
+ const data = ui.__;
807
+ if (!data.__strokeWidth)
809
808
  return;
810
- if (__font) {
809
+ if (data.__font) {
811
810
  strokeText(stroke, ui, canvas);
812
811
  }
813
812
  else {
814
- switch (strokeAlign) {
813
+ switch (data.strokeAlign) {
815
814
  case 'center':
816
- canvas.setStroke(stroke, __strokeWidth, options);
817
- canvas.stroke();
818
- if (options.__useArrow)
819
- strokeArrow(ui, canvas);
815
+ drawCenter(stroke, 1, ui, canvas);
820
816
  break;
821
817
  case 'inside':
822
- canvas.save();
823
- canvas.setStroke(stroke, __strokeWidth * 2, options);
824
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
825
- canvas.stroke();
826
- canvas.restore();
818
+ drawInside(stroke, ui, canvas);
827
819
  break;
828
820
  case 'outside':
829
- const out = canvas.getSameCanvas(true, true);
830
- out.setStroke(stroke, __strokeWidth * 2, options);
831
- ui.__drawRenderPath(out);
832
- out.stroke();
833
- options.windingRule ? out.clip(options.windingRule) : out.clip();
834
- out.clearWorld(ui.__layout.renderBounds);
835
- if (ui.__worldFlipped)
836
- canvas.copyWorldByReset(out, ui.__nowWorld);
837
- else
838
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
839
- out.recycle(ui.__nowWorld);
821
+ drawOutside(stroke, ui, canvas);
840
822
  break;
841
823
  }
842
824
  }
843
825
  }
844
826
  function strokes(strokes, ui, canvas) {
845
- const options = ui.__;
846
- const { __strokeWidth, strokeAlign, __font } = options;
847
- if (!__strokeWidth)
848
- return;
849
- if (__font) {
850
- strokeText(strokes, ui, canvas);
827
+ stroke(strokes, ui, canvas);
828
+ }
829
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
830
+ const data = ui.__;
831
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
832
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
833
+ if (data.__useArrow)
834
+ draw.Paint.strokeArrow(stroke, ui, canvas);
835
+ }
836
+ function drawInside(stroke, ui, canvas) {
837
+ canvas.save();
838
+ canvas.clipUI(ui);
839
+ drawCenter(stroke, 2, ui, canvas);
840
+ canvas.restore();
841
+ }
842
+ function drawOutside(stroke, ui, canvas) {
843
+ const data = ui.__;
844
+ if (data.__fillAfterStroke) {
845
+ drawCenter(stroke, 2, ui, canvas);
851
846
  }
852
847
  else {
853
- switch (strokeAlign) {
854
- case 'center':
855
- canvas.setStroke(undefined, __strokeWidth, options);
856
- drawStrokesStyle(strokes, false, ui, canvas);
857
- if (options.__useArrow)
858
- strokeArrow(ui, canvas);
859
- break;
860
- case 'inside':
861
- canvas.save();
862
- canvas.setStroke(undefined, __strokeWidth * 2, options);
863
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
864
- drawStrokesStyle(strokes, false, ui, canvas);
865
- canvas.restore();
866
- break;
867
- case 'outside':
868
- const { renderBounds } = ui.__layout;
869
- const out = canvas.getSameCanvas(true, true);
870
- ui.__drawRenderPath(out);
871
- out.setStroke(undefined, __strokeWidth * 2, options);
872
- drawStrokesStyle(strokes, false, ui, out);
873
- options.windingRule ? out.clip(options.windingRule) : out.clip();
874
- out.clearWorld(renderBounds);
875
- if (ui.__worldFlipped)
876
- canvas.copyWorldByReset(out, ui.__nowWorld);
877
- else
878
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
879
- out.recycle(ui.__nowWorld);
880
- break;
881
- }
882
- }
883
- }
884
- function strokeArrow(ui, canvas) {
885
- if (ui.__.dashPattern) {
886
- canvas.beginPath();
887
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
888
- canvas.dashPattern = null;
889
- canvas.stroke();
848
+ const { renderBounds } = ui.__layout;
849
+ const out = canvas.getSameCanvas(true, true);
850
+ ui.__drawRenderPath(out);
851
+ drawCenter(stroke, 2, ui, out);
852
+ out.clipUI(data);
853
+ out.clearWorld(renderBounds);
854
+ copyWorld(canvas, out, ui);
855
+ out.recycle(ui.__nowWorld);
890
856
  }
891
857
  }
892
858
 
@@ -933,41 +899,66 @@ function shape(ui, current, options) {
933
899
  }
934
900
 
935
901
  let recycleMap;
902
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
936
903
  function compute(attrName, ui) {
937
904
  const data = ui.__, leafPaints = [];
938
- let paints = data.__input[attrName], hasOpacityPixel;
905
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
939
906
  if (!(paints instanceof Array))
940
907
  paints = [paints];
941
908
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
942
909
  for (let i = 0, len = paints.length, item; i < len; i++) {
943
- item = getLeafPaint(attrName, paints[i], ui);
944
- if (item)
945
- leafPaints.push(item);
910
+ (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
946
911
  }
947
912
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
948
- if (leafPaints.length && leafPaints[0].image)
949
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
950
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
913
+ if (leafPaints.length) {
914
+ if (leafPaints.every(item => item.isTransparent)) {
915
+ if (leafPaints.some(item => item.image))
916
+ isAlphaPixel = true;
917
+ isTransparent = true;
918
+ }
919
+ }
920
+ if (attrName === 'fill') {
921
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
922
+ stintSet(data, '__isTransparentFill', isTransparent);
923
+ }
924
+ else {
925
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
926
+ stintSet(data, '__isTransparentStroke', isTransparent);
927
+ }
951
928
  }
952
929
  function getLeafPaint(attrName, paint, ui) {
953
930
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
954
931
  return undefined;
932
+ let data;
955
933
  const { boxBounds } = ui.__layout;
956
934
  switch (paint.type) {
957
- case 'solid':
958
- let { type, blendMode, color, opacity } = paint;
959
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
960
935
  case 'image':
961
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
936
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
937
+ break;
962
938
  case 'linear':
963
- return draw.PaintGradient.linearGradient(paint, boxBounds);
939
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
940
+ break;
964
941
  case 'radial':
965
- return draw.PaintGradient.radialGradient(paint, boxBounds);
942
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
943
+ break;
966
944
  case 'angular':
967
- return draw.PaintGradient.conicGradient(paint, boxBounds);
945
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
946
+ break;
947
+ case 'solid':
948
+ const { type, color, opacity } = paint;
949
+ data = { type, style: draw.ColorConvert.string(color, opacity) };
950
+ break;
968
951
  default:
969
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
952
+ if (paint.r !== undefined)
953
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
970
954
  }
955
+ if (data) {
956
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
957
+ data.isTransparent = true;
958
+ if (paint.blendMode)
959
+ data.blendMode = paint.blendMode;
960
+ }
961
+ return data;
971
962
  }
972
963
 
973
964
  const PaintModule = {
@@ -1033,12 +1024,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1033
1024
 
1034
1025
  const { get: get$2, translate } = core.MatrixHelper;
1035
1026
  const tempBox = new core.Bounds();
1036
- const tempPoint = {};
1037
1027
  const tempScaleData = {};
1028
+ const tempImage = {};
1038
1029
  function createData(leafPaint, image, paint, box) {
1039
- const { blendMode, changeful, sync } = paint;
1040
- if (blendMode)
1041
- leafPaint.blendMode = blendMode;
1030
+ const { changeful, sync } = paint;
1042
1031
  if (changeful)
1043
1032
  leafPaint.changeful = changeful;
1044
1033
  if (sync)
@@ -1046,38 +1035,38 @@ function createData(leafPaint, image, paint, box) {
1046
1035
  leafPaint.data = getPatternData(paint, box, image);
1047
1036
  }
1048
1037
  function getPatternData(paint, box, image) {
1049
- let { width, height } = image;
1050
1038
  if (paint.padding)
1051
1039
  box = tempBox.set(box).shrink(paint.padding);
1052
1040
  if (paint.mode === 'strench')
1053
1041
  paint.mode = 'stretch';
1042
+ let { width, height } = image;
1054
1043
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1055
1044
  const sameBox = box.width === width && box.height === height;
1056
1045
  const data = { mode };
1057
1046
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1058
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1059
- let x = 0, y = 0, scaleX, scaleY;
1047
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1048
+ let scaleX, scaleY;
1060
1049
  if (!mode || mode === 'cover' || mode === 'fit') {
1061
1050
  if (!sameBox || rotation) {
1062
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1063
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1064
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1051
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1052
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1053
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1065
1054
  }
1066
1055
  }
1067
- else if (scale || size) {
1068
- core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1069
- scaleX = tempScaleData.scaleX;
1070
- scaleY = tempScaleData.scaleY;
1071
- }
1072
- if (align) {
1073
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1074
- if (scaleX)
1075
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1076
- core.AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1077
- x += tempPoint.x, y += tempPoint.y;
1056
+ else {
1057
+ if (scale || size) {
1058
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1059
+ scaleX = tempScaleData.scaleX;
1060
+ scaleY = tempScaleData.scaleY;
1061
+ }
1062
+ if (align) {
1063
+ if (scaleX)
1064
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1065
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1066
+ }
1078
1067
  }
1079
1068
  if (offset)
1080
- x += offset.x, y += offset.y;
1069
+ core.PointHelper.move(tempImage, offset);
1081
1070
  switch (mode) {
1082
1071
  case 'stretch':
1083
1072
  if (!sameBox)
@@ -1085,12 +1074,12 @@ function getPatternData(paint, box, image) {
1085
1074
  break;
1086
1075
  case 'normal':
1087
1076
  case 'clip':
1088
- if (x || y || scaleX || rotation)
1089
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1077
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1078
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1090
1079
  break;
1091
1080
  case 'repeat':
1092
1081
  if (!sameBox || scaleX || rotation)
1093
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1082
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1094
1083
  if (!repeat)
1095
1084
  data.repeat = 'repeat';
1096
1085
  break;
@@ -1098,7 +1087,7 @@ function getPatternData(paint, box, image) {
1098
1087
  case 'cover':
1099
1088
  default:
1100
1089
  if (scaleX)
1101
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1090
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1102
1091
  }
1103
1092
  if (!data.transform) {
1104
1093
  if (box.x || box.y) {
@@ -1131,6 +1120,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1131
1120
  }
1132
1121
  else {
1133
1122
  leafPaint = { type: paint.type, image };
1123
+ if (image.hasAlphaPixel)
1124
+ leafPaint.isTransparent = true;
1134
1125
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1135
1126
  }
1136
1127
  if (firstUse || image.loading)
@@ -1155,7 +1146,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1155
1146
  ignoreRender(ui, false);
1156
1147
  if (!ui.destroyed) {
1157
1148
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1158
- if (image.hasOpacityPixel)
1149
+ if (image.hasAlphaPixel)
1159
1150
  ui.__layout.hitCanvasChanged = true;
1160
1151
  ui.forceUpdate('surface');
1161
1152
  }
@@ -1167,13 +1158,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1167
1158
  onLoadError(ui, event, error);
1168
1159
  leafPaint.loadId = null;
1169
1160
  });
1170
- if (ui.placeholderColor)
1171
- setTimeout(() => {
1172
- if (!(image.ready || image.isPlacehold)) {
1173
- image.isPlacehold = true;
1174
- ui.forceUpdate('surface');
1175
- }
1176
- }, 100);
1161
+ if (ui.placeholderColor) {
1162
+ if (!ui.placeholderDelay)
1163
+ image.isPlacehold = true;
1164
+ else
1165
+ setTimeout(() => {
1166
+ if (!image.ready) {
1167
+ image.isPlacehold = true;
1168
+ ui.forceUpdate('surface');
1169
+ }
1170
+ }, ui.placeholderDelay);
1171
+ }
1177
1172
  }
1178
1173
  return leafPaint;
1179
1174
  }
@@ -1328,7 +1323,7 @@ function checkImage(ui, canvas, paint, allowDraw) {
1328
1323
  }
1329
1324
  function drawImage(ui, canvas, paint, data) {
1330
1325
  canvas.save();
1331
- ui.windingRule ? canvas.clip(ui.windingRule) : canvas.clip();
1326
+ canvas.clipUI(ui);
1332
1327
  if (paint.blendMode)
1333
1328
  canvas.blendMode = paint.blendMode;
1334
1329
  if (data.opacity)
@@ -1379,32 +1374,33 @@ const PaintImageModule = {
1379
1374
  repeatMode
1380
1375
  };
1381
1376
 
1382
- const { toPoint: toPoint$2 } = core.AroundHelper;
1377
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1383
1378
  const realFrom$2 = {};
1384
1379
  const realTo$2 = {};
1385
1380
  function linearGradient(paint, box) {
1386
- let { from, to, type, blendMode, opacity } = paint;
1381
+ let { from, to, type, opacity } = paint;
1387
1382
  toPoint$2(from || 'top', box, realFrom$2);
1388
1383
  toPoint$2(to || 'bottom', box, realTo$2);
1389
1384
  const style = core.Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1390
- applyStops(style, paint.stops, opacity);
1391
1385
  const data = { type, style };
1392
- if (blendMode)
1393
- data.blendMode = blendMode;
1386
+ applyStops(data, style, paint.stops, opacity);
1394
1387
  return data;
1395
1388
  }
1396
- function applyStops(gradient, stops, opacity) {
1389
+ function applyStops(data, gradient, stops, opacity) {
1397
1390
  if (stops) {
1398
- let stop;
1391
+ let stop, color, offset, isTransparent;
1399
1392
  for (let i = 0, len = stops.length; i < len; i++) {
1400
1393
  stop = stops[i];
1401
- if (typeof stop === 'string') {
1402
- gradient.addColorStop(i / (len - 1), draw.ColorConvert.string(stop, opacity));
1403
- }
1404
- else {
1405
- gradient.addColorStop(stop.offset, draw.ColorConvert.string(stop.color, opacity));
1406
- }
1394
+ if (typeof stop === 'string')
1395
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1396
+ else
1397
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1398
+ gradient.addColorStop(offset, color);
1399
+ if (!isTransparent && hasTransparent(color))
1400
+ isTransparent = true;
1407
1401
  }
1402
+ if (isTransparent)
1403
+ data.isTransparent = true;
1408
1404
  }
1409
1405
  }
1410
1406
 
@@ -1414,17 +1410,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1414
1410
  const realFrom$1 = {};
1415
1411
  const realTo$1 = {};
1416
1412
  function radialGradient(paint, box) {
1417
- let { from, to, type, opacity, blendMode, stretch } = paint;
1413
+ let { from, to, type, opacity, stretch } = paint;
1418
1414
  toPoint$1(from || 'center', box, realFrom$1);
1419
1415
  toPoint$1(to || 'bottom', box, realTo$1);
1420
1416
  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));
1421
- applyStops(style, paint.stops, opacity);
1422
1417
  const data = { type, style };
1418
+ applyStops(data, style, paint.stops, opacity);
1423
1419
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1424
1420
  if (transform)
1425
1421
  data.transform = transform;
1426
- if (blendMode)
1427
- data.blendMode = blendMode;
1428
1422
  return data;
1429
1423
  }
1430
1424
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1450,17 +1444,15 @@ const { toPoint } = core.AroundHelper;
1450
1444
  const realFrom = {};
1451
1445
  const realTo = {};
1452
1446
  function conicGradient(paint, box) {
1453
- let { from, to, type, opacity, blendMode, stretch } = paint;
1447
+ let { from, to, type, opacity, stretch } = paint;
1454
1448
  toPoint(from || 'center', box, realFrom);
1455
1449
  toPoint(to || 'bottom', box, realTo);
1456
1450
  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));
1457
- applyStops(style, paint.stops, opacity);
1458
1451
  const data = { type, style };
1452
+ applyStops(data, style, paint.stops, opacity);
1459
1453
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1460
1454
  if (transform)
1461
1455
  data.transform = transform;
1462
- if (blendMode)
1463
- data.blendMode = blendMode;
1464
1456
  return data;
1465
1457
  }
1466
1458
 
@@ -1496,12 +1488,10 @@ function shadow(ui, current, shape) {
1496
1488
  }
1497
1489
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1498
1490
  }
1499
- if (ui.__worldFlipped) {
1491
+ if (ui.__worldFlipped)
1500
1492
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1501
- }
1502
- else {
1493
+ else
1503
1494
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1504
- }
1505
1495
  if (end && index < end)
1506
1496
  other.clearWorld(copyBounds, true);
1507
1497
  });
@@ -1560,12 +1550,10 @@ function innerShadow(ui, current, shape) {
1560
1550
  copyBounds = bounds;
1561
1551
  }
1562
1552
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), 'source-in');
1563
- if (ui.__worldFlipped) {
1553
+ if (ui.__worldFlipped)
1564
1554
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1565
- }
1566
- else {
1555
+ else
1567
1556
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1568
- }
1569
1557
  if (end && index < end)
1570
1558
  other.clearWorld(copyBounds, true);
1571
1559
  });
@@ -1793,6 +1781,8 @@ function createRows(drawData, content, style) {
1793
1781
  lastCharType = null;
1794
1782
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1795
1783
  word = { data: [] }, row = { words: [] };
1784
+ if (__letterSpacing)
1785
+ content = [...content];
1796
1786
  for (let i = 0, len = content.length; i < len; i++) {
1797
1787
  char = content[i];
1798
1788
  if (char === '\n') {
@@ -2242,10 +2232,9 @@ const ExportModule = {
2242
2232
  else {
2243
2233
  let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2244
2234
  const { worldTransform, isLeafer, leafer, isFrame } = leaf;
2245
- const { slice, clip, trim, padding, onCanvas } = options;
2235
+ const { slice, clip, trim, screenshot, padding, onCanvas } = options;
2246
2236
  const smooth = options.smooth === undefined ? (leafer ? leafer.config.smooth : true) : options.smooth;
2247
2237
  const contextSettings = options.contextSettings || (leafer ? leafer.config.contextSettings : undefined);
2248
- const screenshot = options.screenshot || leaf.isApp;
2249
2238
  const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
2250
2239
  const needFill = draw.FileHelper.isOpaqueImage(filename) || fill, matrix = new draw.Matrix();
2251
2240
  if (screenshot) {
@@ -2281,11 +2270,6 @@ const ExportModule = {
2281
2270
  const scaleData = { scaleX: 1, scaleY: 1 };
2282
2271
  draw.MathHelper.getScaleData(options.scale, options.size, renderBounds, scaleData);
2283
2272
  let pixelRatio = options.pixelRatio || 1;
2284
- if (leaf.isApp) {
2285
- scaleData.scaleX *= pixelRatio;
2286
- scaleData.scaleY *= pixelRatio;
2287
- pixelRatio = leaf.app.pixelRatio;
2288
- }
2289
2273
  let { x, y, width, height } = new draw.Bounds(renderBounds).scale(scaleData.scaleX, scaleData.scaleY);
2290
2274
  if (clip)
2291
2275
  x += clip.x, y += clip.y, width = clip.width, height = clip.height;