leafer-ui 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/web.cjs CHANGED
@@ -39,7 +39,7 @@ class LeaferCanvas extends core.LeaferCanvasBase {
39
39
  }
40
40
  if (core.Platform.syncDomFont && !this.parentView) {
41
41
  style.display = "none";
42
- document.body.appendChild(this.view);
42
+ if (document.body) document.body.appendChild(this.view);
43
43
  }
44
44
  this.__createContext();
45
45
  if (!this.autoLayout) this.resize(config);
@@ -635,6 +635,7 @@ class Renderer {
635
635
  usePartRender: true,
636
636
  maxFPS: 120
637
637
  };
638
+ this.frames = [];
638
639
  this.target = target;
639
640
  this.canvas = canvas;
640
641
  if (userConfig) this.config = core.DataHelper.default(userConfig, this.config);
@@ -787,12 +788,15 @@ class Renderer {
787
788
  const target = this.target;
788
789
  if (this.requestTime || !target) return;
789
790
  if (target.parentApp) return target.parentApp.requestRender(false);
790
- const requestTime = this.requestTime = Date.now();
791
+ this.requestTime = this.frameTime || Date.now();
791
792
  const render = () => {
792
- const nowFPS = 1e3 / (Date.now() - requestTime);
793
+ const nowFPS = 1e3 / ((this.frameTime = Date.now()) - this.requestTime);
793
794
  const {maxFPS: maxFPS} = this.config;
794
- if (maxFPS && nowFPS > maxFPS - .5) return core.Platform.requestRender(render);
795
- this.FPS = Math.min(120, Math.ceil(nowFPS));
795
+ if (maxFPS && nowFPS > maxFPS) return core.Platform.requestRender(render);
796
+ const {frames: frames} = this;
797
+ if (frames.length > 30) frames.shift();
798
+ frames.push(nowFPS);
799
+ this.FPS = Math.round(frames.reduce((a, b) => a + b, 0) / frames.length);
796
800
  this.requestTime = 0;
797
801
  this.checkRender();
798
802
  };
@@ -1570,24 +1574,29 @@ function drawOutside(stroke, ui, canvas) {
1570
1574
  }
1571
1575
  }
1572
1576
 
1573
- const {getSpread: getSpread, getOuterOf: getOuterOf, getByMove: getByMove, getIntersectData: getIntersectData} = core.BoundsHelper;
1577
+ const {getSpread: getSpread, copyAndSpread: copyAndSpread, toOuterOf: toOuterOf, getOuterOf: getOuterOf, getByMove: getByMove, move: move$1, getIntersectData: getIntersectData} = core.BoundsHelper;
1578
+
1579
+ const tempBounds$1 = {};
1574
1580
 
1575
1581
  function shape(ui, current, options) {
1576
1582
  const canvas = current.getSameCanvas();
1577
- const nowWorld = ui.__nowWorld, currentBounds = current.bounds;
1578
- let bounds, matrix, fitMatrix, shapeBounds, worldCanvas;
1583
+ const currentBounds = current.bounds, nowWorld = ui.__nowWorld, layout = ui.__layout;
1584
+ const nowWorldShapeBounds = ui.__nowWorldShapeBounds || (ui.__nowWorldShapeBounds = {});
1585
+ toOuterOf(layout.strokeSpread ? (copyAndSpread(tempBounds$1, layout.boxBounds, layout.strokeSpread),
1586
+ tempBounds$1) : layout.boxBounds, nowWorld, nowWorldShapeBounds);
1587
+ let bounds, renderBounds, matrix, fitMatrix, shapeBounds, worldCanvas;
1579
1588
  let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true);
