@leafer-draw/worker 1.6.2 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.cjs CHANGED
@@ -160,17 +160,15 @@ class Watcher {
160
160
  this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
161
161
  this.__updatedList = new core.LeafList();
162
162
  this.totalTimes++;
163
- this.changed = false;
164
- this.hasVisible = false;
165
- this.hasRemove = false;
166
- this.hasAdd = false;
163
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
167
164
  }
168
165
  __listenEvents() {
169
- const { target } = this;
170
166
  this.__eventIds = [
171
- target.on_(core.PropertyEvent.CHANGE, this.__onAttrChange, this),
172
- target.on_([core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this),
173
- target.on_(core.WatchEvent.REQUEST, this.__onRquestData, this)
167
+ this.target.on_([
168
+ [core.PropertyEvent.CHANGE, this.__onAttrChange, this],
169
+ [[core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this],
170
+ [core.WatchEvent.REQUEST, this.__onRquestData, this]
171
+ ])
174
172
  ];
175
173
  }
176
174
  __removeListenEvents() {
@@ -180,8 +178,7 @@ class Watcher {
180
178
  if (this.target) {
181
179
  this.stop();
182
180
  this.__removeListenEvents();
183
- this.target = null;
184
- this.__updatedList = null;
181
+ this.target = this.__updatedList = null;
185
182
  }
186
183
  }
187
184
  }
@@ -286,7 +283,7 @@ class Layouter {
286
283
  this.disabled = true;
287
284
  }
288
285
  layout() {
289
- if (!this.running)
286
+ if (this.layouting || !this.running)
290
287
  return;
291
288
  const { target } = this;
292
289
  this.times = 0;
@@ -369,12 +366,10 @@ class Layouter {
369
366
  }
370
367
  static fullLayout(target) {
371
368
  updateAllMatrix(target, true);
372
- if (target.isBranch) {
369
+ if (target.isBranch)
373
370
  core.BranchHelper.updateBounds(target);
374
- }
375
- else {
371
+ else
376
372
  core.LeafHelper.updateBounds(target);
377
- }
378
373
  updateAllChange(target);
379
374
  }
380
375
  addExtra(leaf) {
@@ -397,11 +392,12 @@ class Layouter {
397
392
  this.__updatedList = event.data.updatedList;
398
393
  }
399
394
  __listenEvents() {
400
- const { target } = this;
401
395
  this.__eventIds = [
402
- target.on_(core.LayoutEvent.REQUEST, this.layout, this),
403
- target.on_(core.LayoutEvent.AGAIN, this.layoutAgain, this),
404
- target.on_(core.WatchEvent.DATA, this.__onReceiveWatchData, this)
396
+ this.target.on_([
397
+ [core.LayoutEvent.REQUEST, this.layout, this],
398
+ [core.LayoutEvent.AGAIN, this.layoutAgain, this],
399
+ [core.WatchEvent.DATA, this.__onReceiveWatchData, this]
400
+ ])
405
401
  ];
406
402
  }
407
403
  __removeListenEvents() {
@@ -632,12 +628,13 @@ class Renderer {
632
628
  this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
633
629
  }
634
630
  __listenEvents() {
635
- const { target } = this;
636
631
  this.__eventIds = [
637
- target.on_(core.RenderEvent.REQUEST, this.update, this),
638
- target.on_(core.LayoutEvent.END, this.__onLayoutEnd, this),
639
- target.on_(core.RenderEvent.AGAIN, this.renderAgain, this),
640
- target.on_(core.ResizeEvent.RESIZE, this.__onResize, this)
632
+ this.target.on_([
633
+ [core.RenderEvent.REQUEST, this.update, this],
634
+ [core.LayoutEvent.END, this.__onLayoutEnd, this],
635
+ [core.RenderEvent.AGAIN, this.renderAgain, this],
636
+ [core.ResizeEvent.RESIZE, this.__onResize, this]
637
+ ])
641
638
  ];
642
639
  }
643
640
  __removeListenEvents() {
@@ -724,35 +721,38 @@ function fillPathOrText(ui, canvas) {
724
721
  }
725
722
 
726
723
  function strokeText(stroke, ui, canvas) {
727
- const { strokeAlign } = ui.__;
728
- const isStrokes = typeof stroke !== 'string';
729
- switch (strokeAlign) {
724
+ switch (ui.__.strokeAlign) {
730
725
  case 'center':
731
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
732
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
726
+ drawCenter$1(stroke, 1, ui, canvas);
733
727
  break;
734
728
  case 'inside':
735
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
729
+ drawAlign(stroke, 'inside', ui, canvas);
736
730
  break;
737
731
  case 'outside':
738
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
732
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
739
733
  break;
740
734
  }
741
735
  }
742
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
743
- const { __strokeWidth, __font } = ui.__;
736
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
737
+ const data = ui.__;
738
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
739
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
740
+ }
741
+ function drawAlign(stroke, align, ui, canvas) {
744
742
  const out = canvas.getSameCanvas(true, true);
745
- out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
746
- out.font = __font;
747
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
743
+ out.font = ui.__.__font;
744
+ drawCenter$1(stroke, 2, ui, out);
748
745
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
749
746
  fillText(ui, out);
750
747
  out.blendMode = 'normal';
751
- if (ui.__worldFlipped)
748
+ copyWorld(canvas, out, ui);
749
+ out.recycle(ui.__nowWorld);
750
+ }
751
+ function copyWorld(canvas, out, ui) {
752
+ if (ui.__worldFlipped || core.Platform.fullImageShadow)
752
753
  canvas.copyWorldByReset(out, ui.__nowWorld);
753
754
  else
754
755
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
755
- out.recycle(ui.__nowWorld);
756
756
  }
757
757
  function drawTextStroke(ui, canvas) {
758
758
  let row, data = ui.__.__textDrawData;
@@ -790,90 +790,56 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
790
790
  }
791
791
 
792
792
  function stroke(stroke, ui, canvas) {
793
- const options = ui.__;
794
- const { __strokeWidth, strokeAlign, __font } = options;
795
- if (!__strokeWidth)
793
+ const data = ui.__;
794
+ if (!data.__strokeWidth)
796
795
  return;
797
- if (__font) {
796
+ if (data.__font) {
798
797
  strokeText(stroke, ui, canvas);
799
798
  }
800
799
  else {
801
- switch (strokeAlign) {
800
+ switch (data.strokeAlign) {
802
801
  case 'center':
803
- canvas.setStroke(stroke, __strokeWidth, options);
804
- canvas.stroke();
805
- if (options.__useArrow)
806
- strokeArrow(ui, canvas);
802
+ drawCenter(stroke, 1, ui, canvas);
807
803
  break;
808
804
  case 'inside':
809
- canvas.save();
810
- canvas.setStroke(stroke, __strokeWidth * 2, options);
811
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
812
- canvas.stroke();
813
- canvas.restore();
805
+ drawInside(stroke, ui, canvas);
814
806
  break;
815
807
  case 'outside':
816
- const out = canvas.getSameCanvas(true, true);
817
- out.setStroke(stroke, __strokeWidth * 2, options);
818
- ui.__drawRenderPath(out);
819
- out.stroke();
820
- options.windingRule ? out.clip(options.windingRule) : out.clip();
821
- out.clearWorld(ui.__layout.renderBounds);
822
- if (ui.__worldFlipped)
823
- canvas.copyWorldByReset(out, ui.__nowWorld);
824
- else
825
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
826
- out.recycle(ui.__nowWorld);
808
+ drawOutside(stroke, ui, canvas);
827
809
  break;
828
810
  }
829
811
  }
830
812
  }
831
813
  function strokes(strokes, ui, canvas) {
832
- const options = ui.__;
833
- const { __strokeWidth, strokeAlign, __font } = options;
834
- if (!__strokeWidth)
835
- return;
836
- if (__font) {
837
- strokeText(strokes, ui, canvas);
814
+ stroke(strokes, ui, canvas);
815
+ }
816
+ function drawCenter(stroke, strokeWidthScale, ui, canvas) {
817
+ const data = ui.__;
818
+ canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
819
+ data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
820
+ if (data.__useArrow)
821
+ draw.Paint.strokeArrow(stroke, ui, canvas);
822
+ }
823
+ function drawInside(stroke, ui, canvas) {
824
+ canvas.save();
825
+ canvas.clipUI(ui);
826
+ drawCenter(stroke, 2, ui, canvas);
827
+ canvas.restore();
828
+ }
829
+ function drawOutside(stroke, ui, canvas) {
830
+ const data = ui.__;
831
+ if (data.__fillAfterStroke) {
832
+ drawCenter(stroke, 2, ui, canvas);
838
833
  }
839
834
  else {
840
- switch (strokeAlign) {
841
- case 'center':
842
- canvas.setStroke(undefined, __strokeWidth, options);
843
- drawStrokesStyle(strokes, false, ui, canvas);
844
- if (options.__useArrow)
845
- strokeArrow(ui, canvas);
846
- break;
847
- case 'inside':
848
- canvas.save();
849
- canvas.setStroke(undefined, __strokeWidth * 2, options);
850
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
851
- drawStrokesStyle(strokes, false, ui, canvas);
852
- canvas.restore();
853
- break;
854
- case 'outside':
855
- const { renderBounds } = ui.__layout;
856
- const out = canvas.getSameCanvas(true, true);
857
- ui.__drawRenderPath(out);
858
- out.setStroke(undefined, __strokeWidth * 2, options);
859
- drawStrokesStyle(strokes, false, ui, out);
860
- options.windingRule ? out.clip(options.windingRule) : out.clip();
861
- out.clearWorld(renderBounds);
862
- if (ui.__worldFlipped)
863
- canvas.copyWorldByReset(out, ui.__nowWorld);
864
- else
865
- canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
866
- out.recycle(ui.__nowWorld);
867
- break;
868
- }
869
- }
870
- }
871
- function strokeArrow(ui, canvas) {
872
- if (ui.__.dashPattern) {
873
- canvas.beginPath();
874
- ui.__drawPathByData(canvas, ui.__.__pathForArrow);
875
- canvas.dashPattern = null;
876
- canvas.stroke();
835
+ const { renderBounds } = ui.__layout;
836
+ const out = canvas.getSameCanvas(true, true);
837
+ ui.__drawRenderPath(out);
838
+ drawCenter(stroke, 2, ui, out);
839
+ out.clipUI(data);
840
+ out.clearWorld(renderBounds);
841
+ copyWorld(canvas, out, ui);
842
+ out.recycle(ui.__nowWorld);
877
843
  }
878
844
  }
879
845
 
@@ -920,41 +886,66 @@ function shape(ui, current, options) {
920
886
  }
921
887
 
922
888
  let recycleMap;
889
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
923
890
  function compute(attrName, ui) {
924
891
  const data = ui.__, leafPaints = [];
925
- let paints = data.__input[attrName], hasOpacityPixel;
892
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
926
893
  if (!(paints instanceof Array))
927
894
  paints = [paints];
928
895
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
929
896
  for (let i = 0, len = paints.length, item; i < len; i++) {
930
- item = getLeafPaint(attrName, paints[i], ui);
931
- if (item)
932
- leafPaints.push(item);
897
+ (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
933
898
  }
934
899
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
935
- if (leafPaints.length && leafPaints[0].image)
936
- hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
937
- attrName === 'fill' ? data.__pixelFill = hasOpacityPixel : data.__pixelStroke = hasOpacityPixel;
900
+ if (leafPaints.length) {
901
+ if (leafPaints.every(item => item.isTransparent)) {
902
+ if (leafPaints.some(item => item.image))
903
+ isAlphaPixel = true;
904
+ isTransparent = true;
905
+ }
906
+ }
907
+ if (attrName === 'fill') {
908
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
909
+ stintSet(data, '__isTransparentFill', isTransparent);
910
+ }
911
+ else {
912
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
913
+ stintSet(data, '__isTransparentStroke', isTransparent);
914
+ }
938
915
  }
939
916
  function getLeafPaint(attrName, paint, ui) {
940
917
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
941
918
  return undefined;
919
+ let data;
942
920
  const { boxBounds } = ui.__layout;
943
921
  switch (paint.type) {
944
- case 'solid':
945
- let { type, blendMode, color, opacity } = paint;
946
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
947
922
  case 'image':
948
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
923
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
924
+ break;
949
925
  case 'linear':
950
- return draw.PaintGradient.linearGradient(paint, boxBounds);
926
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
927
+ break;
951
928
  case 'radial':
952
- return draw.PaintGradient.radialGradient(paint, boxBounds);
929
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
930
+ break;
953
931
  case 'angular':
954
- return draw.PaintGradient.conicGradient(paint, boxBounds);
932
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
933
+ break;
934
+ case 'solid':
935
+ const { type, color, opacity } = paint;
936
+ data = { type, style: draw.ColorConvert.string(color, opacity) };
937
+ break;
955
938
  default:
956
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
939
+ if (paint.r !== undefined)
940
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
941
+ }
942
+ if (data) {
943
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
944
+ data.isTransparent = true;
945
+ if (paint.blendMode)
946
+ data.blendMode = paint.blendMode;
957
947
  }
948
+ return data;
958
949
  }
959
950
 
960
951
  const PaintModule = {
@@ -1020,12 +1011,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1020
1011
 
1021
1012
  const { get: get$2, translate } = core.MatrixHelper;
1022
1013
  const tempBox = new core.Bounds();
1023
- const tempPoint = {};
1024
1014
  const tempScaleData = {};
1015
+ const tempImage = {};
1025
1016
  function createData(leafPaint, image, paint, box) {
1026
- const { blendMode, changeful, sync } = paint;
1027
- if (blendMode)
1028
- leafPaint.blendMode = blendMode;
1017
+ const { changeful, sync } = paint;
1029
1018
  if (changeful)
1030
1019
  leafPaint.changeful = changeful;
1031
1020
  if (sync)
@@ -1033,38 +1022,38 @@ function createData(leafPaint, image, paint, box) {
1033
1022
  leafPaint.data = getPatternData(paint, box, image);
1034
1023
  }
1035
1024
  function getPatternData(paint, box, image) {
1036
- let { width, height } = image;
1037
1025
  if (paint.padding)
1038
1026
  box = tempBox.set(box).shrink(paint.padding);
1039
1027
  if (paint.mode === 'strench')
1040
1028
  paint.mode = 'stretch';
1029
+ let { width, height } = image;
1041
1030
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1042
1031
  const sameBox = box.width === width && box.height === height;
1043
1032
  const data = { mode };
1044
1033
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1045
- const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1046
- let x = 0, y = 0, scaleX, scaleY;
1034
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1035
+ let scaleX, scaleY;
1047
1036
  if (!mode || mode === 'cover' || mode === 'fit') {
1048
1037
  if (!sameBox || rotation) {
1049
- const sw = box.width / swapWidth, sh = box.height / swapHeight;
1050
- scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1051
- x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1038
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1039
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1040
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1052
1041
  }
1053
1042
  }
1054
- else if (scale || size) {
1055
- core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1056
- scaleX = tempScaleData.scaleX;
1057
- scaleY = tempScaleData.scaleY;
1058
- }
1059
- if (align) {
1060
- const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1061
- if (scaleX)
1062
- imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1063
- core.AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1064
- x += tempPoint.x, y += tempPoint.y;
1043
+ else {
1044
+ if (scale || size) {
1045
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1046
+ scaleX = tempScaleData.scaleX;
1047
+ scaleY = tempScaleData.scaleY;
1048
+ }
1049
+ if (align) {
1050
+ if (scaleX)
1051
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1052
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1053
+ }
1065
1054
  }
1066
1055
  if (offset)
1067
- x += offset.x, y += offset.y;
1056
+ core.PointHelper.move(tempImage, offset);
1068
1057
  switch (mode) {
1069
1058
  case 'stretch':
1070
1059
  if (!sameBox)
@@ -1072,12 +1061,12 @@ function getPatternData(paint, box, image) {
1072
1061
  break;
1073
1062
  case 'normal':
1074
1063
  case 'clip':
1075
- if (x || y || scaleX || rotation)
1076
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1064
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1065
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1077
1066
  break;
1078
1067
  case 'repeat':
1079
1068
  if (!sameBox || scaleX || rotation)
1080
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1069
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1081
1070
  if (!repeat)
1082
1071
  data.repeat = 'repeat';
1083
1072
  break;
@@ -1085,7 +1074,7 @@ function getPatternData(paint, box, image) {
1085
1074
  case 'cover':
1086
1075
  default:
1087
1076
  if (scaleX)
1088
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1077
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1089
1078
  }
1090
1079
  if (!data.transform) {
1091
1080
  if (box.x || box.y) {
@@ -1118,6 +1107,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1118
1107
  }
1119
1108
  else {
1120
1109
  leafPaint = { type: paint.type, image };
1110
+ if (image.hasAlphaPixel)
1111
+ leafPaint.isTransparent = true;
1121
1112
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1122
1113
  }
1123
1114
  if (firstUse || image.loading)
@@ -1142,7 +1133,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1142
1133
  ignoreRender(ui, false);
1143
1134
  if (!ui.destroyed) {
1144
1135
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1145
- if (image.hasOpacityPixel)
1136
+ if (image.hasAlphaPixel)
1146
1137
  ui.__layout.hitCanvasChanged = true;
1147
1138
  ui.forceUpdate('surface');
1148
1139
  }
@@ -1154,13 +1145,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1154
1145
  onLoadError(ui, event, error);
1155
1146
  leafPaint.loadId = null;
1156
1147
  });
1157
- if (ui.placeholderColor)
1158
- setTimeout(() => {
1159
- if (!(image.ready || image.isPlacehold)) {
1160
- image.isPlacehold = true;
1161
- ui.forceUpdate('surface');
1162
- }
1163
- }, 100);
1148
+ if (ui.placeholderColor) {
1149
+ if (!ui.placeholderDelay)
1150
+ image.isPlacehold = true;
1151
+ else
1152
+ setTimeout(() => {
1153
+ if (!image.ready) {
1154
+ image.isPlacehold = true;
1155
+ ui.forceUpdate('surface');
1156
+ }
1157
+ }, ui.placeholderDelay);
1158
+ }
1164
1159
  }
1165
1160
  return leafPaint;
1166
1161
  }
@@ -1347,7 +1342,7 @@ function checkImage(ui, canvas, paint, allowDraw) {
1347
1342
  }
1348
1343
  function drawImage(ui, canvas, paint, data) {
1349
1344
  canvas.save();
1350
- ui.windingRule ? canvas.clip(ui.windingRule) : canvas.clip();
1345
+ canvas.clipUI(ui);
1351
1346
  if (paint.blendMode)
1352
1347
  canvas.blendMode = paint.blendMode;
1353
1348
  if (data.opacity)
@@ -1398,32 +1393,33 @@ const PaintImageModule = {
1398
1393
  repeatMode
1399
1394
  };
1400
1395
 
1401
- const { toPoint: toPoint$2 } = core.AroundHelper;
1396
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1402
1397
  const realFrom$2 = {};
1403
1398
  const realTo$2 = {};
1404
1399
  function linearGradient(paint, box) {
1405
- let { from, to, type, blendMode, opacity } = paint;
1400
+ let { from, to, type, opacity } = paint;
1406
1401
  toPoint$2(from || 'top', box, realFrom$2);
1407
1402
  toPoint$2(to || 'bottom', box, realTo$2);
1408
1403
  const style = core.Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1409
- applyStops(style, paint.stops, opacity);
1410
1404
  const data = { type, style };
1411
- if (blendMode)
1412
- data.blendMode = blendMode;
1405
+ applyStops(data, style, paint.stops, opacity);
1413
1406
  return data;
1414
1407
  }
1415
- function applyStops(gradient, stops, opacity) {
1408
+ function applyStops(data, gradient, stops, opacity) {
1416
1409
  if (stops) {
1417
- let stop;
1410
+ let stop, color, offset, isTransparent;
1418
1411
  for (let i = 0, len = stops.length; i < len; i++) {
1419
1412
  stop = stops[i];
1420
- if (typeof stop === 'string') {
1421
- gradient.addColorStop(i / (len - 1), draw.ColorConvert.string(stop, opacity));
1422
- }
1423
- else {
1424
- gradient.addColorStop(stop.offset, draw.ColorConvert.string(stop.color, opacity));
1425
- }
1413
+ if (typeof stop === 'string')
1414
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1415
+ else
1416
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1417
+ gradient.addColorStop(offset, color);
1418
+ if (!isTransparent && hasTransparent(color))
1419
+ isTransparent = true;
1426
1420
  }
1421
+ if (isTransparent)
1422
+ data.isTransparent = true;
1427
1423
  }
1428
1424
  }
1429
1425
 
@@ -1433,17 +1429,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1433
1429
  const realFrom$1 = {};
1434
1430
  const realTo$1 = {};
1435
1431
  function radialGradient(paint, box) {
1436
- let { from, to, type, opacity, blendMode, stretch } = paint;
1432
+ let { from, to, type, opacity, stretch } = paint;
1437
1433
  toPoint$1(from || 'center', box, realFrom$1);
1438
1434
  toPoint$1(to || 'bottom', box, realTo$1);
1439
1435
  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));
1440
- applyStops(style, paint.stops, opacity);
1441
1436
  const data = { type, style };
1437
+ applyStops(data, style, paint.stops, opacity);
1442
1438
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1443
1439
  if (transform)
1444
1440
  data.transform = transform;
1445
- if (blendMode)
1446
- data.blendMode = blendMode;
1447
1441
  return data;
1448
1442
  }
1449
1443
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1469,17 +1463,15 @@ const { toPoint } = core.AroundHelper;
1469
1463
  const realFrom = {};
1470
1464
  const realTo = {};
1471
1465
  function conicGradient(paint, box) {
1472
- let { from, to, type, opacity, blendMode, stretch } = paint;
1466
+ let { from, to, type, opacity, stretch } = paint;
1473
1467
  toPoint(from || 'center', box, realFrom);
1474
1468
  toPoint(to || 'bottom', box, realTo);
1475
1469
  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));
1476
- applyStops(style, paint.stops, opacity);
1477
1470
  const data = { type, style };
1471
+ applyStops(data, style, paint.stops, opacity);
1478
1472
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1479
1473
  if (transform)
1480
1474
  data.transform = transform;
1481
- if (blendMode)
1482
- data.blendMode = blendMode;
1483
1475
  return data;
1484
1476
  }
1485
1477
 
@@ -1515,12 +1507,10 @@ function shadow(ui, current, shape) {
1515
1507
  }
1516
1508
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1517
1509
  }
1518
- if (ui.__worldFlipped) {
1510
+ if (ui.__worldFlipped)
1519
1511
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1520
- }
1521
- else {
1512
+ else
1522
1513
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1523
- }
1524
1514
  if (end && index < end)
1525
1515
  other.clearWorld(copyBounds, true);
1526
1516
  });
@@ -1579,12 +1569,10 @@ function innerShadow(ui, current, shape) {
1579
1569
  copyBounds = bounds;
1580
1570
  }
1581
1571
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), 'source-in');
1582
- if (ui.__worldFlipped) {
1572
+ if (ui.__worldFlipped)
1583
1573
  current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1584
- }
1585
- else {
1574
+ else
1586
1575
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1587
- }
1588
1576
  if (end && index < end)
1589
1577
  other.clearWorld(copyBounds, true);
1590
1578
  });
@@ -1812,6 +1800,8 @@ function createRows(drawData, content, style) {
1812
1800
  lastCharType = null;
1813
1801
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1814
1802
  word = { data: [] }, row = { words: [] };
1803
+ if (__letterSpacing)
1804
+ content = [...content];
1815
1805
  for (let i = 0, len = content.length; i < len; i++) {
1816
1806
  char = content[i];
1817
1807
  if (char === '\n') {