leafer-ui 1.7.0 → 1.8.0

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/README.md CHANGED
@@ -113,7 +113,10 @@ LeaferJS 致力于实现一套简洁、开放、现代化的 UI 绘图语言标
113
113
 
114
114
  <p><h3 align="center">金牌赞助商</h3></p>
115
115
  <p style="display: flex;flex-wrap: wrap;justify-content: center;gap: 15px;">
116
- <a target="_blank" href="https://github.com/dromara/yft-design">
116
+ <a target="_blank" href="https://xpai.design">
117
+ <img width="180" title="迅排设计" src="https://www.leaferjs.com/image/sponsor/gold/xp.jpg" loading="lazy" />
118
+ </a>
119
+ <a target="_blank" href="https://github.com/dromara/yft-design">
117
120
  <img width="180" title="yft-design" src="https://www.leaferjs.com/image/sponsor/gold/yft.jpg" loading="lazy" />
118
121
  </a>
119
122
  <a target="_blank" href="https://www.finclip.com/landing/miniappgame?from=leafer">
@@ -143,12 +146,15 @@ LeaferJS 致力于实现一套简洁、开放、现代化的 UI 绘图语言标
143
146
  </p>
144
147
  <p><h3 align="center">银牌赞助</h3></p>
145
148
  <p style="display: flex;flex-wrap: wrap;justify-content: center;gap: 5px;">
146
- <a target="_blank" href="https://www.u-tools.cn/plugins/detail/%E6%88%AA%E5%9B%BE%E5%B7%A5%E5%85%B7%20Plus/index.html">
147
- <img width="40" title="截图工具 Plus" src="https://www.leaferjs.com/image/sponsor/user/135.png" loading="lazy" />
149
+ <a target="_blank" href="">
150
+ <img width="40" title="goosen" src="https://www.leaferjs.com/image/sponsor/user/122.jpeg" loading="lazy" />
148
151
  </a>
149
152
  <a target="_blank" href="">
150
153
  <img width="40" title="dev_chen" src="https://www.leaferjs.com/image/sponsor/user/137.jpg" loading="lazy" />
151
154
  </a>
155
+ <a target="_blank" href="https://www.u-tools.cn/plugins/detail/%E6%88%AA%E5%9B%BE%E5%B7%A5%E5%85%B7%20Plus/index.html">
156
+ <img width="40" title="截图工具 Plus" src="https://www.leaferjs.com/image/sponsor/user/135.png" loading="lazy" />
157
+ </a>
152
158
  <a target="_blank" href="https://frameelf.com/">
153
159
  <img width="40" title="边框水印精灵" src="https://www.leaferjs.com/image/sponsor/user/134.jpg" loading="lazy" />
154
160
  </a>
@@ -296,7 +302,7 @@ LeaferJS 致力于实现一套简洁、开放、现代化的 UI 绘图语言标
296
302
  </p>
297
303
  <p><h3 align="center">铜牌赞助</h3></p>
298
304
  <p style="display: flex;flex-wrap: wrap;justify-content: center;gap: 15px;">
