@leafer-draw/worker 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/worker.cjs CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var core = require('@leafer/core');
4
4
  var draw = require('@leafer-ui/draw');
5
+ var core$1 = require('@leafer-ui/core');
5
6
 
6
7
  class LeaferCanvas extends core.LeaferCanvasBase {
7
8
  get allowBackgroundColor() { return true; }
@@ -160,17 +161,15 @@ class Watcher {
160
161
  this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
161
162
  this.__updatedList = new core.LeafList();
162
163
  this.totalTimes++;
163
- this.changed = false;
164
- this.hasVisible = false;
165
- this.hasRemove = false;
166
- this.hasAdd = false;
164
+ this.changed = this.hasVisible = this.hasRemove = this.hasAdd = false;
167
165
  }
168
166
  __listenEvents() {
169
- const { target } = this;
170
167
  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)
168
+ this.target.on_([
169
+ [core.PropertyEvent.CHANGE, this.__onAttrChange, this],
170
+ [[core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this],
171
+ [core.WatchEvent.REQUEST, this.__onRquestData, this]
172
+ ])
174
173
  ];
175
174
  }
176
175
  __removeListenEvents() {
@@ -180,8 +179,7 @@ class Watcher {
180
179
  if (this.target) {
181
180
  this.stop();
182
181
  this.__removeListenEvents();
183
- this.target = null;
184
- this.__updatedList = null;
182
+ this.target = this.__updatedList = null;
185
183
  }
186
184
  }
187
185
  }
@@ -286,7 +284,7 @@ class Layouter {
286
284
  this.disabled = true;
287
285
  }
288
286
  layout() {
289
- if (!this.running)
287
+ if (this.layouting || !this.running)
290
288
  return;
291
289
  const { target } = this;
292
290
  this.times = 0;
@@ -369,12 +367,10 @@ class Layouter {
369
367
  }
370
368
  static fullLayout(target) {
371
369
  updateAllMatrix(target, true);
372
- if (target.isBranch) {
370
+ if (target.isBranch)
373
371
  core.BranchHelper.updateBounds(target);
374
- }
375
- else {
372
+ else
376
373
  core.LeafHelper.updateBounds(target);
377
- }
378
374
  updateAllChange(target);
379
375
  }
380
376
  addExtra(leaf) {
@@ -397,11 +393,12 @@ class Layouter {
397
393
  this.__updatedList = event.data.updatedList;
398
394
  }
399
395
  __listenEvents() {
400
- const { target } = this;
401
396
  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)
397
+ this.target.on_([
398
+ [core.LayoutEvent.REQUEST, this.layout, this],
399
+ [core.LayoutEvent.AGAIN, this.layoutAgain, this],
400
+ [core.WatchEvent.DATA, this.__onReceiveWatchData, this]
401
+ ])
405
402
  ];
406
403
  }
407
404
  __removeListenEvents() {
@@ -632,12 +629,13 @@ class Renderer {
632
629
  this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
633
630
  }
634
631
  __listenEvents() {
635
- const { target } = this;
636
632
  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)
633
+ this.target.on_([
634
+ [core.RenderEvent.REQUEST, this.update, this],
635
+ [core.LayoutEvent.END, this.__onLayoutEnd, this],
636
+ [core.RenderEvent.AGAIN, this.renderAgain, this],
637
+ [core.ResizeEvent.RESIZE, this.__onResize, this]
638
+ ])
641
639
  ];
642
640
  }