1580
- if (currentBounds.includes(nowWorld)) {
1589
+ if (currentBounds.includes(nowWorldShapeBounds)) {
1581
1590
  worldCanvas = canvas;
1582
- bounds = shapeBounds = nowWorld;
1591
+ bounds = shapeBounds = nowWorldShapeBounds;
1592
+ renderBounds = nowWorld;
1583
1593
  } else {
1584
- const {renderShapeSpread: spread} = ui.__layout;
1585
1594
  let worldClipBounds;
1586
1595
  if (core.Platform.fullImageShadow) {
1587
- worldClipBounds = nowWorld;
1596
+ worldClipBounds = nowWorldShapeBounds;
1588
1597
  } else {
1589
- const spreadBounds = spread ? getSpread(currentBounds, scaleX === scaleY ? spread * scaleX : [ spread * scaleY, spread * scaleX ]) : currentBounds;
1590
- worldClipBounds = getIntersectData(spreadBounds, nowWorld);
1598
+ const spreadBounds = layout.renderShapeSpread ? getSpread(currentBounds, core.FourNumberHelper.swapAndScale(layout.renderShapeSpread, scaleX, scaleY)) : currentBounds;
1599
+ worldClipBounds = getIntersectData(spreadBounds, nowWorldShapeBounds);
1591
1600
  }
1592
1601
  fitMatrix = currentBounds.getFitMatrix(worldClipBounds);
1593
1602
  let {a: fitScaleX, d: fitScaleY} = fitMatrix;
@@ -1597,8 +1606,10 @@ function shape(ui, current, options) {
1597
1606
  scaleX *= fitScaleX;
1598
1607
  scaleY *= fitScaleY;
1599
1608
  }
1600
- shapeBounds = getOuterOf(nowWorld, fitMatrix);
1609
+ shapeBounds = getOuterOf(nowWorldShapeBounds, fitMatrix);
1601
1610
  bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
1611
+ renderBounds = getOuterOf(nowWorld, fitMatrix);
1612
+ move$1(renderBounds, -fitMatrix.e, -fitMatrix.f);
1602
1613
  const userMatrix = options.matrix;
1603
1614
  if (userMatrix) {
1604
1615
  matrix = new core.Matrix(fitMatrix);
@@ -1617,6 +1628,7 @@ function shape(ui, current, options) {
1617
1628
  matrix: matrix,
1618
1629
  fitMatrix: fitMatrix,
1619
1630
  bounds: bounds,
1631
+ renderBounds: renderBounds,
1620
1632
  worldCanvas: worldCanvas,
1621
1633
  shapeBounds: shapeBounds,
1622
1634
  scaleX: scaleX,
@@ -1720,7 +1732,7 @@ const PaintModule = {
1720
1732
  shape: shape
1721
1733
  };
1722
1734
 
1723
- let origin = {}, tempMatrix = core.getMatrixData();
1735
+ let origin = {}, tempMatrix$1 = core.getMatrixData();
1724
1736
 
1725
1737
  const {get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent: multiplyParent, scale: scaleHelper, rotate: rotate, skew: skewHelper} = core.MatrixHelper;
1726
1738
 
@@ -1735,12 +1747,12 @@ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1735
1747
  data.transform = transform;
1736
1748
  }
1737
1749
 
1738
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipSize) {
1750
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY) {
1739
1751
  const transform = get$3();
1740
1752
  layout(transform, box, x, y, scaleX, scaleY, rotation, skew);
1741
- if (clipSize) {
1742
- tempMatrix.a = box.width / clipSize.width, tempMatrix.d = box.height / clipSize.height;
1743
- multiplyParent(transform, tempMatrix);
1753
+ if (clipScaleX) {
1754
+ tempMatrix$1.a = clipScaleX, tempMatrix$1.d = clipScaleY;
1755
+ multiplyParent(transform, tempMatrix$1);
1744
1756
  }
1745
1757
  data.transform = transform;
1746
1758
  }
@@ -1841,7 +1853,12 @@ function getPatternData(paint, box, image) {
1841
1853
 
1842
1854
  case "normal":
1843
1855
  case "clip":
1844
- if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, paint.clipSize);
1856
+ if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew) {
1857
+ let clipScaleX, clipScaleY;
1858
+ if (clipSize) clipScaleX = box.width / clipSize.width, clipScaleY = box.height / clipSize.height;
1859
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, clipScaleX, clipScaleY);
1860
+ if (clipScaleX) scaleX = scaleX ? scaleX * clipScaleX : scaleX, scaleY = scaleY ? scaleY * clipScaleY : clipScaleY;
1861
+ }
1845
1862
  break;
1846
1863
 
1847
1864
  case "repeat":
@@ -1999,7 +2016,7 @@ function ignoreRender(ui, value) {
1999
2016
 
2000
2017
  const {get: get$1, scale: scale, copy: copy$1} = core.MatrixHelper;
2001
2018
 
2002
- const {floor: floor, ceil: ceil, max: max, abs: abs} = Math;
2019
+ const {floor: floor, ceil: ceil, max: max$1, abs: abs} = Math;
2003
2020
 
2004
2021
  function createPattern(ui, paint, pixelRatio) {
2005
2022
  let {scaleX: scaleX, scaleY: scaleY} = ui.getRenderScaleData(true, paint.scaleFixed);
@@ -2048,8 +2065,8 @@ function createPattern(ui, paint, pixelRatio) {
2048
2065
  if (transform || scaleX !== 1 || scaleY !== 1) {
2049
2066
  const canvasWidth = width + (xGap || 0);
2050
2067
  const canvasHeight = height + (yGap || 0);
2051
- scaleX /= canvasWidth / max(floor(canvasWidth), 1);
2052
- scaleY /= canvasHeight / max(floor(canvasHeight), 1);
2068
+ scaleX /= canvasWidth / max$1(floor(canvasWidth), 1);
2069
+ scaleY /= canvasHeight / max$1(floor(canvasHeight), 1);
2053
2070
  if (!imageMatrix) {
2054
2071
  imageMatrix = get$1();
2055
2072
  if (transform) copy$1(imageMatrix, transform);
@@ -2108,17 +2125,15 @@ function checkImage(ui, canvas, paint, allowDraw) {
2108
2125
  if (allowDraw) {
2109
2126
  if (data.repeat) {
2110
2127
  allowDraw = false;
2111
- } else {
2112
- if (!(paint.changeful || core.Platform.name === "miniapp" && core.ResizeEvent.isResizing(ui) || draw.Export.running)) {
2113
- let {width: width, height: height} = data;
2114
- width *= scaleX * pixelRatio;
2115
- height *= scaleY * pixelRatio;
2116
- if (data.scaleX) {
2117
- width *= data.scaleX;
2118
- height *= data.scaleY;
2119
- }
2120
- allowDraw = width * height > core.Platform.image.maxCacheSize;
2128
+ } else if (!(paint.changeful || core.Platform.name === "miniapp" && core.ResizeEvent.isResizing(ui) || draw.Export.running)) {
2129
+ let {width: width, height: height} = data;
2130
+ width *= scaleX * pixelRatio;
2131
+ height *= scaleY * pixelRatio;
2132
+ if (data.scaleX) {
2133
+ width *= data.scaleX;
2134
+ height *= data.scaleY;
2121
2135
  }
2136
+ allowDraw = width * height > core.Platform.image.maxCacheSize;
2122
2137
  }
2123
2138
  }
2124
2139
  if (allowDraw) {
@@ -2298,75 +2313,82 @@ const PaintGradientModule = {
2298
2313
  getTransform: getTransform
2299
2314
  };
2300
2315
 
2301
- const {copy: copy, toOffsetOutBounds: toOffsetOutBounds$1} = core.BoundsHelper;
2316
+ const {copy: copy, move: move, toOffsetOutBounds: toOffsetOutBounds$1} = core.BoundsHelper, {max: max} = Math;
2302
2317
 
2303
- const tempBounds = {};
2318
+ const tempBounds = {}, tempMatrix = new core.Matrix;
2304
2319
 
2305
2320
  const offsetOutBounds$1 = {};
2306
2321
 
2307
2322
  function shadow(ui, current, shape) {
2308
- let copyBounds, spreadScale;
2309
- const {__nowWorld: nowWorld, __layout: __layout} = ui;
2323
+ let copyBounds, transform;
2324
+ const {__nowWorld: nowWorld} = ui;
2310
2325
  const {shadow: shadow} = ui.__;
2311
- const {worldCanvas: worldCanvas, bounds: bounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
2326
+ const {worldCanvas: worldCanvas, bounds: bounds, renderBounds: renderBounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
2312
2327
  const other = current.getSameCanvas();
2313
2328
  const end = shadow.length - 1;
2314
- toOffsetOutBounds$1(bounds, offsetOutBounds$1);
2329
+ toOffsetOutBounds$1(bounds, offsetOutBounds$1, renderBounds);
2315
2330
  shadow.forEach((item, index) => {
2316
2331
  let otherScale = 1;
2317
2332
  if (item.scaleFixed) {
2318
2333
  const sx = Math.abs(nowWorld.scaleX);
2319
2334
  if (sx > 1) otherScale = 1 / sx;
2320
2335
  }
2321
- 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));
2322
- spreadScale = item.spread ? 1 + item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) * otherScale : 0;
2323
- drawWorldShadow(other, offsetOutBounds$1, spreadScale, shape);
2324
- copyBounds = bounds;
2336
+ 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));
2337
+ transform = draw.Effect.getShadowTransform(ui, other, shape, item, offsetOutBounds$1, otherScale);
2338
+ if (transform) other.setTransform(transform);
2339
+ drawWorldShadow(other, offsetOutBounds$1, shape);
2340
+ if (transform) other.resetTransform();
2341
+ copyBounds = renderBounds;
2325
2342
  if (item.box) {
2326
2343
  other.restore();
2327
2344
  other.save();
2328
2345
  if (worldCanvas) {
2329
- other.copyWorld(other, bounds, nowWorld, "copy");
2346
+ other.copyWorld(other, renderBounds, nowWorld, "copy");
2330
2347
  copyBounds = nowWorld;
2331
2348
  }
2332
2349
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, "destination-out") : other.copyWorld(shape.canvas, shapeBounds, bounds, "destination-out");
2333
2350
  }
2334
- if (draw.Effect.isTransformShadow(item)) draw.Effect.renderTransformShadow(ui, current, other, copyBounds, item); else core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
2351
+ core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
2335
2352
  if (end && index < end) other.clearWorld(copyBounds);
2336
2353
  });
2337
2354
  other.recycle(copyBounds);
2338
2355
  }
2339
2356
 
2340
- function getShadowSpread(_ui, shadow) {
2341
- let width = 0;
2342
- 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));
2343
- return width;
2357
+ function getShadowRenderSpread(_ui, shadow) {
2358
+ let top = 0, right = 0, bottom = 0, left = 0, x, y, spread, blur;
2359
+ shadow.forEach(item => {
2360
+ x = item.x || 0, y = item.y || 0, spread = item.spread || 0, blur = (item.blur || 0) * 1.5;
2361
+ top = max(top, spread + blur - y);
2362
+ right = max(right, spread + blur + x);
2363
+ bottom = max(bottom, spread + blur + y);
2364
+ left = max(left, spread + blur - x);
2365
+ });
2366
+ return top === right && right === bottom && bottom === left ? top : [ top, right, bottom, left ];
2344
2367
  }
2345
2368
 
2346
- function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
2347
- const {bounds: bounds, shapeBounds: shapeBounds} = shape;
2369
+ function getShadowTransform(ui, canvas, _shape, shadow, outBounds, otherScale, isInnerShaodw) {
2370
+ if (shadow.spread) {
2371
+ const spreadScale = 1 + shadow.spread * 2 / ui.__layout.strokeBounds.width * otherScale * (isInnerShaodw ? -1 : 1);
2372
+ tempMatrix.set().scaleOfOuter({
2373
+ x: (outBounds.x + outBounds.width / 2) * canvas.pixelRatio,
2374
+ y: (outBounds.y + outBounds.height / 2) * canvas.pixelRatio
2375
+ }, spreadScale);
2376
+ return tempMatrix;
2377
+ }
2378
+ return undefined;
2379
+ }
2380
+
2381
+ function drawWorldShadow(canvas, outBounds, shape) {
2382
+ const {shapeBounds: shapeBounds} = shape;
2383
+ let from, to;
2348
2384
  if (core.Platform.fullImageShadow) {
2349
2385
  copy(tempBounds, canvas.bounds);
2350
- tempBounds.x += outBounds.x - shapeBounds.x;
2351
- tempBounds.y += outBounds.y - shapeBounds.y;
2352
- if (spreadScale) {
2353
- const {fitMatrix: fitMatrix} = shape;
2354
- tempBounds.x -= (bounds.x + (fitMatrix ? fitMatrix.e : 0) + bounds.width / 2) * (spreadScale - 1);
2355
- tempBounds.y -= (bounds.y + (fitMatrix ? fitMatrix.f : 0) + bounds.height / 2) * (spreadScale - 1);
2356
- tempBounds.width *= spreadScale;
2357
- tempBounds.height *= spreadScale;
2358
- }
2359
- canvas.copyWorld(shape.canvas, canvas.bounds, tempBounds);
2386
+ move(tempBounds, outBounds.x - shapeBounds.x, outBounds.y - shapeBounds.y);
2387
+ from = canvas.bounds, to = tempBounds;
2360
2388
  } else {
2361
- if (spreadScale) {
2362
- copy(tempBounds, outBounds);
2363
- tempBounds.x -= outBounds.width / 2 * (spreadScale - 1);
2364
- tempBounds.y -= outBounds.height / 2 * (spreadScale - 1);
2365
- tempBounds.width *= spreadScale;
2366
- tempBounds.height *= spreadScale;
2367
- }
2368
- canvas.copyWorld(shape.canvas, shapeBounds, spreadScale ? tempBounds : outBounds);
2389
+ from = shapeBounds, to = outBounds;
2369
2390
  }
2391
+ canvas.copyWorld(shape.canvas, from, to);
2370
2392
  }
2371
2393
 
2372
2394
  const {toOffsetOutBounds: toOffsetOutBounds} = core.BoundsHelper;
@@ -2374,13 +2396,13 @@ const {toOffsetOutBounds: toOffsetOutBounds} = core.BoundsHelper;
2374
2396
  const offsetOutBounds = {};
2375
2397
 
2376
2398
  function innerShadow(ui, current, shape) {
2377
- let copyBounds, spreadScale;
2378
- const {__nowWorld: nowWorld, __layout: __layout} = ui;
2399
+ let copyBounds, transform;
2400
+ const {__nowWorld: nowWorld} = ui;
2379
2401
  const {innerShadow: innerShadow} = ui.__;
2380
- const {worldCanvas: worldCanvas, bounds: bounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
2402
+ const {worldCanvas: worldCanvas, bounds: bounds, renderBounds: renderBounds, shapeBounds: shapeBounds, scaleX: scaleX, scaleY: scaleY} = shape;
2381
2403
  const other = current.getSameCanvas();
2382
2404
  const end = innerShadow.length - 1;
2383
- toOffsetOutBounds(bounds, offsetOutBounds);
2405
+ toOffsetOutBounds(bounds, offsetOutBounds, renderBounds);
2384
2406
  innerShadow.forEach((item, index) => {
2385
2407
  let otherScale = 1;
2386
2408
  if (item.scaleFixed) {
@@ -2388,17 +2410,18 @@ function innerShadow(ui, current, shape) {
2388
2410
  if (sx > 1) otherScale = 1 / sx;
2389
2411
  }
2390
2412
  other.save();
2391
- other.setWorldShadow(offsetOutBounds.offsetX + item.x * scaleX * otherScale, offsetOutBounds.offsetY + item.y * scaleY * otherScale, item.blur * scaleX * otherScale);
2392
- spreadScale = item.spread ? 1 - item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) * otherScale : 0;
2393
- drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
2413
+ other.setWorldShadow(offsetOutBounds.offsetX + (item.x || 0) * scaleX * otherScale, offsetOutBounds.offsetY + (item.y || 0) * scaleY * otherScale, (item.blur || 0) * scaleX * otherScale);
2414
+ transform = draw.Effect.getShadowTransform(ui, other, shape, item, offsetOutBounds, otherScale, true);
2415
+ if (transform) other.setTransform(transform);
2416
+ drawWorldShadow(other, offsetOutBounds, shape);
2394
2417
  other.restore();
2395
2418
  if (worldCanvas) {
2396
- other.copyWorld(other, bounds, nowWorld, "copy");
2419
+ other.copyWorld(other, renderBounds, nowWorld, "copy");
2397
2420
  other.copyWorld(worldCanvas, nowWorld, nowWorld, "source-out");
2398
2421
  copyBounds = nowWorld;
2399
2422
  } else {
2400
2423
  other.copyWorld(shape.canvas, shapeBounds, bounds, "source-out");
2401
- copyBounds = bounds;
2424
+ copyBounds = renderBounds;
2402
2425
  }
2403
2426
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), "source-in");
2404
2427
  core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
@@ -2407,6 +2430,8 @@ function innerShadow(ui, current, shape) {
2407
2430
  other.recycle(copyBounds);
2408
2431
  }
2409
2432
 
2433
+ const getInnerShadowSpread = getShadowRenderSpread;
2434
+
2410
2435
  function blur(ui, current, origin) {
2411
2436
  const {blur: blur} = ui.__;
2412
2437
  origin.setWorldBlur(blur * ui.__nowWorld.a);
@@ -2421,10 +2446,12 @@ const EffectModule = {
2421
2446
  innerShadow: innerShadow,
2422
2447
  blur: blur,
2423
2448
  backgroundBlur: backgroundBlur,
2424
- getShadowSpread: getShadowSpread,
2449
+ getShadowRenderSpread: getShadowRenderSpread,
2450
+ getShadowTransform: getShadowTransform,
2425
2451
  isTransformShadow(_shadow) {
2426
2452
  return undefined;
2427
- }
2453
+ },
2454
+ getInnerShadowSpread: getInnerShadowSpread
2428
2455
  };
2429
2456
 
2430
2457
  const {excludeRenderBounds: excludeRenderBounds} = core.LeafBoundsHelper;
@@ -2441,6 +2468,7 @@ draw.Group.prototype.__renderMask = function(canvas, options) {
2441
2468
  maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity, undefined, true);
2442
2469
  maskCanvas = contentCanvas = null;
2443
2470
  }
2471
+ if (mask === "clipping" || mask === "clipping-path") excludeRenderBounds(child, options) || child.__render(canvas, options);
2444
2472
  maskOpacity = child.__.opacity;
2445
2473
  usedGrayscaleAlpha = false;
2446
2474
  if (mask === "path" || mask === "clipping-path") {
@@ -2458,7 +2486,6 @@ draw.Group.prototype.__renderMask = function(canvas, options) {
2458
2486
  if (!contentCanvas) contentCanvas = getCanvas(canvas);
2459
2487
  child.__render(maskCanvas, options);
2460
2488
  }
2461
- if (mask === "clipping" || mask === "clipping-path") excludeRenderBounds(child, options) || child.__render(canvas, options);
2462
2489
  continue;
2463
2490
  }
2464
2491
  const childBlendMode = maskOpacity === 1 && child.__.__blendMode;
@@ -3020,6 +3047,7 @@ const TextConvertModule = {
3020
3047
  };
3021
3048
 
3022
3049
  function string(color, opacity) {
3050
+ if (!color) return "#000";
3023
3051
  const doOpacity = core.isNumber(opacity) && opacity < 1;
3024
3052
  if (core.isString(color)) {
3025
3053
  if (doOpacity && draw.ColorConvert.object) color = draw.ColorConvert.object(color); else return color;