299
- Lauginwing &nbsp;&nbsp;江万江 &nbsp;&nbsp;在路上 &nbsp;&nbsp;张余🌈 &nbsp;&nbsp;Jerry &nbsp;&nbsp;李狗嗨。💢 &nbsp;&nbsp;李维亮 &nbsp;&nbsp;朝夕 &nbsp;&nbsp;SaltedFish &nbsp;&nbsp;zhk &nbsp;&nbsp;格子 &nbsp;&nbsp;等等 &nbsp;&nbsp;goosen &nbsp;&nbsp;建伟F4nniu &nbsp;&nbsp;梁福斌 &nbsp;&nbsp;江万江 &nbsp;&nbsp;杨超 &nbsp;&nbsp;ToB Dev &nbsp;&nbsp;前端之虎陈随易 &nbsp;&nbsp;A☀️云☀️A &nbsp;&nbsp;ʚ LMT ɞ &nbsp;&nbsp;爱发电用户_c9c82 &nbsp;&nbsp;轻简历 &nbsp;&nbsp;爱发电用户_0fac0 &nbsp;&nbsp;wangyesheji.cn &nbsp;&nbsp;风间 &nbsp;&nbsp;爱发电用户_Tqsm &nbsp;&nbsp;爱发电用户_6KpE &nbsp;&nbsp;dongdong &nbsp;&nbsp;zwm &nbsp;&nbsp;爱发电用户_3725c &nbsp;&nbsp;Noth1ng &nbsp;&nbsp;纳西妲の√ &nbsp;&nbsp;爱发电用户_Ahb9 &nbsp;&nbsp;爱发电用户_7617d &nbsp;&nbsp;冷漠 &nbsp;&nbsp;爱发电用户_9RXB &nbsp;&nbsp;今日值得读 &nbsp;&nbsp;爱发电用户_49sT &nbsp;&nbsp;爱发电用户_NFCS &nbsp;&nbsp;爱发电用户_43ad8 &nbsp;&nbsp;爱发电用户_30455 &nbsp;&nbsp;xiaozhang &nbsp;&nbsp;砖吐筷筷 &nbsp;&nbsp;爱发电用户_b47b3 &nbsp;&nbsp;longbow1998 &nbsp;&nbsp;爱发电用户_5d755 &nbsp;&nbsp;爱发电用户_b76b8 &nbsp;&nbsp;爱发电用户_e70c2 &nbsp;&nbsp;爱发电用户_039dc &nbsp;&nbsp;花祁 &nbsp;&nbsp;爱发电用户_99f39 &nbsp;&nbsp;坤坤 &nbsp;&nbsp;爱发电用户_X6hp &nbsp;&nbsp;爱发电用户_s5u9 &nbsp;&nbsp;曹吉美爸爸 &nbsp;&nbsp;啸沧海 &nbsp;&nbsp;Ronny &nbsp;&nbsp;Biu &nbsp;&nbsp;王志强 &nbsp;&nbsp;PD.新城คิดถึง &nbsp;&nbsp;糖颂缘冥倾 &nbsp;&nbsp;ALBERT. &nbsp;&nbsp;爱发电用户_UXEV &nbsp;&nbsp;SaltedFish &nbsp;&nbsp;爱发电用户_76f9d &nbsp;&nbsp;Leafer &nbsp;&nbsp;爱发电用户_Pbm7 &nbsp;&nbsp;</p>
305
+ 黑色摩天仑 &nbsp;&nbsp;Charm &nbsp;&nbsp;Lauginwing &nbsp;&nbsp;在路上 &nbsp;&nbsp;张余🌈 &nbsp;&nbsp;Jerry &nbsp;&nbsp;李狗嗨。💢 &nbsp;&nbsp;李维亮 &nbsp;&nbsp;朝夕 &nbsp;&nbsp;SaltedFish &nbsp;&nbsp;zhk &nbsp;&nbsp;格子 &nbsp;&nbsp;等等 &nbsp;&nbsp;goosen &nbsp;&nbsp;建伟F4nniu &nbsp;&nbsp;梁福斌 &nbsp;&nbsp;江万江 &nbsp;&nbsp;杨超 &nbsp;&nbsp;ToB Dev &nbsp;&nbsp;前端之虎陈随易 &nbsp;&nbsp;A☀️云☀️A &nbsp;&nbsp;ʚ LMT ɞ &nbsp;&nbsp;爱发电用户_c9c82 &nbsp;&nbsp;轻简历 &nbsp;&nbsp;爱发电用户_0fac0 &nbsp;&nbsp;wangyesheji.cn &nbsp;&nbsp;风间 &nbsp;&nbsp;爱发电用户_Tqsm &nbsp;&nbsp;爱发电用户_6KpE &nbsp;&nbsp;dongdong &nbsp;&nbsp;zwm &nbsp;&nbsp;爱发电用户_3725c &nbsp;&nbsp;Noth1ng &nbsp;&nbsp;纳西妲の√ &nbsp;&nbsp;爱发电用户_Ahb9 &nbsp;&nbsp;爱发电用户_7617d &nbsp;&nbsp;冷漠 &nbsp;&nbsp;爱发电用户_9RXB &nbsp;&nbsp;今日值得读 &nbsp;&nbsp;爱发电用户_49sT &nbsp;&nbsp;爱发电用户_NFCS &nbsp;&nbsp;爱发电用户_43ad8 &nbsp;&nbsp;爱发电用户_30455 &nbsp;&nbsp;xiaozhang &nbsp;&nbsp;砖吐筷筷 &nbsp;&nbsp;爱发电用户_b47b3 &nbsp;&nbsp;longbow1998 &nbsp;&nbsp;爱发电用户_5d755 &nbsp;&nbsp;爱发电用户_b76b8 &nbsp;&nbsp;爱发电用户_e70c2 &nbsp;&nbsp;爱发电用户_039dc &nbsp;&nbsp;花祁 &nbsp;&nbsp;爱发电用户_99f39 &nbsp;&nbsp;坤坤 &nbsp;&nbsp;爱发电用户_X6hp &nbsp;&nbsp;爱发电用户_s5u9 &nbsp;&nbsp;曹吉美爸爸 &nbsp;&nbsp;啸沧海 &nbsp;&nbsp;Ronny &nbsp;&nbsp;Biu &nbsp;&nbsp;王志强 &nbsp;&nbsp;PD.新城คิดถึง &nbsp;&nbsp;糖颂缘冥倾 &nbsp;&nbsp;ALBERT. &nbsp;&nbsp;爱发电用户_UXEV &nbsp;&nbsp;SaltedFish &nbsp;&nbsp;爱发电用户_76f9d &nbsp;&nbsp;Leafer &nbsp;&nbsp;爱发电用户_Pbm7 &nbsp;&nbsp;</p>
300
306
 
301
307
  ## License
302
308
 
package/dist/web.cjs CHANGED
@@ -1348,9 +1348,14 @@ function fills(fills, ui, canvas) {
1348
1348
  }
1349
1349
  }
1350
1350
  canvas.fillStyle = item.style;