643
641
  __removeListenEvents() {
@@ -723,32 +721,34 @@ function fillPathOrText(ui, canvas) {
723
721
  ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
724
722
  }
725
723
 
724
+ const Paint = {};
725
+
726
726
  function strokeText(stroke, ui, canvas) {
727
- const { strokeAlign } = ui.__;
728
- const isStrokes = typeof stroke !== 'string';
729
- switch (strokeAlign) {
727
+ switch (ui.__.strokeAlign) {
730
728
  case 'center':
731
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
732
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
729
+ drawCenter$1(stroke, 1, ui, canvas);
733
730
  break;
734
731
  case 'inside':
735
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
732
+ drawAlign(stroke, 'inside', ui, canvas);
736
733
  break;
737
734
  case 'outside':
738
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
735
+ ui.__.__fillAfterStroke ? drawCenter$1(stroke, 2, ui, canvas) : drawAlign(stroke, 'outside', ui, canvas);
739
736
  break;
740
737
  }
741
738
  }
742
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
743
- const { __strokeWidth, __font } = ui.__;
739
+ function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
740
+ const data = ui.__;
741
+ canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
742
+ data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
743
+ }
744
+ function drawAlign(stroke, align, ui, canvas) {
744
745
  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);
746
+ out.font = ui.__.__font;
747
+ drawCenter$1(stroke, 2, ui, out);
748
748
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
749
749
  fillText(ui, out);
750
750
  out.blendMode = 'normal';
751
- if (ui.__worldFlipped)
751
+ if (ui.__worldFlipped || core$1.Platform.fullImageShadow)
752
752
  canvas.copyWorldByReset(out, ui.__nowWorld);
753
753
  else
754
754
  canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
@@ -790,90 +790,60 @@ 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
+ Paint.strokeArrow(stroke, ui, canvas);
822
+ }
823
+ function drawInside(stroke, ui, canvas) {
824
+ const data = ui.__;
825
+ canvas.save();
826
+ data.windingRule ? canvas.clip(data.windingRule) : canvas.clip();
827
+ drawCenter(stroke, 2, ui, canvas);
828
+ canvas.restore();
829
+ }
830
+ function drawOutside(stroke, ui, canvas) {
831
+ const data = ui.__;
832
+ if (data.__fillAfterStroke) {
833
+ drawCenter(stroke, 2, ui, canvas);
838
834
  }
839
835
  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();
836
+ const { renderBounds } = ui.__layout;
837
+ const out = canvas.getSameCanvas(true, true);
838
+ ui.__drawRenderPath(out);
839
+ drawCenter(stroke, 2, ui, out);
840
+ data.windingRule ? out.clip(data.windingRule) : out.clip();
841
+ out.clearWorld(renderBounds);
842
+ if (ui.__worldFlipped || core$1.Platform.fullImageShadow)
843
+ canvas.copyWorldByReset(out, ui.__nowWorld);
844
+ else
845
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
846
+ out.recycle(ui.__nowWorld);
877
847
  }
878
848
  }
879
849
 
@@ -920,9 +890,10 @@ function shape(ui, current, options) {
920
890
  }
921
891
 
922
892
  let recycleMap;
893
+ const { stintSet } = core.DataHelper, { hasTransparent: hasTransparent$1 } = draw.ColorConvert;
923
894
  function compute(attrName, ui) {
924
895
  const data = ui.__, leafPaints = [];
925
- let paints = data.__input[attrName], hasOpacityPixel;
896
+ let paints = data.__input[attrName], isAlphaPixel, isTransparent;
926
897
  if (!(paints instanceof Array))
927
898
  paints = [paints];
928
899
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
@@ -932,29 +903,55 @@ function compute(attrName, ui) {
932
903
  leafPaints.push(item);
933
904
  }
934
905
  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;
906
+ if (leafPaints.length) {
907
+ if (leafPaints.every(item => item.isTransparent)) {
908
+ if (leafPaints.some(item => item.image))
909
+ isAlphaPixel = true;
910
+ isTransparent = true;
911
+ }
912
+ }
913
+ if (attrName === 'fill') {
914
+ stintSet(data, '__isAlphaPixelFill', isAlphaPixel);
915
+ stintSet(data, '__isTransparentFill', isTransparent);
916
+ }
917
+ else {
918
+ stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
919
+ stintSet(data, '__isTransparentStroke', isTransparent);
920
+ }
938
921
  }
