@leafer-draw/worker 1.9.7 → 1.9.9

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
@@ -427,6 +427,7 @@ class Renderer {
427
427
  usePartRender: true,
428
428
  maxFPS: 120
429
429
  };
430
+ this.frames = [];
430
431
  this.target = target;
431
432
  this.canvas = canvas;
432
433
  if (userConfig) this.config = core.DataHelper.default(userConfig, this.config);
@@ -579,12 +580,15 @@ class Renderer {
579
580
  const target = this.target;
580
581
  if (this.requestTime || !target) return;
581
582
  if (target.parentApp) return target.parentApp.requestRender(false);
582
- const requestTime = this.requestTime = Date.now();
583
+ this.requestTime = this.frameTime || Date.now();
583
584
  const render = () => {
584
- const nowFPS = 1e3 / (Date.now() - requestTime);
585
+ const nowFPS = 1e3 / ((this.frameTime = Date.now()) - this.requestTime);
585
586
  const {maxFPS: maxFPS} = this.config;
586
- if (maxFPS && nowFPS > maxFPS - .5) return core.Platform.requestRender(render);
587
- this.FPS = Math.min(120, Math.ceil(nowFPS));
587
+ if (maxFPS && nowFPS > maxFPS) return core.Platform.requestRender(render);
588
+ const {frames: frames} = this;
589
+ if (frames.length > 30) frames.shift();
590
+ frames.push(nowFPS);
591
+ this.FPS = Math.round(frames.reduce((a, b) => a + b, 0) / frames.length);
588
592
  this.requestTime = 0;
589
593
  this.checkRender();
590
594
  };
@@ -851,24 +855,29 @@ function drawOutside(stroke, ui, canvas) {
851
855
  }
852
856
  }
853
857
 
854
- const {getSpread: getSpread, getOuterOf: getOuterOf, getByMove: getByMove, getIntersectData: getIntersectData} = core.BoundsHelper;
858
+ const {getSpread: getSpread, copyAndSpread: copyAndSpread, toOuterOf: toOuterOf, getOuterOf: getOuterOf, getByMove: getByMove, move: move$1, getIntersectData: getIntersectData} = core.BoundsHelper;
859
+
860
+ const tempBounds$1 = {};
855
861
 
856
862
  function shape(ui, current, options) {
857
863
  const canvas = current.getSameCanvas();
858
- const nowWorld = ui.__nowWorld, currentBounds = current.bounds;
859
- let bounds, matrix, fitMatrix, shapeBounds, worldCanvas;
864
+ const currentBounds = current.bounds, nowWorld = ui.__nowWorld, layout = ui.__layout;
865
+ const nowWorldShapeBounds = ui.__nowWorldShapeBounds || (ui.__nowWorldShapeBounds = {});
866
+ toOuterOf(layout.strokeSpread ? (copyAndSpread(tempBounds$1, layout.boxBounds, layout.strokeSpread),
867
+ tempBounds$1) : layout.boxBounds, nowWorld, nowWorldShapeBounds);
868
+ let bounds, renderBounds, matrix, fitMatrix, shapeBounds, worldCanvas;
860
869
  let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true);