1351
- if (item.transform) {
1351
+ if (item.transform || item.scaleFixed) {
1352
1352
  canvas.save();
1353
- canvas.transform(item.transform);
1353
+ if (item.transform)
1354
+ canvas.transform(item.transform);
1355
+ if (item.scaleFixed) {
1356
+ const { scaleX, scaleY } = ui.getRenderScaleData(true);
1357
+ canvas.scale(1 / scaleX, 1 / scaleY);
1358
+ }
1354
1359
  if (item.blendMode)
1355
1360
  canvas.blendMode = item.blendMode;
1356
1361
  fillPathOrText(ui, canvas);
@@ -1386,8 +1391,13 @@ function strokeText(stroke, ui, canvas) {
1386
1391
  }
1387
1392
  function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1388
1393
  const data = ui.__;
1389
- canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
1390
- data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1394
+ if (typeof stroke === 'object') {
1395
+ drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas);
1396
+ }
1397
+ else {
1398
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1399
+ drawTextStroke(ui, canvas);
1400
+ }
1391
1401
  }
1392
1402
  function drawAlign(stroke, align, ui, canvas) {
1393
1403
  const out = canvas.getSameCanvas(true, true);
@@ -1396,15 +1406,9 @@ function drawAlign(stroke, align, ui, canvas) {
1396
1406
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1397
1407
  fillText(ui, out);
1398
1408
  out.blendMode = 'normal';
1399
- copyWorld(canvas, out, ui);
1409
+ core.LeafHelper.copyCanvasByWorld(ui, canvas, out);
1400
1410
  out.recycle(ui.__nowWorld);
1401
1411
  }
1402
- function copyWorld(canvas, out, ui) {
1403
- if (ui.__worldFlipped || core.Platform.fullImageShadow)
1404
- canvas.copyWorldByReset(out, ui.__nowWorld);
1405
- else
1406
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1407
- }
1408
1412
  function drawTextStroke(ui, canvas) {
1409
1413
  let row, data = ui.__.__textDrawData;
1410
1414
  const { rows, decorationY } = data;
@@ -1420,14 +1424,21 @@ function drawTextStroke(ui, canvas) {
1420
1424
  rows.forEach(row => decorationY.forEach(value => canvas.strokeRect(row.x, row.y + value, row.width, decorationHeight)));
1421
1425
  }
1422
1426
  }
1423
- function drawStrokesStyle(strokes, isText, ui, canvas) {
1427
+ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
1424
1428
  let item;
1429
+ const data = ui.__, { __hasMultiStrokeStyle } = data;
1430
+ __hasMultiStrokeStyle || canvas.setStroke(undefined, data.__strokeWidth * strokeWidthScale, data);
1425
1431
  for (let i = 0, len = strokes.length; i < len; i++) {
1426
1432
  item = strokes[i];
1427
1433
  if (item.image && draw.PaintImage.checkImage(ui, canvas, item, false))
1428
1434
  continue;
1429
1435
  if (item.style) {
1430
- canvas.strokeStyle = item.style;
1436
+ if (__hasMultiStrokeStyle) {
1437
+ const { strokeStyle } = item;
1438
+ strokeStyle ? canvas.setStroke(item.style, data.__getRealStrokeWidth(strokeStyle) * strokeWidthScale, data, strokeStyle) : canvas.setStroke(item.style, data.__strokeWidth * strokeWidthScale, data);
1439
+ }
1440
+ else
1441
+ canvas.strokeStyle = item.style;
1431
1442
  if (item.blendMode) {
1432
1443
  canvas.saveBlendMode(item.blendMode);
1433
1444
  isText ? drawTextStroke(ui, canvas) : canvas.stroke();
@@ -1466,8 +1477,13 @@ function strokes(strokes, ui, canvas) {
1466
1477
  }
1467
1478
  function drawCenter(stroke, strokeWidthScale, ui, canvas) {
1468
1479
  const data = ui.__;
1469
- canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
1470
- data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
1480
+ if (typeof stroke === 'object') {
1481
+ drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas);
1482
+ }
1483
+ else {
1484
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1485
+ canvas.stroke();
1486
+ }
1471
1487
  if (data.__useArrow)
1472
1488
  draw.Paint.strokeArrow(stroke, ui, canvas);
1473
1489
  }
@@ -1489,7 +1505,7 @@ function drawOutside(stroke, ui, canvas) {
1489
1505
  drawCenter(stroke, 2, ui, out);
1490
1506
  out.clipUI(data);
1491
1507
  out.clearWorld(renderBounds);
1492
- copyWorld(canvas, out, ui);
1508
+ core.LeafHelper.copyCanvasByWorld(ui, canvas, out);
1493
1509
  out.recycle(ui.__nowWorld);
1494
1510
  }
1495
1511
  }
@@ -1544,8 +1560,16 @@ function compute(attrName, ui) {
1544
1560
  if (!(paints instanceof Array))
1545
1561
  paints = [paints];
1546
1562
  recycleMap = draw.PaintImage.recycleImage(attrName, data);
1563
+ let maxChildStrokeWidth;
1547
1564
  for (let i = 0, len = paints.length, item; i < len; i++) {
1548
- (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
1565
+ if (item = getLeafPaint(attrName, paints[i], ui)) {
1566
+ leafPaints.push(item);
1567
+ if (item.strokeStyle) {
1568
+ maxChildStrokeWidth || (maxChildStrokeWidth = 1);
1569
+ if (item.strokeStyle.strokeWidth)
1570
+ maxChildStrokeWidth = Math.max(maxChildStrokeWidth, item.strokeStyle.strokeWidth);
1571
+ }
1572
+ }
1549
1573
  }
1550
1574
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1551
1575
  if (leafPaints.length) {
@@ -1562,6 +1586,7 @@ function compute(attrName, ui) {
1562
1586
  else {
1563
1587
  stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1564
1588
  stintSet(data, '__isTransparentStroke', isTransparent);
1589
+ stintSet(data, '__hasMultiStrokeStyle', maxChildStrokeWidth);
1565
1590
  }
1566
1591
  }
1567
1592
  function getLeafPaint(attrName, paint, ui) {
@@ -1593,6 +1618,11 @@ function getLeafPaint(attrName, paint, ui) {
1593
1618
  if (data) {
1594
1619
  if (typeof data.style === 'string' && hasTransparent$1(data.style))
1595
1620
  data.isTransparent = true;
1621
+ if (paint.style) {
1622
+ if (paint.style.strokeWidth === 0)
1623
+ return undefined;
1624
+ data.strokeStyle = paint.style;
1625
+ }
1596
1626
  if (paint.blendMode)
1597
1627
  data.blendMode = paint.blendMode;
1598
1628
  }
@@ -1612,8 +1642,8 @@ const PaintModule = {
1612
1642
  shape
1613
1643
  };
1614
1644
 
1615
- let origin = {};
1616
- const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate, skew: skewHelper } = core.MatrixHelper;
1645
+ let origin = {}, tempMatrix = core.getMatrixData();
1646
+ const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent, scale: scaleHelper, rotate, skew: skewHelper } = core.MatrixHelper;
1617
1647
  function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1618
1648
  const transform = get$3();
1619
1649
  translate$1(transform, box.x + x, box.y + y);
@@ -1622,7 +1652,7 @@ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1622
1652
  rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1623
1653
  data.transform = transform;
1624
1654
  }
1625
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew) {
1655
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipSize) {
1626
1656
  const transform = get$3();
1627
1657
  if (rotation)
1628
1658
  rotate(transform, rotation);
@@ -1631,6 +1661,10 @@ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew) {
1631
1661
  if (scaleX)
1632
1662
  scaleHelper(transform, scaleX, scaleY);
1633
1663
  translate$1(transform, box.x + x, box.y + y);
1664
+ if (clipSize) {
1665
+ tempMatrix.a = box.width / clipSize.width, tempMatrix.d = box.height / clipSize.height;
1666
+ multiplyParent(transform, tempMatrix);
1667
+ }
1634
1668
  data.transform = transform;
1635
1669
  }
1636
1670
  function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
@@ -1667,13 +1701,15 @@ const tempBox = new core.Bounds();
1667
1701
  const tempScaleData = {};
1668
1702
  const tempImage = {};
1669
1703
  function createData(leafPaint, image, paint, box) {
1670
- const { changeful, sync, editing } = paint;
1704
+ const { changeful, sync, editing, scaleFixed } = paint;
1671
1705
  if (changeful)
1672
1706
  leafPaint.changeful = changeful;
1673
1707
  if (sync)
1674
1708
  leafPaint.sync = sync;
1675
1709
  if (editing)
1676
1710
  leafPaint.editing = editing;
1711
+ if (scaleFixed)
1712
+ leafPaint.scaleFixed = scaleFixed;
1677
1713
  leafPaint.data = getPatternData(paint, box, image);
1678
1714
  }
1679
1715
  function getPatternData(paint, box, image) {
@@ -1682,7 +1718,7 @@ function getPatternData(paint, box, image) {
1682
1718
  if (paint.mode === 'strench')
1683
1719
  paint.mode = 'stretch';
1684
1720
  let { width, height } = image;
1685
- const { opacity, mode, align, offset, scale, size, rotation, skew, repeat, filters } = paint;
1721
+ const { opacity, mode, align, offset, scale, size, rotation, skew, clipSize, repeat, filters } = paint;
1686
1722
  const sameBox = box.width === width && box.height === height;
1687
1723
  const data = { mode };
1688
1724
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
@@ -1716,8 +1752,8 @@ function getPatternData(paint, box, image) {
1716
1752
  break;
1717
1753
  case 'normal':
1718
1754
  case 'clip':
1719
- if (tempImage.x || tempImage.y || scaleX || rotation || skew)
1720
- clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew);
1755
+ if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew)
1756
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, paint.clipSize);
1721
1757
  break;
1722
1758
  case 'repeat':
1723
1759
  if (!sameBox || scaleX || rotation)
@@ -1854,18 +1890,16 @@ function ignoreRender(ui, value) {
1854
1890
  }
1855
1891
 
1856
1892
  const { get: get$1, scale, copy: copy$1 } = core.MatrixHelper;
1857
- const { ceil, abs: abs$1 } = Math;
1893
+ const { ceil, abs } = Math;
1858
1894
  function createPattern(ui, paint, pixelRatio) {
1859
- let { scaleX, scaleY } = core.ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1895
+ let { scaleX, scaleY } = ui.getRenderScaleData(true, paint.scaleFixed);
1860
1896
  const id = scaleX + '-' + scaleY + '-' + pixelRatio;
1861
1897
  if (paint.patternId !== id && !ui.destroyed) {
1862
- scaleX = abs$1(scaleX);
1863
- scaleY = abs$1(scaleY);
1864
1898
  const { image, data } = paint;
1865
1899
  let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, transform, repeat } = data;
1866
1900
  if (sx) {
1867
- sx = abs$1(sx);
1868
- sy = abs$1(sy);
1901
+ sx = abs(sx);
1902
+ sy = abs(sy);
1869
1903
  imageMatrix = get$1();
1870
1904
  copy$1(imageMatrix, transform);
1871
1905
  scale(imageMatrix, 1 / sx, 1 / sy);
@@ -1950,9 +1984,8 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
1950
1984
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1951
1985
  };
1952
1986
 
1953
- const { abs } = Math;
1954
1987
  function checkImage(ui, canvas, paint, allowDraw) {
1955
- const { scaleX, scaleY } = core.ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1988
+ const { scaleX, scaleY } = ui.getRenderScaleData(true, paint.scaleFixed);
1956
1989
  const { pixelRatio } = canvas, { data } = paint;
1957
1990
  if (!data || (paint.patternId === scaleX + '-' + scaleY + '-' + pixelRatio && !draw.Export.running)) {
1958
1991
  return false;
@@ -1965,8 +1998,8 @@ function checkImage(ui, canvas, paint, allowDraw) {
1965
1998
  else {
1966
1999
  if (!(paint.changeful || core.ResizeEvent.isResizing(ui) || draw.Export.running)) {
1967
2000
  let { width, height } = data;
1968
- width *= abs(scaleX) * pixelRatio;
1969
- height *= abs(scaleY) * pixelRatio;
2001
+ width *= scaleX * pixelRatio;
2002
+ height *= scaleY * pixelRatio;
1970
2003
  if (data.scaleX) {
1971
2004
  width *= data.scaleX;
1972
2005
  height *= data.scaleY;
@@ -1976,6 +2009,10 @@ function checkImage(ui, canvas, paint, allowDraw) {
1976
2009
  }
1977
2010
  }
1978
2011
  if (allowDraw) {
2012
+ if (ui.__.__isFastShadow) {
2013
+ canvas.fillStyle = paint.style || '#000';
2014
+ canvas.fill();
2015
+ }
1979
2016
  drawImage(ui, canvas, paint, data);
1980
2017
  return true;
1981
2018
  }
@@ -2164,10 +2201,7 @@ function shadow(ui, current, shape) {
2164
2201
  }
2165
2202
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
2166
2203
  }
2167
- if (ui.__worldFlipped)
2168
- current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
2169
- else
2170
- current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2204
+ core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
2171
2205
  if (end && index < end)
2172
2206
  other.clearWorld(copyBounds, true);
2173
2207
  });
@@ -2226,10 +2260,7 @@ function innerShadow(ui, current, shape) {
2226
2260
  copyBounds = bounds;
2227
2261
  }
2228
2262
  other.fillWorld(copyBounds, draw.ColorConvert.string(item.color), 'source-in');
2229
- if (ui.__worldFlipped)
2230
- current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
2231
- else
2232
- current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2263
+ core.LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
2233
2264
  if (end && index < end)
2234
2265
  other.clearWorld(copyBounds, true);
2235
2266
  });
@@ -2285,12 +2316,11 @@ draw.Group.prototype.__renderMask = function (canvas, options) {
2285
2316
  contentCanvas = getCanvas(canvas);
2286
2317
  child.__render(maskCanvas, options);
2287
2318
  }
2288
- if (!(mask === 'clipping' || mask === 'clipping-path'))
2289
- continue;
2290
- }
2291
- if (excludeRenderBounds(child, options))
2319
+ if (mask === 'clipping' || mask === 'clipping-path')
2320
+ excludeRenderBounds(child, options) || child.__render(canvas, options);
2292
2321
  continue;
2293
- child.__render(contentCanvas || canvas, options);
2322
+ }
2323
+ excludeRenderBounds(child, options) || child.__render(contentCanvas || canvas, options);
2294
2324
  }
2295
2325
  maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
2296
2326
  };
package/dist/web.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Debug, LeaferCanvasBase, Platform, DataHelper, canvasSizeAttrs, ResizeEvent, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, LeafLevelList, LayoutEvent, Run, ImageManager, BoundsHelper, Plugin, MathHelper, MatrixHelper, AlignHelper, PointHelper, ImageEvent, AroundHelper, Direction4 } from '@leafer/core';
1
+ import { Debug, LeaferCanvasBase, Platform, DataHelper, canvasSizeAttrs, ResizeEvent, canvasPatch, FileHelper, Creator, LeaferImage, defineKey, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, LeafBoundsHelper, Bounds, LeafLevelList, LayoutEvent, Run, ImageManager, BoundsHelper, Plugin, MathHelper, getMatrixData, MatrixHelper, AlignHelper, PointHelper, ImageEvent, AroundHelper, Direction4 } from '@leafer/core';
2
2
  export * from '@leafer/core';