939
922
  function getLeafPaint(attrName, paint, ui) {
940
923
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
941
924
  return undefined;
925
+ let data;
942
926
  const { boxBounds } = ui.__layout;
943
927
  switch (paint.type) {
944
- case 'solid':
945
- let { type, blendMode, color, opacity } = paint;
946
- return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
947
928
  case 'image':
948
- return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
929
+ data = draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
930
+ break;
949
931
  case 'linear':
950
- return draw.PaintGradient.linearGradient(paint, boxBounds);
932
+ data = draw.PaintGradient.linearGradient(paint, boxBounds);
933
+ break;
951
934
  case 'radial':
952
- return draw.PaintGradient.radialGradient(paint, boxBounds);
935
+ data = draw.PaintGradient.radialGradient(paint, boxBounds);
936
+ break;
953
937
  case 'angular':
954
- return draw.PaintGradient.conicGradient(paint, boxBounds);
938
+ data = draw.PaintGradient.conicGradient(paint, boxBounds);
939
+ break;
940
+ case 'solid':
941
+ const { type, blendMode, color, opacity } = paint;
942
+ data = { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
943
+ break;
955
944
  default:
956
- return paint.r !== undefined ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
945
+ if (paint.r !== undefined)
946
+ data = { type: 'solid', style: draw.ColorConvert.string(paint) };
957
947
  }
948
+ if (data) {
949
+ if (typeof data.style === 'string' && hasTransparent$1(data.style))
950
+ data.isTransparent = true;
951
+ if (paint.blendMode)
952
+ data.blendMode = paint.blendMode;
953
+ }
954
+ return data;
958
955
  }
959
956
 
960
957
  const PaintModule = {
@@ -1020,12 +1017,10 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1020
1017
 
1021
1018
  const { get: get$2, translate } = core.MatrixHelper;
1022
1019
  const tempBox = new core.Bounds();
1023
- const tempPoint = {};
1024
1020
  const tempScaleData = {};
1021
+ const tempImage = {};
1025
1022
  function createData(leafPaint, image, paint, box) {
1026
- const { blendMode, changeful, sync } = paint;
1027
- if (blendMode)
1028
- leafPaint.blendMode = blendMode;
1023
+ const { changeful, sync } = paint;
1029
1024
  if (changeful)
1030
1025
  leafPaint.changeful = changeful;
1031
1026
  if (sync)
@@ -1033,38 +1028,38 @@ function createData(leafPaint, image, paint, box) {
1033
1028
  leafPaint.data = getPatternData(paint, box, image);
1034
1029
  }
1035
1030
  function getPatternData(paint, box, image) {
1036
- let { width, height } = image;
1037
1031
  if (paint.padding)
1038
1032
  box = tempBox.set(box).shrink(paint.padding);
1039
1033
  if (paint.mode === 'strench')
1040
1034
  paint.mode = 'stretch';
1035
+ let { width, height } = image;
1041
1036
  const { opacity, mode, align, offset, scale, size, rotation, repeat, filters } = paint;
1042
1037
  const sameBox = box.width === width && box.height === height;
1043
1038
  const data = { mode };
1044
1039
  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;
1040
+ core.BoundsHelper.set(tempImage, 0, 0, swapSize ? height : width, swapSize ? width : height);
1041
+ let scaleX, scaleY;
1047
1042
  if (!mode || mode === 'cover' || mode === 'fit') {
1048
1043
  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;
1044
+ scaleX = scaleY = core.BoundsHelper.getFitScale(box, tempImage, mode !== 'fit');
1045
+ core.BoundsHelper.put(box, image, align, scaleX, false, tempImage);
1046
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1052
1047
  }
1053
1048
  }
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;
1049
+ else {
1050
+ if (scale || size) {
1051
+ core.MathHelper.getScaleData(scale, size, image, tempScaleData);
1052
+ scaleX = tempScaleData.scaleX;
1053
+ scaleY = tempScaleData.scaleY;
1054
+ }
1055
+ if (align) {
1056
+ if (scaleX)
1057
+ core.BoundsHelper.scale(tempImage, scaleX, scaleY, true);
1058
+ core.AlignHelper.toPoint(align, tempImage, box, tempImage, true, true);
1059
+ }
1065
1060
  }
1066
1061
  if (offset)
1067
- x += offset.x, y += offset.y;
1062
+ core.PointHelper.move(tempImage, offset);
1068
1063
  switch (mode) {
1069
1064
  case 'stretch':
1070
1065
  if (!sameBox)
@@ -1072,12 +1067,12 @@ function getPatternData(paint, box, image) {
1072
1067
  break;
1073
1068
  case 'normal':
1074
1069
  case 'clip':
1075
- if (x || y || scaleX || rotation)
1076
- clipMode(data, box, x, y, scaleX, scaleY, rotation);
1070
+ if (tempImage.x || tempImage.y || scaleX || rotation)
1071
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1077
1072
  break;
1078
1073
  case 'repeat':
1079
1074
  if (!sameBox || scaleX || rotation)
1080
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1075
+ repeatMode(data, box, width, height, tempImage.x, tempImage.y, scaleX, scaleY, rotation, align);
1081
1076
  if (!repeat)
1082
1077
  data.repeat = 'repeat';
1083
1078
  break;
@@ -1085,7 +1080,7 @@ function getPatternData(paint, box, image) {
1085
1080
  case 'cover':
1086
1081
  default:
1087
1082
  if (scaleX)
1088
- fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1083
+ fillOrFitMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation);
1089
1084
  }
1090
1085
  if (!data.transform) {
1091
1086
  if (box.x || box.y) {
@@ -1118,6 +1113,8 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1118
1113
  }
1119
1114
  else {
1120
1115
  leafPaint = { type: paint.type, image };
1116
+ if (image.hasAlphaPixel)
1117
+ leafPaint.isTransparent = true;
1121
1118
  cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1122
1119
  }
1123
1120
  if (firstUse || image.loading)
@@ -1142,7 +1139,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1142
1139
  ignoreRender(ui, false);
1143
1140
  if (!ui.destroyed) {
1144
1141
  if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1145
- if (image.hasOpacityPixel)
1142
+ if (image.hasAlphaPixel)
1146
1143
  ui.__layout.hitCanvasChanged = true;
1147
1144
  ui.forceUpdate('surface');
1148
1145
  }
@@ -1154,13 +1151,17 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
1154
1151
  onLoadError(ui, event, error);
1155
1152
  leafPaint.loadId = null;
1156
1153
  });
1157
- if (ui.placeholderColor)
1158
- setTimeout(() => {
1159
- if (!(image.ready || image.isPlacehold)) {
1160
- image.isPlacehold = true;
1161
- ui.forceUpdate('surface');
1162
- }
1163
- }, 100);
1154
+ if (ui.placeholderColor) {
1155
+ if (!ui.placeholderDelay)
1156
+ image.isPlacehold = true;
1157
+ else
1158
+ setTimeout(() => {
1159
+ if (!image.ready) {
1160
+ image.isPlacehold = true;
1161
+ ui.forceUpdate('surface');
1162
+ }
1163
+ }, ui.placeholderDelay);
1164
+ }
1164
1165
  }
1165
1166
  return leafPaint;
1166
1167
  }
@@ -1398,32 +1399,33 @@ const PaintImageModule = {
1398
1399
  repeatMode
1399
1400
  };
1400
1401
 
1401
- const { toPoint: toPoint$2 } = core.AroundHelper;
1402
+ const { toPoint: toPoint$2 } = core.AroundHelper, { hasTransparent } = draw.ColorConvert;
1402
1403
  const realFrom$2 = {};
1403
1404
  const realTo$2 = {};
1404
1405
  function linearGradient(paint, box) {
1405
- let { from, to, type, blendMode, opacity } = paint;
1406
+ let { from, to, type, opacity } = paint;
1406
1407
  toPoint$2(from || 'top', box, realFrom$2);
1407
1408
  toPoint$2(to || 'bottom', box, realTo$2);
1408
1409
  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
1410
  const data = { type, style };
1411
- if (blendMode)
1412
- data.blendMode = blendMode;
1411
+ applyStops(data, style, paint.stops, opacity);
1413
1412
  return data;
1414
1413
  }
1415
- function applyStops(gradient, stops, opacity) {
1414
+ function applyStops(data, gradient, stops, opacity) {
1416
1415
  if (stops) {
1417
- let stop;
1416
+ let stop, color, offset, isTransparent;
1418
1417
  for (let i = 0, len = stops.length; i < len; i++) {
1419
1418
  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
- }
1419
+ if (typeof stop === 'string')
1420
+ offset = i / (len - 1), color = draw.ColorConvert.string(stop, opacity);
1421
+ else
1422
+ offset = stop.offset, color = draw.ColorConvert.string(stop.color, opacity);
1423
+ gradient.addColorStop(offset, color);
1424
+ if (!isTransparent && hasTransparent(color))
1425
+ isTransparent = true;
1426
1426
  }
1427
+ if (isTransparent)
1428
+ data.isTransparent = true;
1427
1429
  }
1428
1430
  }
1429
1431
 
@@ -1433,17 +1435,15 @@ const { toPoint: toPoint$1 } = core.AroundHelper;
1433
1435
  const realFrom$1 = {};
1434
1436
  const realTo$1 = {};
1435
1437
  function radialGradient(paint, box) {
1436
- let { from, to, type, opacity, blendMode, stretch } = paint;
1438
+ let { from, to, type, opacity, stretch } = paint;
1437
1439
  toPoint$1(from || 'center', box, realFrom$1);
1438
1440
  toPoint$1(to || 'bottom', box, realTo$1);
1439
1441
  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
1442
  const data = { type, style };
1443
+ applyStops(data, style, paint.stops, opacity);
1442
1444
  const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1443
1445
  if (transform)
1444
1446
  data.transform = transform;
1445
- if (blendMode)
1446
- data.blendMode = blendMode;
1447
1447
  return data;
1448
1448
  }
1449
1449
  function getTransform(box, from, to, stretch, rotate90) {
@@ -1469,17 +1469,15 @@ const { toPoint } = core.AroundHelper;
1469
1469
  const realFrom = {};
1470
1470
  const realTo = {};
1471
1471
  function conicGradient(paint, box) {
1472
- let { from, to, type, opacity, blendMode, stretch } = paint;
1472
+ let { from, to, type, opacity, stretch } = paint;
1473
1473
  toPoint(from || 'center', box, realFrom);
1474
1474
  toPoint(to || 'bottom', box, realTo);
1475
1475
  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
1476
  const data = { type, style };
1477
+ applyStops(data, style, paint.stops, opacity);
1478
1478
  const transform = getTransform(box, realFrom, realTo, stretch || 1, core.Platform.conicGradientRotate90);
1479
1479
  if (transform)
1480
1480
  data.transform = transform;
1481
- if (blendMode)
1482
- data.blendMode = blendMode;
1483
1481
  return data;
1484
1482
  }
1485
1483
 
@@ -1812,6 +1810,8 @@ function createRows(drawData, content, style) {
1812
1810
  lastCharType = null;
1813
1811
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1814
1812
  word = { data: [] }, row = { words: [] };
1813
+ if (__letterSpacing)
1814
+ content = [...content];
1815
1815
  for (let i = 0, len = content.length; i < len; i++) {
1816
1816
  char = content[i];
1817
1817
  if (char === '\n') {