861
- if (currentBounds.includes(nowWorld)) {
870
+ if (currentBounds.includes(nowWorldShapeBounds)) {
862
871
  worldCanvas = canvas;
863
- bounds = shapeBounds = nowWorld;
872
+ bounds = shapeBounds = nowWorldShapeBounds;
873
+ renderBounds = nowWorld;
864
874
  } else {
865
- const {renderShapeSpread: spread} = ui.__layout;
866
875
  let worldClipBounds;
867
876
  if (core.Platform.fullImageShadow) {
868
- worldClipBounds = nowWorld;
877
+ worldClipBounds = nowWorldShapeBounds;
869
878
  } else {
870
- const spreadBounds = spread ? getSpread(currentBounds, scaleX === scaleY ? spread * scaleX : [ spread * scaleY, spread * scaleX ]) : currentBounds;
871
- worldClipBounds = getIntersectData(spreadBounds, nowWorld);
879
+ const spreadBounds = layout.renderShapeSpread ? getSpread(currentBounds, core.FourNumberHelper.swapAndScale(layout.renderShapeSpread, scaleX, scaleY)) : currentBounds;
880
+ worldClipBounds = getIntersectData(spreadBounds, nowWorldShapeBounds);
872
881
  }
873
882
  fitMatrix = currentBounds.getFitMatrix(worldClipBounds);
874
883
  let {a: fitScaleX, d: fitScaleY} = fitMatrix;
@@ -878,8 +887,10 @@ function shape(ui, current, options) {
878
887
  scaleX *= fitScaleX;
879
888
  scaleY *= fitScaleY;
880
889
  }
881
- shapeBounds = getOuterOf(nowWorld, fitMatrix);
890
+ shapeBounds = getOuterOf(nowWorldShapeBounds, fitMatrix);
882
891
  bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
892
+ renderBounds = getOuterOf(nowWorld, fitMatrix);
893
+ move$1(renderBounds, -fitMatrix.e, -fitMatrix.f);
883
894
  const userMatrix = options.matrix;
884
895
  if (userMatrix) {
885
896
  matrix = new core.Matrix(fitMatrix);
@@ -898,6 +909,7 @@ function shape(ui, current, options) {
898
909
  matrix: matrix,
899
910
  fitMatrix: fitMatrix,
900
911
  bounds: bounds,
912
+ renderBounds: renderBounds,
901
913
  worldCanvas: worldCanvas,
902
914
  shapeBounds: shapeBounds,
903
915
  scaleX: scaleX,
@@ -1001,7 +1013,7 @@ const PaintModule = {
1001
1013
  shape: shape
1002
1014
  };
1003
1015
 
1004
- let origin = {}, tempMatrix = core.getMatrixData();
1016
+ let origin = {}, tempMatrix$1 = core.getMatrixData();
1005
1017
 
1006
1018
  const {get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = core.MatrixHelper;
1007
1019
 
@@ -1016,12 +1028,12 @@ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1016
1028
  data.transform = transform;
1017
1029
  }
1018
1030
 
1019
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipSize) {
1031
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1020
1032
  const transform = get$3();
1021
1033
  layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1022
- if (clipSize) {
1023
- tempMatrix.a = box.width / clipSize.width, tempMatrix.d = box.height / clipSize.height;
1024
- multiplyParent(transform, tempMatrix);
1034
+ if (clipScaleX) {
1035
+ tempMatrix$1.a = clipScaleX, tempMatrix$1.d = clipScaleY;
1036
+ multiplyParent(transform, tempMatrix$1);
1025
1037
  }
1026
1038
  data.transform = transform;
1027
1039
  }
@@ -1122,7 +1134,12 @@ function getPatternData(paint, box, image) {
1122
1134
 
1123
1135
  case "normal":
1124
1136
  case "clip":
1125
- if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, paint.clipSize);
1137
+ if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) {
1138
+ let clipScaleX, clipScaleY;
1139
+ if (clipSize) clipScaleX = box.width / clipSize.width, clipScaleY = box.height / clipSize.height;
1140
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1141
+ if (clipScaleX) scaleX = scaleX ? scaleX * clipScaleX : scaleX, scaleY = scaleY ? scaleY * clipScaleY : clipScaleY;
1142
+ }
1126
1143
  break;
1127
1144
 
1128
1145
  case "repeat":
@@ -1280,7 +1297,7 @@ function ignoreRender(ui, value) {
1280
1297
 
1281
1298
  const {get: get$1, scale: scale, copy: copy$1} = core.MatrixHelper;
1282
1299
 
1283
- const {floor: floor, ceil: ceil, max: max, abs: abs} = Math;
1300
+ const {floor: floor, ceil: ceil, max: max$1, abs: abs} = Math;
1284
1301
 
1285
1302
  function createPattern(ui, paint, pixelRatio) {
1286
1303
  let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
@@ -1329,8 +1346,8 @@ function createPattern(ui, paint, pixelRatio) {
1329
1346
  if (transform || scaleX !== 1 || scaleY !== 1) {
1330
1347
  const canvasWidth = width + (xGap || 0);
1331
1348
  const canvasHeight = height + (yGap || 0);
1332
- scaleX /= canvasWidth / max(floor(canvasWidth), 1);
1333
- scaleY /= canvasHeight / max(floor(canvasHeight), 1);
1349
+ scaleX /= canvasWidth / max$1(floor(canvasWidth), 1);
1350
+ scaleY /= canvasHeight / max$1(floor(canvasHeight), 1);
1334
1351
  if (!imageMatrix) {
1335
1352
  imageMatrix = get$1();
1336
1353
  if (transform) copy$1(imageMatrix, transform);
@@ -1389,17 +1406,15 @@ function checkImage(ui, canvas, paint, allowDraw) {
1389
1406
  if (allowDraw) {
1390
1407
  if (data.repeat) {
1391
1408
  allowDraw = false;
1392
- } else {
1393
- if (!(paint.changeful || core.Platform.name === "miniapp" && core.ResizeEvent.isResizing(ui) || draw.Export.running)) {
1394
- let {width: width, height: height} = data;
1395
- width *= scaleX * pixelRatio;
1396
- height *= scaleY * pixelRatio;
1397
- if (data.scaleX) {
1398
- width *= data.scaleX;
1399
- height *= data.scaleY;
1400
- }
1401
- allowDraw = width * height > core.Platform.image.maxCacheSize;
1409
+ } else if (!(paint.changeful || core.Platform.name === "miniapp" && core.ResizeEvent.isResizing(ui) || draw.Export.running)) {
1410
+ let {width: width, height: height} = data;
1411
+ width *= scaleX * pixelRatio;
1412
+ height *= scaleY * pixelRatio;
1413
+ if (data.scaleX) {
1414
+ width *= data.scaleX;
1415
+ height *= data.scaleY;
1402
1416
  }
1417
+ allowDraw = width * height > core.Platform.image.maxCacheSize;
1403
1418
  }
1404
1419
  }
1405
1420
  if (allowDraw) {
@@ -1579,75 +1594,82 @@ const PaintGradientModule = {
1579
1594
  getTransform: getTransform
1580
1595
  };
1581
1596
 
1582
- const {copy: copy, toOffsetOutBounds: toOffsetOutBounds$1} = core.BoundsHelper;
1597
+ const {copy: copy, move: move, toOffsetOutBounds: toOffsetOutBounds$1} = core.BoundsHelper, {max: max} = Math;
1583
1598
 
1584
- const tempBounds = {};
1599
+ const tempBounds = {}, tempMatrix = new core.Matrix;
1585
1600
 
1586
1601
  const offsetOutBounds$1 = {};
1587
1602
 
1588
1603
  function shadow(ui, current, shape) {
1589
- let copyBounds, spreadScale;
1590
- const {__nowWorld: nowWorld, __layout: __layout} = ui;
1604
+ let copyBounds, transform;
1605
+ const {__nowWorld: nowWorld} = ui;
1591
1606
  const {shadow: shadow} = ui.__;
1592
- const {worldCanvas: worldCanvas, bounds: bounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
1607
+ const {worldCanvas: worldCanvas, bounds: bounds, renderBounds: renderBounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
1593
1608
  const other = current.getSameCanvas();
1594
1609
  const end = shadow.length - 1;
1595
- toOffsetOutBounds$1(bounds, offsetOutBounds$1);
1610
+ toOffsetOutBounds$1(bounds, offsetOutBounds$1, renderBounds);
1596
1611
  shadow.forEach((item, index) => {
1597
1612
  let otherScale = 1;
1598
1613
  if (item.scaleFixed) {
1599
1614
  const sx = Math.abs(nowWorld.scaleX);
1600
1615
  if (sx > 1) otherScale = 1 / sx;
1601
1616
  }
1602
- other.setWorldShadow(offsetOutBounds$1.offsetX + item.x * scaleX * otherScale, offsetOutBounds$1.offsetY + item.y * scaleY * otherScale, item.blur * scaleX * otherScale, draw.ColorConvert.string(item.color));
1603
- spreadScale = item.spread ? 1 + item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) * otherScale : 0;
1604
- drawWorldShadow(other, offsetOutBounds$1, spreadScale, shape);
1605
- copyBounds = bounds;
1617
+ other.setWorldShadow(offsetOutBounds$1.offsetX + (item.x || 0) * scaleX * otherScale, offsetOutBounds$1.offsetY + (item.y || 0) * scaleY * otherScale, (item.blur || 0) * scaleX * otherScale, draw.ColorConvert.string(item.color));
1618
+ transform = draw.Effect.getShadowTransform(ui, other, shape, item, offsetOutBounds$1, otherScale);
1619
+ if (transform) other.setTransform(transform);
1620
+ drawWorldShadow(other, offsetOutBounds$1, shape);
1621
+ if (transform) other.resetTransform();
1622
+ copyBounds = renderBounds;
1606
1623
  if (item.box) {
1607
1624
  other.restore();
1608
1625
  other.save();
1609
1626
  if (worldCanvas) {
1610
- other.copyWorld(other, bounds, nowWorld, "copy");
1627
+ other.copyWorld(other, renderBounds, nowWorld, "copy");
1611
1628
  copyBounds = nowWorld;
1612
1629
  }
1613
1630
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, "destination-out") : other.copyWorld(shape.canvas, shapeBounds, bounds, "destination-out");
1614
1631
  }
1615
- if (draw.Effect.isTransformShadow(item)) draw.Effect.renderTransformShadow(ui, current, other, copyBounds, item); else core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
1632
+ core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
1616
1633
  if (end && index < end) other.clearWorld(copyBounds);
1617
1634
  });
1618
1635
  other.recycle(copyBounds);
1619
1636
  }
1620
1637
 
1621
- function getShadowSpread(_ui, shadow) {
1622
- let width = 0;
1623
- shadow.forEach(item => width = Math.max(width, Math.max(Math.abs(item.y), Math.abs(item.x)) + (item.spread > 0 ? item.spread : 0) + item.blur * 1.5));
1624
- return width;
1638
+ function getShadowRenderSpread(_ui, shadow) {
1639
+ let top = 0, right = 0, bottom = 0, left = 0, x, y, spread, blur;
1640
+ shadow.forEach(item => {
1641
+ x = item.x || 0, y = item.y || 0, spread = item.spread || 0, blur = (item.blur || 0) * 1.5;
1642
+ top = max(top, spread + blur - y);
1643
+ right = max(right, spread + blur + x);
1644
+ bottom = max(bottom, spread + blur + y);
1645
+ left = max(left, spread + blur - x);
1646
+ });
1647
+ return top === right && right === bottom && bottom === left ? top : [ top, right, bottom, left ];
1648
+ }
1649
+
1650
+ function getShadowTransform(ui, canvas, _shape, shadow, outBounds, otherScale, isInnerShaodw) {
1651
+ if (shadow.spread) {
1652
+ const spreadScale = 1 + shadow.spread * 2 / ui.__layout.strokeBounds.width * otherScale * (isInnerShaodw ? -1 : 1);
1653
+ tempMatrix.set().scaleOfOuter({
1654
+ x: (outBounds.x + outBounds.width / 2) * canvas.pixelRatio,
1655
+ y: (outBounds.y + outBounds.height / 2) * canvas.pixelRatio
1656
+ }, spreadScale);
1657
+ return tempMatrix;
1658
+ }
1659
+ return undefined;
1625
1660
  }
1626
1661
 
1627
- function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1628
- const {bounds: bounds, shapeBounds: shapeBounds} = shape;
1662
+ function drawWorldShadow(canvas, outBounds, shape) {
1663
+ const {shapeBounds: shapeBounds} = shape;
1664
+ let from, to;
1629
1665
  if (core.Platform.fullImageShadow) {
1630
1666
  copy(tempBounds, canvas.bounds);
1631
- tempBounds.x += outBounds.x - shapeBounds.x;
1632
- tempBounds.y += outBounds.y - shapeBounds.y;
1633
- if (spreadScale) {
1634
- const {fitMatrix: fitMatrix} = shape;
1635
- tempBounds.x -= (bounds.x + (fitMatrix ? fitMatrix.e : 0) + bounds.width / 2) * (spreadScale - 1);
1636
- tempBounds.y -= (bounds.y + (fitMatrix ? fitMatrix.f : 0) + bounds.height / 2) * (spreadScale - 1);
1637
- tempBounds.width *= spreadScale;
1638
- tempBounds.height *= spreadScale;
1639
- }
1640
- canvas.copyWorld(shape.canvas, canvas.bounds, tempBounds);
1667
+ move(tempBounds, outBounds.x - shapeBounds.x, outBounds.y - shapeBounds.y);
1668
+ from = canvas.bounds, to = tempBounds;
1641
1669
  } else {
1642
- if (spreadScale) {
1643
- copy(tempBounds, outBounds);
1644
- tempBounds.x -= outBounds.width / 2 * (spreadScale - 1);
1645
- tempBounds.y -= outBounds.height / 2 * (spreadScale - 1);
1646
- tempBounds.width *= spreadScale;
1647
- tempBounds.height *= spreadScale;
1648
- }
1649
- canvas.copyWorld(shape.canvas, shapeBounds, spreadScale ? tempBounds : outBounds);
1670
+ from = shapeBounds, to = outBounds;
1650
1671
  }
1672
+ canvas.copyWorld(shape.canvas, from, to);
1651
1673
  }
1652
1674
 
1653
1675
  const {toOffsetOutBounds: toOffsetOutBounds} = core.BoundsHelper;
@@ -1655,13 +1677,13 @@ const {toOffsetOutBounds: toOffsetOutBounds} = core.BoundsHelper;
1655
1677
  const offsetOutBounds = {};
1656
1678
 
1657
1679
  function innerShadow(ui, current, shape) {
1658
- let copyBounds, spreadScale;
1659
- const {__nowWorld: nowWorld, __layout: __layout} = ui;
1680
+ let copyBounds, transform;
1681
+ const {__nowWorld: nowWorld} = ui;
1660
1682
  const {innerShadow: innerShadow} = ui.__;
1661
- const {worldCanvas: worldCanvas, bounds: bounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
1683
+ const {worldCanvas: worldCanvas, bounds: bounds, renderBounds: renderBounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
1662
1684
  const other = current.getSameCanvas();
1663
1685
  const end = innerShadow.length - 1;
1664
- toOffsetOutBounds(bounds, offsetOutBounds);
1686
+ toOffsetOutBounds(bounds, offsetOutBounds, renderBounds);
1665
1687
  innerShadow.forEach((item, index) => {
1666
1688
  let otherScale = 1;
1667
1689
  if (item.scaleFixed) {
@@ -1669,17 +1691,18 @@ function innerShadow(ui, current, shape) {
1669
1691
  if (sx > 1) otherScale = 1 / sx;
1670
1692
  }
1671
1693
  other.save();
1672
- other.setWorldShadow(offsetOutBounds.offsetX + item.x * scaleX * otherScale, offsetOutBounds.offsetY + item.y * scaleY * otherScale, item.blur * scaleX * otherScale);
1673
- spreadScale = item.spread ? 1 - item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) * otherScale : 0;
1674
- drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
1694
+ other.setWorldShadow(offsetOutBounds.offsetX + (item.x || 0) * scaleX * otherScale, offsetOutBounds.offsetY + (item.y || 0) * scaleY * otherScale, (item.blur || 0) * scaleX * otherScale);
1695
+ transform = draw.Effect.getShadowTransform(ui, other, shape, item, offsetOutBounds, otherScale, true);
1696
+ if (transform) other.setTransform(transform);
1697
+ drawWorldShadow(other, offsetOutBounds, shape);
1675
1698
  other.restore();
1676
1699
  if (worldCanvas) {
1677
- other.copyWorld(other, bounds, nowWorld, "copy");
1700
+ other.copyWorld(other, renderBounds, nowWorld, "copy");
1678
1701
  other.copyWorld(worldCanvas, nowWorld, nowWorld, "source-out");
1679
1702
  copyBounds = nowWorld;
1680
1703
  } else {
1681
1704
  other.copyWorld(shape.canvas, shapeBounds, bounds, "source-out");
1682
- copyBounds = bounds;
1705
+ copyBounds = renderBounds;
1683
1706
  }
1684
1707
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), "source-in");
1685
1708
  core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
@@ -1688,6 +1711,8 @@ function innerShadow(ui, current, shape) {
1688
1711
  other.recycle(copyBounds);
1689
1712
  }
1690
1713
 
1714
+ const getInnerShadowSpread = getShadowRenderSpread;
1715
+
1691
1716
  function blur(ui, current, origin) {
1692
1717
  const {blur: blur} = ui.__;
1693
1718
  origin.setWorldBlur(blur * ui.__nowWorld.a);
@@ -1702,10 +1727,12 @@ const EffectModule = {
1702
1727
  innerShadow: innerShadow,
1703
1728
  blur: blur,
1704
1729
  backgroundBlur: backgroundBlur,
1705
- getShadowSpread: getShadowSpread,
1730
+ getShadowRenderSpread: getShadowRenderSpread,
1731
+ getShadowTransform: getShadowTransform,
1706
1732
  isTransformShadow(_shadow) {
1707
1733
  return undefined;
1708
- }
1734
+ },
1735
+ getInnerShadowSpread: getInnerShadowSpread
1709
1736
  };
1710
1737
 
1711
1738
  const {excludeRenderBounds: excludeRenderBounds} = core.LeafBoundsHelper;
@@ -1722,6 +1749,7 @@ draw.Group.prototype.__renderMask = function(canvas, options) {
1722
1749
  maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity, undefined, true);
1723
1750
  maskCanvas = contentCanvas = null;
1724
1751
  }
1752
+ if (mask === "clipping" || mask === "clipping-path") excludeRenderBounds(child, options) || child.__render(canvas, options);
1725
1753
  maskOpacity = child.__.opacity;
1726
1754
  usedGrayscaleAlpha = false;
1727
1755
  if (mask === "path" || mask === "clipping-path") {
@@ -1739,7 +1767,6 @@ draw.Group.prototype.__renderMask = function(canvas, options) {
1739
1767
  if (!contentCanvas) contentCanvas = getCanvas(canvas);
1740
1768
  child.__render(maskCanvas, options);
1741
1769
  }
1742
- if (mask === "clipping" || mask === "clipping-path") excludeRenderBounds(child, options) || child.__render(canvas, options);
1743
1770
  continue;
1744
1771
  }
1745
1772
  const childBlendMode = maskOpacity === 1 && child.__.__blendMode;
@@ -2301,6 +2328,7 @@ const TextConvertModule = {
2301
2328
  };
2302
2329
 
2303
2330
  function string(color, opacity) {
2331
+ if (!color) return "#000";
2304
2332
  const doOpacity = core.isNumber(opacity) && opacity < 1;
2305
2333
  if (core.isString(color)) {
2306
2334
  if (doOpacity && draw.ColorConvert.object) color = draw.ColorConvert.object(color); else return color;