3
3
  export { LeaferImage } from '@leafer/core';
4
4
  import { InteractionHelper, InteractionBase, Cursor, HitCanvasManager } from '@leafer-ui/core';
@@ -1349,9 +1349,14 @@ function fills(fills, ui, canvas) {
1349
1349
  }
1350
1350
  }
1351
1351
  canvas.fillStyle = item.style;
1352
- if (item.transform) {
1352
+ if (item.transform || item.scaleFixed) {
1353
1353
  canvas.save();
1354
- canvas.transform(item.transform);
1354
+ if (item.transform)
1355
+ canvas.transform(item.transform);
1356
+ if (item.scaleFixed) {
1357
+ const { scaleX, scaleY } = ui.getRenderScaleData(true);
1358
+ canvas.scale(1 / scaleX, 1 / scaleY);
1359
+ }
1355
1360
  if (item.blendMode)
1356
1361
  canvas.blendMode = item.blendMode;
1357
1362
  fillPathOrText(ui, canvas);
@@ -1387,8 +1392,13 @@ function strokeText(stroke, ui, canvas) {
1387
1392
  }
1388
1393
  function drawCenter$1(stroke, strokeWidthScale, ui, canvas) {
1389
1394
  const data = ui.__;
1390
- canvas.setStroke(!data.__isStrokes && stroke, data.strokeWidth * strokeWidthScale, data);
1391
- data.__isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1395
+ if (typeof stroke === 'object') {
1396
+ drawStrokesStyle(stroke, strokeWidthScale, true, ui, canvas);
1397
+ }
1398
+ else {
1399
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1400
+ drawTextStroke(ui, canvas);
1401
+ }
1392
1402
  }
1393
1403
  function drawAlign(stroke, align, ui, canvas) {
1394
1404
  const out = canvas.getSameCanvas(true, true);
@@ -1397,15 +1407,9 @@ function drawAlign(stroke, align, ui, canvas) {
1397
1407
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1398
1408
  fillText(ui, out);
1399
1409
  out.blendMode = 'normal';
1400
- copyWorld(canvas, out, ui);
1410
+ LeafHelper.copyCanvasByWorld(ui, canvas, out);
1401
1411
  out.recycle(ui.__nowWorld);
1402
1412
  }
1403
- function copyWorld(canvas, out, ui) {
1404
- if (ui.__worldFlipped || Platform.fullImageShadow)
1405
- canvas.copyWorldByReset(out, ui.__nowWorld);
1406
- else
1407
- canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1408
- }
1409
1413
  function drawTextStroke(ui, canvas) {
1410
1414
  let row, data = ui.__.__textDrawData;
1411
1415
  const { rows, decorationY } = data;
@@ -1421,14 +1425,21 @@ function drawTextStroke(ui, canvas) {
1421
1425
  rows.forEach(row => decorationY.forEach(value => canvas.strokeRect(row.x, row.y + value, row.width, decorationHeight)));
1422
1426
  }
1423
1427
  }
1424
- function drawStrokesStyle(strokes, isText, ui, canvas) {
1428
+ function drawStrokesStyle(strokes, strokeWidthScale, isText, ui, canvas) {
1425
1429
  let item;
1430
+ const data = ui.__, { __hasMultiStrokeStyle } = data;
1431
+ __hasMultiStrokeStyle || canvas.setStroke(undefined, data.__strokeWidth * strokeWidthScale, data);
1426
1432
  for (let i = 0, len = strokes.length; i < len; i++) {
1427
1433
  item = strokes[i];
1428
1434
  if (item.image && PaintImage.checkImage(ui, canvas, item, false))
1429
1435
  continue;
1430
1436
  if (item.style) {
1431
- canvas.strokeStyle = item.style;
1437
+ if (__hasMultiStrokeStyle) {
1438
+ const { strokeStyle } = item;
1439
+ strokeStyle ? canvas.setStroke(item.style, data.__getRealStrokeWidth(strokeStyle) * strokeWidthScale, data, strokeStyle) : canvas.setStroke(item.style, data.__strokeWidth * strokeWidthScale, data);
1440
+ }
1441
+ else
1442
+ canvas.strokeStyle = item.style;
1432
1443
  if (item.blendMode) {
1433
1444
  canvas.saveBlendMode(item.blendMode);
1434
1445
  isText ? drawTextStroke(ui, canvas) : canvas.stroke();
@@ -1467,8 +1478,13 @@ function strokes(strokes, ui, canvas) {
1467
1478
  }
1468
1479
  function drawCenter(stroke, strokeWidthScale, ui, canvas) {
1469
1480
  const data = ui.__;
1470
- canvas.setStroke(!data.__isStrokes && stroke, data.__strokeWidth * strokeWidthScale, data);
1471
- data.__isStrokes ? drawStrokesStyle(stroke, false, ui, canvas) : canvas.stroke();
1481
+ if (typeof stroke === 'object') {
1482
+ drawStrokesStyle(stroke, strokeWidthScale, false, ui, canvas);
1483
+ }
1484
+ else {
1485
+ canvas.setStroke(stroke, data.__strokeWidth * strokeWidthScale, data);
1486
+ canvas.stroke();
1487
+ }
1472
1488
  if (data.__useArrow)
1473
1489
  Paint.strokeArrow(stroke, ui, canvas);
1474
1490
  }
@@ -1490,7 +1506,7 @@ function drawOutside(stroke, ui, canvas) {
1490
1506
  drawCenter(stroke, 2, ui, out);
1491
1507
  out.clipUI(data);
1492
1508
  out.clearWorld(renderBounds);
1493
- copyWorld(canvas, out, ui);
1509
+ LeafHelper.copyCanvasByWorld(ui, canvas, out);
1494
1510
  out.recycle(ui.__nowWorld);
1495
1511
  }
1496
1512
  }
@@ -1545,8 +1561,16 @@ function compute(attrName, ui) {
1545
1561
  if (!(paints instanceof Array))
1546
1562
  paints = [paints];
1547
1563
  recycleMap = PaintImage.recycleImage(attrName, data);
1564
+ let maxChildStrokeWidth;
1548
1565
  for (let i = 0, len = paints.length, item; i < len; i++) {
1549
- (item = getLeafPaint(attrName, paints[i], ui)) && leafPaints.push(item);
1566
+ if (item = getLeafPaint(attrName, paints[i], ui)) {
1567
+ leafPaints.push(item);
1568
+ if (item.strokeStyle) {
1569
+ maxChildStrokeWidth || (maxChildStrokeWidth = 1);
1570
+ if (item.strokeStyle.strokeWidth)
1571
+ maxChildStrokeWidth = Math.max(maxChildStrokeWidth, item.strokeStyle.strokeWidth);
1572
+ }
1573
+ }
1550
1574
  }
1551
1575
  data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1552
1576
  if (leafPaints.length) {
@@ -1563,6 +1587,7 @@ function compute(attrName, ui) {
1563
1587
  else {
1564
1588
  stintSet(data, '__isAlphaPixelStroke', isAlphaPixel);
1565
1589
  stintSet(data, '__isTransparentStroke', isTransparent);
1590
+ stintSet(data, '__hasMultiStrokeStyle', maxChildStrokeWidth);
1566
1591
  }
1567
1592
  }
1568
1593
  function getLeafPaint(attrName, paint, ui) {
@@ -1594,6 +1619,11 @@ function getLeafPaint(attrName, paint, ui) {
1594
1619
  if (data) {
1595
1620
  if (typeof data.style === 'string' && hasTransparent$1(data.style))
1596
1621
  data.isTransparent = true;
1622
+ if (paint.style) {
1623
+ if (paint.style.strokeWidth === 0)
1624
+ return undefined;
1625
+ data.strokeStyle = paint.style;
1626
+ }
1597
1627
  if (paint.blendMode)
1598
1628
  data.blendMode = paint.blendMode;
1599
1629
  }
@@ -1613,8 +1643,8 @@ const PaintModule = {
1613
1643
  shape
1614
1644
  };
1615
1645
 
1616
- let origin = {};
1617
- const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate, skew: skewHelper } = MatrixHelper;
1646
+ let origin = {}, tempMatrix = getMatrixData();
1647
+ const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, multiplyParent, scale: scaleHelper, rotate, skew: skewHelper } = MatrixHelper;
1618
1648
  function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1619
1649
  const transform = get$3();
1620
1650
  translate$1(transform, box.x + x, box.y + y);
@@ -1623,7 +1653,7 @@ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1623
1653
  rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1624
1654
  data.transform = transform;
1625
1655
  }
1626
- function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew) {
1656
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew, clipSize) {
1627
1657
  const transform = get$3();
1628
1658
  if (rotation)
1629
1659
  rotate(transform, rotation);
@@ -1632,6 +1662,10 @@ function clipMode(data, box, x, y, scaleX, scaleY, rotation, skew) {
1632
1662
  if (scaleX)
1633
1663
  scaleHelper(transform, scaleX, scaleY);
1634
1664
  translate$1(transform, box.x + x, box.y + y);
1665
+ if (clipSize) {
1666
+ tempMatrix.a = box.width / clipSize.width, tempMatrix.d = box.height / clipSize.height;
1667
+ multiplyParent(transform, tempMatrix);
1668
+ }
1635
1669
  data.transform = transform;
1636
1670
  }
1637
1671
  function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
@@ -1668,13 +1702,15 @@ const tempBox = new Bounds();
1668
1702
  const tempScaleData = {};
1669
1703
  const tempImage = {};
1670
1704
  function createData(leafPaint, image, paint, box) {
1671
- const { changeful, sync, editing } = paint;
1705
+ const { changeful, sync, editing, scaleFixed } = paint;
1672
1706
  if (changeful)
1673
1707
  leafPaint.changeful = changeful;
1674
1708
  if (sync)
1675
1709
  leafPaint.sync = sync;
1676
1710
  if (editing)
1677
1711
  leafPaint.editing = editing;
1712
+ if (scaleFixed)
1713
+ leafPaint.scaleFixed = scaleFixed;
1678
1714
  leafPaint.data = getPatternData(paint, box, image);
1679
1715
  }
1680
1716
  function getPatternData(paint, box, image) {
@@ -1683,7 +1719,7 @@ function getPatternData(paint, box, image) {
1683
1719
  if (paint.mode === 'strench')
1684
1720
  paint.mode = 'stretch';
1685
1721
  let { width, height } = image;
1686
- const { opacity, mode, align, offset, scale, size, rotation, skew, repeat, filters } = paint;
1722
+ const { opacity, mode, align, offset, scale, size, rotation, skew, clipSize, repeat, filters } = paint;
1687
1723
  const sameBox = box.width === width && box.height === height;
1688
1724
  const data = { mode };
1689
1725
  const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
@@ -1717,8 +1753,8 @@ function getPatternData(paint, box, image) {
1717
1753
  break;
1718
1754
  case 'normal':
1719
1755
  case 'clip':
1720
- if (tempImage.x || tempImage.y || scaleX || rotation || skew)
1721
- clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew);
1756
+ if (tempImage.x || tempImage.y || scaleX || clipSize || rotation || skew)
1757
+ clipMode(data, box, tempImage.x, tempImage.y, scaleX, scaleY, rotation, skew, paint.clipSize);
1722
1758
  break;
1723
1759
  case 'repeat':
1724
1760
  if (!sameBox || scaleX || rotation)
@@ -1855,18 +1891,16 @@ function ignoreRender(ui, value) {
1855
1891
  }
1856
1892
 
1857
1893
  const { get: get$1, scale, copy: copy$1 } = MatrixHelper;
1858
- const { ceil, abs: abs$1 } = Math;
1894
+ const { ceil, abs } = Math;
1859
1895
  function createPattern(ui, paint, pixelRatio) {
1860
- let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1896
+ let { scaleX, scaleY } = ui.getRenderScaleData(true, paint.scaleFixed);
1861
1897
  const id = scaleX + '-' + scaleY + '-' + pixelRatio;
1862
1898
  if (paint.patternId !== id && !ui.destroyed) {
1863
- scaleX = abs$1(scaleX);
1864
- scaleY = abs$1(scaleY);
1865
1899
  const { image, data } = paint;
1866
1900
  let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, transform, repeat } = data;
1867
1901
  if (sx) {
1868
- sx = abs$1(sx);
1869
- sy = abs$1(sy);
1902
+ sx = abs(sx);
1903
+ sy = abs(sy);
1870
1904
  imageMatrix = get$1();
1871
1905
  copy$1(imageMatrix, transform);
1872
1906
  scale(imageMatrix, 1 / sx, 1 / sy);
@@ -1951,9 +1985,8 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
1951
1985
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1952
1986
  };
1953
1987
 
1954
- const { abs } = Math;
1955
1988
  function checkImage(ui, canvas, paint, allowDraw) {
1956
- const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1989
+ const { scaleX, scaleY } = ui.getRenderScaleData(true, paint.scaleFixed);
1957
1990
  const { pixelRatio } = canvas, { data } = paint;
1958
1991
  if (!data || (paint.patternId === scaleX + '-' + scaleY + '-' + pixelRatio && !Export.running)) {
1959
1992
  return false;
@@ -1966,8 +1999,8 @@ function checkImage(ui, canvas, paint, allowDraw) {
1966
1999
  else {
1967
2000
  if (!(paint.changeful || ResizeEvent.isResizing(ui) || Export.running)) {
1968
2001
  let { width, height } = data;
1969
- width *= abs(scaleX) * pixelRatio;
1970
- height *= abs(scaleY) * pixelRatio;
2002
+ width *= scaleX * pixelRatio;
2003
+ height *= scaleY * pixelRatio;
1971
2004
  if (data.scaleX) {
1972
2005
  width *= data.scaleX;
1973
2006
  height *= data.scaleY;
@@ -1977,6 +2010,10 @@ function checkImage(ui, canvas, paint, allowDraw) {
1977
2010
  }
1978
2011
  }
1979
2012
  if (allowDraw) {
2013
+ if (ui.__.__isFastShadow) {
2014
+ canvas.fillStyle = paint.style || '#000';
2015
+ canvas.fill();
2016
+ }
1980
2017
  drawImage(ui, canvas, paint, data);
1981
2018
  return true;
1982
2019
  }
@@ -2165,10 +2202,7 @@ function shadow(ui, current, shape) {
2165
2202
  }
2166
2203
  worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
2167
2204
  }
2168
- if (ui.__worldFlipped)
2169
- current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
2170
- else
2171
- current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2205
+ LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
2172
2206
  if (end && index < end)
2173
2207
  other.clearWorld(copyBounds, true);
2174
2208
  });
@@ -2227,10 +2261,7 @@ function innerShadow(ui, current, shape) {
2227
2261
  copyBounds = bounds;
2228
2262
  }
2229
2263
  other.fillWorld(copyBounds, ColorConvert.string(item.color), 'source-in');
2230
- if (ui.__worldFlipped)
2231
- current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
2232
- else
2233
- current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2264
+ LeafHelper.copyCanvasByWorld(ui, current, other, copyBounds, item.blendMode);
2234
2265
  if (end && index < end)
2235
2266
  other.clearWorld(copyBounds, true);
2236
2267
  });
@@ -2286,12 +2317,11 @@ Group.prototype.__renderMask = function (canvas, options) {
2286
2317
  contentCanvas = getCanvas(canvas);
2287
2318
  child.__render(maskCanvas, options);
2288
2319
  }
2289
- if (!(mask === 'clipping' || mask === 'clipping-path'))
2290
- continue;
2291
- }
2292
- if (excludeRenderBounds(child, options))
2320
+ if (mask === 'clipping' || mask === 'clipping-path')
2321
+ excludeRenderBounds(child, options) || child.__render(canvas, options);
2293
2322
  continue;
2294
- child.__render(contentCanvas || canvas, options);
2323
+ }
2324
+ excludeRenderBounds(child, options) || child.__render(contentCanvas || canvas, options);
2295
2325
  }
2296
2326
  maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
2297
2327
  };