gradiente 2.1.2 → 2.3.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/dist/index.js CHANGED
@@ -1179,8 +1179,37 @@ var LinearGradient = class LinearGradient extends GradientBase {
1179
1179
  //#endregion
1180
1180
  //#region src/gradients/RadialGradient.ts
1181
1181
  var RadialGradient = class RadialGradient extends GradientBase {
1182
+ static DEFAULT_CONFIG = {
1183
+ isRepeating: false,
1184
+ stops: [{
1185
+ type: "color-stop",
1186
+ value: "red",
1187
+ position: 0
1188
+ }, {
1189
+ type: "color-stop",
1190
+ value: "blue",
1191
+ position: 1
1192
+ }],
1193
+ config: {
1194
+ shape: "ellipse",
1195
+ size: {
1196
+ kind: "extent",
1197
+ value: "farthest-corner"
1198
+ },
1199
+ position: {
1200
+ kind: "keywords",
1201
+ x: "center",
1202
+ y: "center"
1203
+ }
1204
+ }
1205
+ };
1182
1206
  type = "radial-gradient";
1183
- constructor(config) {
1207
+ constructor(input) {
1208
+ const config = {
1209
+ ...RadialGradient.DEFAULT_CONFIG,
1210
+ ...input
1211
+ };
1212
+ if (config.config.interpolation) config.config.interpolation = RadialGradient._normalizeConfigInterpolation(config.config.interpolation);
1184
1213
  super(config);
1185
1214
  }
1186
1215
  static fromString(input) {
@@ -1201,31 +1230,47 @@ var RadialGradient = class RadialGradient extends GradientBase {
1201
1230
  return new RadialGradient(this.toJSON());
1202
1231
  }
1203
1232
  toString() {
1204
- return `${this.isRepeating ? `repeating-${this.type}` : this.type}(${[this._serializeRadialConfig(this.config), ...this._serializeStopsCompact()].filter(Boolean).join(", ")})`;
1233
+ return `${this.isRepeating ? `repeating-${this.type}` : this.type}(${[this._parseConfigToString(this.config), ...this._serializeStopsCompact()].filter(Boolean).join(", ")})`;
1205
1234
  }
1206
1235
  _validateConfig(config) {
1207
1236
  if (config.shape !== "circle" && config.shape !== "ellipse") throw new Error("Invalid shape");
1208
1237
  if (!config.position) throw new Error("Position is required");
1209
1238
  if (!config.size) throw new Error("Size is required");
1210
1239
  }
1211
- _serializeRadialConfig(config) {
1240
+ _parseConfigToString(config) {
1241
+ const configParts = [];
1242
+ const radialConfigString = this._parseRadialConfigToString(config);
1243
+ if (radialConfigString.length > 0) configParts.push(radialConfigString);
1244
+ if (config.interpolation !== void 0) configParts.push(this._parseInterpolationToString(config.interpolation));
1245
+ return configParts.join(" ");
1246
+ }
1247
+ _parseRadialConfigToString(config) {
1212
1248
  const parts = [];
1213
- parts.push(config.shape);
1214
- if (config.size.kind === "extent") parts.push(config.size.value);
1215
- else {
1216
- const x = this._formatLengthPercentage(config.size.x);
1217
- const y = config.size.y ? ` ${this._formatLengthPercentage(config.size.y)}` : "";
1218
- parts.push(`${x}${y}`);
1219
- }
1220
- parts.push(`at ${this._serializePosition(config.position)}`);
1221
- if (config.interpolation) if (config.interpolation.kind === "rectangular") parts.push(`in ${config.interpolation.space}`);
1222
- else {
1223
- let str = `in ${config.interpolation.space}`;
1224
- if (config.interpolation.hueMethod) str += ` ${config.interpolation.hueMethod} hue`;
1225
- parts.push(str);
1226
- }
1249
+ if (!this._isDefaultRadialShape(config.shape)) parts.push(config.shape);
1250
+ if (!this._isDefaultRadialSize(config.size)) parts.push(this._parseRadialSizeToString(config.size));
1251
+ if (!this._isDefaultRadialPosition(config.position)) parts.push(`at ${this._serializePosition(config.position)}`);
1227
1252
  return parts.join(" ");
1228
1253
  }
1254
+ _parseRadialSizeToString(size) {
1255
+ if (size.kind === "extent") return size.value;
1256
+ const x = this._formatLengthPercentage(size.x);
1257
+ if (size.y === void 0) return x;
1258
+ return `${x} ${this._formatLengthPercentage(size.y)}`;
1259
+ }
1260
+ _parseInterpolationToString(interpolation) {
1261
+ const { colorSpace, hue } = interpolation;
1262
+ if (hue === void 0) return `in ${colorSpace}`;
1263
+ return `in ${colorSpace} ${hue} hue`;
1264
+ }
1265
+ _isDefaultRadialShape(shape) {
1266
+ return shape === "ellipse";
1267
+ }
1268
+ _isDefaultRadialSize(size) {
1269
+ return size.kind === "extent" && size.value === "farthest-corner";
1270
+ }
1271
+ _isDefaultRadialPosition(position) {
1272
+ return position.kind === "keywords" && position.x === "center" && position.y === "center";
1273
+ }
1229
1274
  _serializePosition(position) {
1230
1275
  if (position.kind === "keywords") return `${position.x} ${position.y}`;
1231
1276
  const x = this._formatLengthPercentage(position.x);
@@ -1247,6 +1292,11 @@ var RadialGradient = class RadialGradient extends GradientBase {
1247
1292
  x: "center",
1248
1293
  y: "center"
1249
1294
  };
1295
+ let interpolation;
1296
+ const isLengthPercentage = (value) => {
1297
+ if (value === void 0) return false;
1298
+ return value.endsWith("%") || /^-?\d*\.?\d+[a-zA-Z]+$/.test(value);
1299
+ };
1250
1300
  for (const input of inputs) {
1251
1301
  if (input.type !== "config") continue;
1252
1302
  const tokens = splitTopLevelByWhitespace(input.value);
@@ -1263,20 +1313,88 @@ var RadialGradient = class RadialGradient extends GradientBase {
1263
1313
  };
1264
1314
  continue;
1265
1315
  }
1316
+ if (isLengthPercentage(t)) {
1317
+ const nextToken = tokens[i + 1];
1318
+ if (shape === "ellipse" && isLengthPercentage(nextToken)) {
1319
+ size = {
1320
+ kind: "explicit",
1321
+ x: this._parseLengthPercentage(t),
1322
+ y: this._parseLengthPercentage(nextToken)
1323
+ };
1324
+ i += 1;
1325
+ continue;
1326
+ }
1327
+ size = {
1328
+ kind: "explicit",
1329
+ x: this._parseLengthPercentage(t)
1330
+ };
1331
+ continue;
1332
+ }
1266
1333
  if (t === "at") {
1267
1334
  const xToken = tokens[i + 1];
1268
1335
  const yToken = tokens[i + 2];
1269
- if ((xToken === "left" || xToken === "center" || xToken === "right") && (yToken === "top" || yToken === "center" || yToken === "bottom")) position = {
1270
- kind: "keywords",
1271
- x: xToken,
1272
- y: yToken
1273
- };
1274
- else position = {
1275
- kind: "values",
1276
- x: this._parseLengthPercentage(xToken),
1277
- y: this._parseLengthPercentage(yToken)
1278
- };
1279
- i += 2;
1336
+ if (xToken === "center" && (yToken === void 0 || yToken === "in")) {
1337
+ position = {
1338
+ kind: "keywords",
1339
+ x: "center",
1340
+ y: "center"
1341
+ };
1342
+ i += 1;
1343
+ continue;
1344
+ }
1345
+ if ((xToken === "left" || xToken === "right") && (yToken === void 0 || yToken === "in")) {
1346
+ position = {
1347
+ kind: "keywords",
1348
+ x: xToken,
1349
+ y: "center"
1350
+ };
1351
+ i += 1;
1352
+ continue;
1353
+ }
1354
+ if ((xToken === "top" || xToken === "bottom") && (yToken === void 0 || yToken === "in")) {
1355
+ position = {
1356
+ kind: "keywords",
1357
+ x: "center",
1358
+ y: xToken
1359
+ };
1360
+ i += 1;
1361
+ continue;
1362
+ }
1363
+ if ((xToken === "left" || xToken === "center" || xToken === "right") && (yToken === "top" || yToken === "center" || yToken === "bottom")) {
1364
+ position = {
1365
+ kind: "keywords",
1366
+ x: xToken,
1367
+ y: yToken
1368
+ };
1369
+ i += 2;
1370
+ continue;
1371
+ }
1372
+ if (isLengthPercentage(xToken) && isLengthPercentage(yToken)) {
1373
+ position = {
1374
+ kind: "values",
1375
+ x: this._parseLengthPercentage(xToken),
1376
+ y: this._parseLengthPercentage(yToken)
1377
+ };
1378
+ i += 2;
1379
+ continue;
1380
+ }
1381
+ throw new Error(`Invalid radial-gradient position: ${xToken ?? ""} ${yToken ?? ""}`);
1382
+ }
1383
+ if (t === "in") {
1384
+ const colorSpace = tokens[i + 1];
1385
+ const maybeHue = tokens[i + 2];
1386
+ const maybeHueKeyword = tokens[i + 3];
1387
+ if (!colorSpace) throw new Error("Invalid radial-gradient interpolation: missing color space");
1388
+ if (maybeHue !== void 0 && maybeHueKeyword === "hue") {
1389
+ interpolation = this._normalizeConfigInterpolation({
1390
+ colorSpace,
1391
+ hue: maybeHue
1392
+ });
1393
+ i += 3;
1394
+ continue;
1395
+ }
1396
+ interpolation = this._normalizeConfigInterpolation({ colorSpace });
1397
+ i += 1;
1280
1398
  continue;
1281
1399
  }
1282
1400
  }
@@ -1284,7 +1402,8 @@ var RadialGradient = class RadialGradient extends GradientBase {
1284
1402
  return {
1285
1403
  shape,
1286
1404
  size,
1287
- position
1405
+ position,
1406
+ interpolation
1288
1407
  };
1289
1408
  }
1290
1409
  static _parseLengthPercentage(input) {
@@ -1300,6 +1419,15 @@ var RadialGradient = class RadialGradient extends GradientBase {
1300
1419
  unit: match[2]
1301
1420
  };
1302
1421
  }
1422
+ static _normalizeConfigInterpolation(value) {
1423
+ const { colorSpace, hue } = value;
1424
+ if (hue === void 0) return { colorSpace };
1425
+ if (!isGradientPolarColorSpace(colorSpace)) return { colorSpace };
1426
+ return {
1427
+ colorSpace,
1428
+ hue
1429
+ };
1430
+ }
1303
1431
  };
1304
1432
  //#endregion
1305
1433
  //#region src/gradients/ConicGradient.ts
@@ -1332,18 +1460,12 @@ var ConicGradient = class ConicGradient extends GradientBase {
1332
1460
  _validateConfig(config) {}
1333
1461
  _serializeConfig() {
1334
1462
  const parts = [];
1335
- const angle = this.config.from;
1336
- parts.push(`from ${angle.value}${angle.unit}`);
1337
- parts.push(`at ${this._serializePosition(this.config.position)}`);
1338
- if (this.config.interpolation) {
1339
- const i = this.config.interpolation;
1340
- if (i.kind === "rectangular") parts.push(`in ${i.space}`);
1341
- else {
1342
- let str = `in ${i.space}`;
1343
- if (i.hueMethod) str += ` ${i.hueMethod} hue`;
1344
- parts.push(str);
1345
- }
1463
+ if (!this._isDefaultFrom(this.config.from)) {
1464
+ const angle = this.config.from;
1465
+ parts.push(`from ${angle.value}${angle.unit}`);
1346
1466
  }
1467
+ if (!this._isDefaultPosition(this.config.position)) parts.push(`at ${this._serializePosition(this.config.position)}`);
1468
+ if (this.config.interpolation !== void 0) parts.push(this._serializeInterpolation(this.config.interpolation));
1347
1469
  return parts.join(" ");
1348
1470
  }
1349
1471
  _serializePosition(position) {
@@ -1356,6 +1478,17 @@ var ConicGradient = class ConicGradient extends GradientBase {
1356
1478
  if (value.kind === "percent") return `${value.value}%`;
1357
1479
  return `${value.value}${value.unit}`;
1358
1480
  }
1481
+ _serializeInterpolation(interpolation) {
1482
+ const { colorSpace, hue } = interpolation;
1483
+ if (hue === void 0) return `in ${colorSpace}`;
1484
+ return `in ${colorSpace} ${hue} hue`;
1485
+ }
1486
+ _isDefaultFrom(from) {
1487
+ return from.value === 0 && from.unit === "deg";
1488
+ }
1489
+ _isDefaultPosition(position) {
1490
+ return position.kind === "keywords" && position.x === "center" && position.y === "center";
1491
+ }
1359
1492
  static _parseConfig(input) {
1360
1493
  const config = {
1361
1494
  from: {
@@ -1371,46 +1504,86 @@ var ConicGradient = class ConicGradient extends GradientBase {
1371
1504
  };
1372
1505
  if (!input) return config;
1373
1506
  const tokens = splitTopLevelByWhitespace(input);
1507
+ const isLengthPercentage = (value) => {
1508
+ if (value === void 0) return false;
1509
+ return value.endsWith("%") || /^-?\d*\.?\d+[a-zA-Z]+$/.test(value);
1510
+ };
1374
1511
  for (let i = 0; i < tokens.length; i++) {
1375
1512
  const token = tokens[i];
1376
1513
  if (token === "from") {
1377
- config.from = this._parseAngle(tokens[i + 1]);
1514
+ const angleToken = tokens[i + 1];
1515
+ if (angleToken === void 0) throw new Error("Invalid conic-gradient config: missing angle after from");
1516
+ config.from = this._parseAngle(angleToken);
1378
1517
  i += 1;
1379
1518
  continue;
1380
1519
  }
1381
1520
  if (token === "at") {
1382
1521
  const xToken = tokens[i + 1];
1383
1522
  const yToken = tokens[i + 2];
1384
- if ((xToken === "left" || xToken === "center" || xToken === "right") && (yToken === "top" || yToken === "center" || yToken === "bottom")) config.position = {
1385
- kind: "keywords",
1386
- x: xToken,
1387
- y: yToken
1388
- };
1389
- else config.position = {
1390
- kind: "values",
1391
- x: this._parseLengthPercentage(xToken),
1392
- y: this._parseLengthPercentage(yToken)
1393
- };
1394
- i += 2;
1395
- continue;
1523
+ if (xToken === void 0) throw new Error("Invalid conic-gradient config: missing position after at");
1524
+ if (xToken === "center" && (yToken === void 0 || yToken === "in")) {
1525
+ config.position = {
1526
+ kind: "keywords",
1527
+ x: "center",
1528
+ y: "center"
1529
+ };
1530
+ i += 1;
1531
+ continue;
1532
+ }
1533
+ if ((xToken === "left" || xToken === "right") && (yToken === void 0 || yToken === "in")) {
1534
+ config.position = {
1535
+ kind: "keywords",
1536
+ x: xToken,
1537
+ y: "center"
1538
+ };
1539
+ i += 1;
1540
+ continue;
1541
+ }
1542
+ if ((xToken === "top" || xToken === "bottom") && (yToken === void 0 || yToken === "in")) {
1543
+ config.position = {
1544
+ kind: "keywords",
1545
+ x: "center",
1546
+ y: xToken
1547
+ };
1548
+ i += 1;
1549
+ continue;
1550
+ }
1551
+ if ((xToken === "left" || xToken === "center" || xToken === "right") && (yToken === "top" || yToken === "center" || yToken === "bottom")) {
1552
+ config.position = {
1553
+ kind: "keywords",
1554
+ x: xToken,
1555
+ y: yToken
1556
+ };
1557
+ i += 2;
1558
+ continue;
1559
+ }
1560
+ if (isLengthPercentage(xToken) && isLengthPercentage(yToken)) {
1561
+ config.position = {
1562
+ kind: "values",
1563
+ x: this._parseLengthPercentage(xToken),
1564
+ y: this._parseLengthPercentage(yToken)
1565
+ };
1566
+ i += 2;
1567
+ continue;
1568
+ }
1569
+ throw new Error(`Invalid conic-gradient position: ${xToken} ${yToken ?? ""}`);
1396
1570
  }
1397
1571
  if (token === "in") {
1398
- const space = tokens[i + 1];
1399
- const hueMethod = tokens[i + 2];
1400
- if (tokens[i + 3] === "hue" && (hueMethod === "shorter" || hueMethod === "longer" || hueMethod === "increasing" || hueMethod === "decreasing")) {
1572
+ const colorSpace = tokens[i + 1];
1573
+ const maybeHue = tokens[i + 2];
1574
+ const maybeHueKeyword = tokens[i + 3];
1575
+ if (colorSpace === void 0) throw new Error("Invalid conic-gradient interpolation: missing color space");
1576
+ if (maybeHueKeyword === "hue" && (maybeHue === "shorter" || maybeHue === "longer" || maybeHue === "increasing" || maybeHue === "decreasing")) {
1401
1577
  config.interpolation = {
1402
- kind: "polar",
1403
- space,
1404
- hueMethod
1578
+ colorSpace,
1579
+ hue: maybeHue
1405
1580
  };
1406
1581
  i += 3;
1407
1582
  continue;
1408
1583
  }
1409
- config.interpolation = {
1410
- kind: "rectangular",
1411
- space
1412
- };
1584
+ config.interpolation = { colorSpace };
1413
1585
  i += 1;
1586
+ continue;
1414
1587
  }
1415
1588
  }
1416
1589
  return config;
@@ -1493,7 +1666,7 @@ function sampleColorAtPosition(stops, position) {
1493
1666
  function sampleRepeatingColorAtPosition(stops, position, firstPosition, period) {
1494
1667
  return sampleColorAtPosition(stops, firstPosition + positiveModulo(position - firstPosition, period));
1495
1668
  }
1496
- function expandRepeatingStops(stops) {
1669
+ function expandRepeatingStopsTo(stops, from, to) {
1497
1670
  const colorStops = stops.filter((stop) => stop.type === "color-stop" && stop.position != null).sort((a, b) => a.position - b.position);
1498
1671
  if (colorStops.length < 2) return colorStops;
1499
1672
  const firstPosition = colorStops[0].position;
@@ -1503,18 +1676,18 @@ function expandRepeatingStops(stops) {
1503
1676
  let order = 0;
1504
1677
  result.push({
1505
1678
  type: "color-stop",
1506
- value: sampleRepeatingColorAtPosition(colorStops, 0, firstPosition, period),
1507
- position: 0,
1679
+ value: sampleRepeatingColorAtPosition(colorStops, from, firstPosition, period),
1680
+ position: from,
1508
1681
  _order: order
1509
1682
  });
1510
1683
  order += 1;
1511
- const startRepeat = Math.floor((0 - firstPosition) / period) - 1;
1512
- const endRepeat = Math.ceil((1 - firstPosition) / period) + 1;
1684
+ const startRepeat = Math.floor((from - firstPosition) / period) - 1;
1685
+ const endRepeat = Math.ceil((to - firstPosition) / period) + 1;
1513
1686
  for (let repeatIndex = startRepeat; repeatIndex <= endRepeat; repeatIndex += 1) {
1514
1687
  const offset = repeatIndex * period;
1515
1688
  for (const stop of colorStops) {
1516
1689
  const position = stop.position + offset;
1517
- if (position <= 0 || position >= 1) continue;
1690
+ if (position <= from || position >= to) continue;
1518
1691
  result.push({
1519
1692
  ...stop,
1520
1693
  position,
@@ -1525,8 +1698,8 @@ function expandRepeatingStops(stops) {
1525
1698
  }
1526
1699
  result.push({
1527
1700
  type: "color-stop",
1528
- value: sampleRepeatingColorAtPosition(colorStops, 1, firstPosition, period),
1529
- position: 1,
1701
+ value: sampleRepeatingColorAtPosition(colorStops, to, firstPosition, period),
1702
+ position: to,
1530
1703
  _order: order
1531
1704
  });
1532
1705
  return result.sort((a, b) => {
@@ -1534,6 +1707,33 @@ function expandRepeatingStops(stops) {
1534
1707
  return a.position - b.position;
1535
1708
  }).map(({ _order, ...stop }) => stop);
1536
1709
  }
1710
+ function expandRepeatingStops(stops) {
1711
+ return expandRepeatingStopsTo(stops, 0, 1);
1712
+ }
1713
+ function getMaxVisibleRadialT(center, radii, width, height) {
1714
+ return Math.max(...[
1715
+ {
1716
+ x: 0,
1717
+ y: 0
1718
+ },
1719
+ {
1720
+ x: width,
1721
+ y: 0
1722
+ },
1723
+ {
1724
+ x: 0,
1725
+ y: height
1726
+ },
1727
+ {
1728
+ x: width,
1729
+ y: height
1730
+ }
1731
+ ].map((corner) => {
1732
+ const dx = (corner.x - center.x) / Math.max(radii.x, 1e-4);
1733
+ const dy = (corner.y - center.y) / Math.max(radii.y, 1e-4);
1734
+ return Math.sqrt(dx * dx + dy * dy);
1735
+ }));
1736
+ }
1537
1737
  //#endregion
1538
1738
  //#region src/gradient-transformer/modules/helpers/resolve-renderable-linear-gradient-stops.ts
1539
1739
  function getHueFixup(hue) {
@@ -1583,13 +1783,13 @@ function getColorStopsWithPositions(stops) {
1583
1783
  });
1584
1784
  }
1585
1785
  function formatColorForCanvas(input) {
1586
- const color = toRgb$4(input);
1786
+ const color = toRgb$6(input);
1587
1787
  if (!color) throw new Error("Failed to convert interpolated color to rgb.");
1588
1788
  return formatRgb(color);
1589
1789
  }
1590
1790
  const DEFAULT_SAMPLE_COUNT = 64;
1591
- const toRgb$4 = converter("rgb");
1592
- function resolveRenderableLinearGradientStops(gradient, sampleCount = DEFAULT_SAMPLE_COUNT) {
1791
+ const toRgb$6 = converter("rgb");
1792
+ function resolveRenderableGradientStops(gradient, sampleCount = DEFAULT_SAMPLE_COUNT) {
1593
1793
  const colorStops = getColorStopsWithPositions(gradient.stops);
1594
1794
  const interpolation = gradient.config.interpolation;
1595
1795
  if (colorStops.length < 2) return colorStops;
@@ -1619,9 +1819,9 @@ function resolveRenderableLinearGradientStops(gradient, sampleCount = DEFAULT_SA
1619
1819
  }
1620
1820
  //#endregion
1621
1821
  //#region src/gradient-transformer/modules/canvas/ModuleTransformerLinearGradientToCanvas.ts
1622
- const toRgb$3 = converter("rgb");
1822
+ const toRgb$5 = converter("rgb");
1623
1823
  function toCanvasColor$1(input) {
1624
- const color = toRgb$3(input);
1824
+ const color = toRgb$5(input);
1625
1825
  if (!color) throw new Error(`Failed to convert color: ${input}`);
1626
1826
  return formatRgb(color);
1627
1827
  }
@@ -1638,7 +1838,7 @@ function getStopRange$2(stops) {
1638
1838
  stops: colorStops
1639
1839
  };
1640
1840
  }
1641
- function normalizeStops$2(stops, min, max) {
1841
+ function normalizeStops$3(stops, min, max) {
1642
1842
  const range = max - min || 1;
1643
1843
  return stops.filter((stop) => stop.type === "color-stop" && stop.position != null).map((stop) => ({
1644
1844
  ...stop,
@@ -1661,7 +1861,7 @@ var ModuleTransformerLinearGradientToCanvas = class {
1661
1861
  let startY = centerY - dirY * lineLength / 2;
1662
1862
  let endX = centerX + dirX * lineLength / 2;
1663
1863
  let endY = centerY + dirY * lineLength / 2;
1664
- const { min, max, stops } = getStopRange$2(resolveRenderableLinearGradientStops(gradient));
1864
+ const { min, max, stops } = getStopRange$2(resolveRenderableGradientStops(gradient));
1665
1865
  let normalizedStops = stops;
1666
1866
  if (min < 0 || max > 1) {
1667
1867
  const vx = endX - startX;
@@ -1672,7 +1872,7 @@ var ModuleTransformerLinearGradientToCanvas = class {
1672
1872
  startY = baseStartY + vy * min;
1673
1873
  endX = baseStartX + vx * max;
1674
1874
  endY = baseStartY + vy * max;
1675
- normalizedStops = normalizeStops$2(stops, min, max);
1875
+ normalizedStops = normalizeStops$3(stops, min, max);
1676
1876
  }
1677
1877
  const canvasGradient = ctx.createLinearGradient(startX, startY, endX, endY);
1678
1878
  for (const stop of normalizedStops) canvasGradient.addColorStop(stop.position, toCanvasColor$1(stop.value));
@@ -1684,9 +1884,10 @@ var ModuleTransformerLinearGradientToCanvas = class {
1684
1884
  };
1685
1885
  //#endregion
1686
1886
  //#region src/gradient-transformer/modules/canvas/ModuleTransformerRadialGradientToCanvas.ts
1687
- const toRgb$2 = converter("rgb");
1887
+ const toRgb$4 = converter("rgb");
1888
+ const RADIAL_GRADIENT_SAMPLE_COUNT = 128;
1688
1889
  function toCanvasColor(input) {
1689
- const color = toRgb$2(input);
1890
+ const color = toRgb$4(input);
1690
1891
  if (!color) throw new Error(`Failed to convert color: ${input}`);
1691
1892
  return formatRgb(color);
1692
1893
  }
@@ -1703,47 +1904,200 @@ function getStopRange$1(stops) {
1703
1904
  stops: colorStops
1704
1905
  };
1705
1906
  }
1706
- function normalizeStops$1(stops, min, max) {
1907
+ function normalizeStops$2(stops, min, max) {
1707
1908
  const range = max - min || 1;
1708
1909
  return stops.map((stop) => ({
1709
1910
  ...stop,
1710
1911
  position: (stop.position - min) / range
1711
1912
  }));
1712
1913
  }
1914
+ function getDistanceToSide$1(center, width, height, side) {
1915
+ if (side === "left") return center.x;
1916
+ if (side === "right") return width - center.x;
1917
+ if (side === "top") return center.y;
1918
+ return height - center.y;
1919
+ }
1920
+ function getDistanceToCorner$1(center, corner) {
1921
+ const dx = corner.x - center.x;
1922
+ const dy = corner.y - center.y;
1923
+ return Math.sqrt(dx * dx + dy * dy);
1924
+ }
1925
+ function getCornerDeltas$1(center, width, height) {
1926
+ return [
1927
+ {
1928
+ dx: -center.x,
1929
+ dy: -center.y
1930
+ },
1931
+ {
1932
+ dx: width - center.x,
1933
+ dy: -center.y
1934
+ },
1935
+ {
1936
+ dx: -center.x,
1937
+ dy: height - center.y
1938
+ },
1939
+ {
1940
+ dx: width - center.x,
1941
+ dy: height - center.y
1942
+ }
1943
+ ];
1944
+ }
1945
+ function scaleEllipseRadiiToCorner$1(radiusX, radiusY, dx, dy) {
1946
+ const safeRadiusX = Math.max(radiusX, 1e-4);
1947
+ const safeRadiusY = Math.max(radiusY, 1e-4);
1948
+ const scale = Math.sqrt(dx * dx / (safeRadiusX * safeRadiusX) + dy * dy / (safeRadiusY * safeRadiusY));
1949
+ return {
1950
+ x: safeRadiusX * scale,
1951
+ y: safeRadiusY * scale
1952
+ };
1953
+ }
1713
1954
  var ModuleTransformerRadialGradientToCanvas = class {
1714
1955
  target = "canvas-2d";
1715
1956
  gradientType = "radial-gradient";
1716
1957
  to(input) {
1717
1958
  const gradient = input;
1718
1959
  return { draw: (ctx, width, height) => {
1719
- const pos = gradient.config.position;
1720
- let x = width / 2;
1721
- let y = height / 2;
1722
- if (pos.kind === "values") {
1723
- x = this._resolve(pos.x, width);
1724
- y = this._resolve(pos.y, height);
1725
- }
1726
- const dx = Math.max(x, width - x);
1727
- const dy = Math.max(y, height - y);
1728
- const radius = Math.sqrt(dx * dx + dy * dy);
1729
- const { min, max, stops } = getStopRange$1(gradient.stops);
1730
- let innerRadius = 0;
1731
- let outerRadius = radius;
1960
+ const center = this._resolveCenter(gradient.config.position, width, height);
1961
+ const radii = this._resolveRadialRadii(gradient.config.size, gradient.config.shape, center, width, height);
1962
+ const maxVisibleT = getMaxVisibleRadialT(center, radii, width, height);
1963
+ const baseStops = resolveRenderableGradientStops(gradient, RADIAL_GRADIENT_SAMPLE_COUNT);
1964
+ const { min, max, stops } = getStopRange$1(gradient.isRepeating ? expandRepeatingStopsTo(baseStops, 0, maxVisibleT) : baseStops);
1732
1965
  let normalizedStops = stops;
1733
- if (min >= 0 && (min < 0 || max > 1)) {
1734
- innerRadius = radius * min;
1735
- outerRadius = radius * max;
1736
- normalizedStops = normalizeStops$1(stops, min, max);
1737
- } else if (max > 1) {
1738
- outerRadius = radius * max;
1739
- normalizedStops = normalizeStops$1(stops, min, max);
1966
+ let innerFactor = 0;
1967
+ let outerFactor = gradient.isRepeating ? maxVisibleT : 1;
1968
+ if (gradient.isRepeating) normalizedStops = normalizeStops$2(stops, 0, maxVisibleT);
1969
+ else if (min < 0 || max > 1) {
1970
+ normalizedStops = normalizeStops$2(stops, min, max);
1971
+ innerFactor = min;
1972
+ outerFactor = max;
1740
1973
  }
1741
- const g = ctx.createRadialGradient(x, y, innerRadius, x, y, outerRadius);
1974
+ if (gradient.config.shape === "circle") {
1975
+ const baseRadius = radii.x;
1976
+ const innerRadius = Math.max(0, baseRadius * innerFactor);
1977
+ const outerRadius = Math.max(innerRadius + 1e-4, baseRadius * outerFactor);
1978
+ const g = ctx.createRadialGradient(center.x, center.y, innerRadius, center.x, center.y, outerRadius);
1979
+ for (const stop of normalizedStops) g.addColorStop(stop.position, toCanvasColor(stop.value));
1980
+ ctx.fillStyle = g;
1981
+ ctx.fillRect(0, 0, width, height);
1982
+ return;
1983
+ }
1984
+ const outerRadius = Math.max(radii.x, radii.y);
1985
+ const scaleX = radii.x / outerRadius;
1986
+ const scaleY = radii.y / outerRadius;
1987
+ const innerRadius = Math.max(0, outerRadius * innerFactor);
1988
+ const scaledOuterRadius = Math.max(innerRadius + 1e-4, outerRadius * outerFactor);
1989
+ ctx.save();
1990
+ ctx.translate(center.x, center.y);
1991
+ ctx.scale(scaleX, scaleY);
1992
+ const g = ctx.createRadialGradient(0, 0, innerRadius, 0, 0, scaledOuterRadius);
1742
1993
  for (const stop of normalizedStops) g.addColorStop(stop.position, toCanvasColor(stop.value));
1743
1994
  ctx.fillStyle = g;
1744
- ctx.fillRect(0, 0, width, height);
1995
+ const drawRadius = scaledOuterRadius + 2;
1996
+ ctx.fillRect(-drawRadius / scaleX * 2, -drawRadius / scaleY * 2, drawRadius / scaleX * 4, drawRadius / scaleY * 4);
1997
+ ctx.restore();
1745
1998
  } };
1746
1999
  }
2000
+ _resolveCenter(position, width, height) {
2001
+ if (position.kind === "keywords") return {
2002
+ x: this._resolveKeywordX(position.x, width),
2003
+ y: this._resolveKeywordY(position.y, height)
2004
+ };
2005
+ return {
2006
+ x: this._resolve(position.x, width),
2007
+ y: this._resolve(position.y, height)
2008
+ };
2009
+ }
2010
+ _resolveKeywordX(value, width) {
2011
+ if (value === "left") return 0;
2012
+ if (value === "center") return width / 2;
2013
+ return width;
2014
+ }
2015
+ _resolveKeywordY(value, height) {
2016
+ if (value === "top") return 0;
2017
+ if (value === "center") return height / 2;
2018
+ return height;
2019
+ }
2020
+ _resolveRadialRadii(size, shape, center, width, height) {
2021
+ if (size.kind === "explicit") {
2022
+ const radiusX = this._resolve(size.x, width);
2023
+ const radiusY = size.y ? this._resolve(size.y, height) : radiusX;
2024
+ return {
2025
+ x: Math.max(radiusX, 1e-4),
2026
+ y: Math.max(shape === "circle" ? radiusX : radiusY, 1e-4)
2027
+ };
2028
+ }
2029
+ const left = getDistanceToSide$1(center, width, height, "left");
2030
+ const right = getDistanceToSide$1(center, width, height, "right");
2031
+ const top = getDistanceToSide$1(center, width, height, "top");
2032
+ const bottom = getDistanceToSide$1(center, width, height, "bottom");
2033
+ if (shape === "circle") {
2034
+ const cornerDistances = [
2035
+ {
2036
+ x: 0,
2037
+ y: 0
2038
+ },
2039
+ {
2040
+ x: width,
2041
+ y: 0
2042
+ },
2043
+ {
2044
+ x: 0,
2045
+ y: height
2046
+ },
2047
+ {
2048
+ x: width,
2049
+ y: height
2050
+ }
2051
+ ].map((corner) => getDistanceToCorner$1(center, corner));
2052
+ if (size.value === "closest-side") {
2053
+ const radius = Math.min(left, right, top, bottom);
2054
+ return {
2055
+ x: radius,
2056
+ y: radius
2057
+ };
2058
+ }
2059
+ if (size.value === "farthest-side") {
2060
+ const radius = Math.max(left, right, top, bottom);
2061
+ return {
2062
+ x: radius,
2063
+ y: radius
2064
+ };
2065
+ }
2066
+ if (size.value === "closest-corner") {
2067
+ const radius = Math.min(...cornerDistances);
2068
+ return {
2069
+ x: radius,
2070
+ y: radius
2071
+ };
2072
+ }
2073
+ const radius = Math.max(...cornerDistances);
2074
+ return {
2075
+ x: radius,
2076
+ y: radius
2077
+ };
2078
+ }
2079
+ const closestSideRadiusX = Math.min(left, right);
2080
+ const closestSideRadiusY = Math.min(top, bottom);
2081
+ const farthestSideRadiusX = Math.max(left, right);
2082
+ const farthestSideRadiusY = Math.max(top, bottom);
2083
+ if (size.value === "closest-side") return {
2084
+ x: Math.max(closestSideRadiusX, 1e-4),
2085
+ y: Math.max(closestSideRadiusY, 1e-4)
2086
+ };
2087
+ if (size.value === "farthest-side") return {
2088
+ x: Math.max(farthestSideRadiusX, 1e-4),
2089
+ y: Math.max(farthestSideRadiusY, 1e-4)
2090
+ };
2091
+ const corners = getCornerDeltas$1(center, width, height);
2092
+ if (size.value === "closest-corner") return corners.map((corner) => scaleEllipseRadiiToCorner$1(closestSideRadiusX, closestSideRadiusY, corner.dx, corner.dy)).reduce((closest, current) => {
2093
+ const closestArea = closest.x * closest.y;
2094
+ return current.x * current.y < closestArea ? current : closest;
2095
+ });
2096
+ return corners.map((corner) => scaleEllipseRadiiToCorner$1(farthestSideRadiusX, farthestSideRadiusY, corner.dx, corner.dy)).reduce((farthest, current) => {
2097
+ const farthestArea = farthest.x * farthest.y;
2098
+ return current.x * current.y > farthestArea ? current : farthest;
2099
+ });
2100
+ }
1747
2101
  _resolve(value, size) {
1748
2102
  if (value.kind === "percent") return value.value / 100 * size;
1749
2103
  if (value.unit === "px") return value.value;
@@ -1752,7 +2106,8 @@ var ModuleTransformerRadialGradientToCanvas = class {
1752
2106
  };
1753
2107
  //#endregion
1754
2108
  //#region src/gradient-transformer/modules/canvas/ModuleTransformerConicGradientToCanvas.ts
1755
- const toRgb$1 = converter("rgb");
2109
+ const CONIC_GRADIENT_SAMPLE_COUNT = 128;
2110
+ const toRgb$3 = converter("rgb");
1756
2111
  var ModuleTransformerConicGradientToCanvas = class {
1757
2112
  target = "canvas-2d";
1758
2113
  gradientType = "conic-gradient";
@@ -1763,7 +2118,8 @@ var ModuleTransformerConicGradientToCanvas = class {
1763
2118
  const data = imageData.data;
1764
2119
  const { x: cx, y: cy } = this._resolvePosition(gradient.config.position, width, height);
1765
2120
  const from = this._toRad(gradient.config.from);
1766
- const stops = this._normalizeStops(gradient.stops);
2121
+ const renderStops = resolveRenderableGradientStops(gradient, CONIC_GRADIENT_SAMPLE_COUNT);
2122
+ const stops = this._normalizeStops(renderStops);
1767
2123
  if (stops.length === 0) {
1768
2124
  ctx.putImageData(imageData, 0, 0);
1769
2125
  return;
@@ -1851,7 +2207,7 @@ var ModuleTransformerConicGradientToCanvas = class {
1851
2207
  };
1852
2208
  }
1853
2209
  _parseColor(input) {
1854
- const color = toRgb$1(input);
2210
+ const color = toRgb$3(input);
1855
2211
  if (!color) throw new Error(`Failed to convert color: ${input}`);
1856
2212
  return {
1857
2213
  r: Math.round((color.r ?? 0) * 255),
@@ -1866,10 +2222,10 @@ var ModuleTransformerConicGradientToCanvas = class {
1866
2222
  };
1867
2223
  //#endregion
1868
2224
  //#region src/gradient-transformer/modules/webgl/ModuleTransformerLinearGradientToWebgl.ts
1869
- const toRgb = converter("rgb");
1870
- const MAX_STOPS = 128;
1871
- function toWebGLColor(input) {
1872
- const color = toRgb(input);
2225
+ const toRgb$2 = converter("rgb");
2226
+ const MAX_STOPS$2 = 128;
2227
+ function toWebGLColor$2(input) {
2228
+ const color = toRgb$2(input);
1873
2229
  if (!color) throw new Error(`Failed to convert color: ${input}`);
1874
2230
  return [
1875
2231
  color.r ?? 0,
@@ -1891,14 +2247,14 @@ function getStopRange(stops) {
1891
2247
  stops: colorStops
1892
2248
  };
1893
2249
  }
1894
- function normalizeStops(stops, min, max) {
2250
+ function normalizeStops$1(stops, min, max) {
1895
2251
  const range = max - min || 1;
1896
2252
  return stops.filter((stop) => stop.type === "color-stop" && stop.position != null).map((stop) => ({
1897
2253
  ...stop,
1898
2254
  position: (stop.position - min) / range
1899
2255
  }));
1900
2256
  }
1901
- function createShader(gl, type, source) {
2257
+ function createShader$2(gl, type, source) {
1902
2258
  const shader = gl.createShader(type);
1903
2259
  if (!shader) throw new Error("Failed to create WebGL shader.");
1904
2260
  gl.shaderSource(shader, source);
@@ -1910,9 +2266,9 @@ function createShader(gl, type, source) {
1910
2266
  }
1911
2267
  return shader;
1912
2268
  }
1913
- function createProgram(gl, vertexSource, fragmentSource) {
1914
- const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);
1915
- const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
2269
+ function createProgram$2(gl, vertexSource, fragmentSource) {
2270
+ const vertexShader = createShader$2(gl, gl.VERTEX_SHADER, vertexSource);
2271
+ const fragmentShader = createShader$2(gl, gl.FRAGMENT_SHADER, fragmentSource);
1916
2272
  const program = gl.createProgram();
1917
2273
  if (!program) throw new Error("Failed to create WebGL program.");
1918
2274
  gl.attachShader(program, vertexShader);
@@ -1925,15 +2281,15 @@ function createProgram(gl, vertexSource, fragmentSource) {
1925
2281
  }
1926
2282
  return program;
1927
2283
  }
1928
- function getColorStopCount(stops) {
2284
+ function getColorStopCount$2(stops) {
1929
2285
  return stops.filter((stop) => stop.type === "color-stop").length;
1930
2286
  }
1931
- function getWebGLSampleCount(gradient, maxStops) {
1932
- const colorStopCount = getColorStopCount(gradient.stops);
2287
+ function getWebGLSampleCount$2(gradient, maxStops) {
2288
+ const colorStopCount = getColorStopCount$2(gradient.stops);
1933
2289
  const segmentCount = Math.max(1, colorStopCount - 1);
1934
2290
  return Math.max(2, Math.floor((maxStops - 1) / segmentCount));
1935
2291
  }
1936
- function getColorAtPosition(stops, position) {
2292
+ function getColorAtPosition$2(stops, position) {
1937
2293
  const colorStops = stops.filter((stop) => stop.type === "color-stop" && stop.position != null).sort((a, b) => a.position - b.position);
1938
2294
  if (colorStops.length === 0) throw new Error("Cannot sample color from empty gradient stops.");
1939
2295
  if (position <= colorStops[0].position) return colorStops[0].value;
@@ -1950,7 +2306,7 @@ function getColorAtPosition(stops, position) {
1950
2306
  }
1951
2307
  return lastStop.value;
1952
2308
  }
1953
- function fitStopsToWebGLLimit(stops, maxStops) {
2309
+ function fitStopsToWebGLLimit$2(stops, maxStops) {
1954
2310
  const colorStops = stops.filter((stop) => stop.type === "color-stop" && stop.position != null).sort((a, b) => a.position - b.position);
1955
2311
  if (colorStops.length <= maxStops) return colorStops;
1956
2312
  const sampledStops = [];
@@ -1958,7 +2314,7 @@ function fitStopsToWebGLLimit(stops, maxStops) {
1958
2314
  const position = index / (maxStops - 1);
1959
2315
  sampledStops.push({
1960
2316
  type: "color-stop",
1961
- value: getColorAtPosition(colorStops, position),
2317
+ value: getColorAtPosition$2(colorStops, position),
1962
2318
  position
1963
2319
  });
1964
2320
  }
@@ -1975,7 +2331,7 @@ var ModuleTransformerLinearGradientToCanvasWebGL = class {
1975
2331
  canvas.width = width;
1976
2332
  canvas.height = height;
1977
2333
  gl.viewport(0, 0, width, height);
1978
- const program = createProgram(gl, `
2334
+ const program = createProgram$2(gl, `
1979
2335
  attribute vec2 a_position;
1980
2336
  varying vec2 v_uv;
1981
2337
 
@@ -1991,13 +2347,13 @@ var ModuleTransformerLinearGradientToCanvasWebGL = class {
1991
2347
  uniform vec2 u_start;
1992
2348
  uniform vec2 u_end;
1993
2349
  uniform int u_stopCount;
1994
- uniform float u_positions[${MAX_STOPS}];
1995
- uniform vec4 u_colors[${MAX_STOPS}];
2350
+ uniform float u_positions[${MAX_STOPS$2}];
2351
+ uniform vec4 u_colors[${MAX_STOPS$2}];
1996
2352
 
1997
2353
  vec4 getGradientColor(float t) {
1998
2354
  vec4 result = u_colors[0];
1999
2355
 
2000
- for (int i = 0; i < ${MAX_STOPS - 1}; i++) {
2356
+ for (int i = 0; i < ${MAX_STOPS$2 - 1}; i++) {
2001
2357
  if (i >= u_stopCount - 1) {
2002
2358
  break;
2003
2359
  }
@@ -2062,7 +2418,7 @@ var ModuleTransformerLinearGradientToCanvasWebGL = class {
2062
2418
  let startY = centerY - dirY * lineLength / 2;
2063
2419
  let endX = centerX + dirX * lineLength / 2;
2064
2420
  let endY = centerY + dirY * lineLength / 2;
2065
- const { min, max, stops } = getStopRange(resolveRenderableLinearGradientStops(gradient, getWebGLSampleCount(gradient, MAX_STOPS)));
2421
+ const { min, max, stops } = getStopRange(resolveRenderableGradientStops(gradient, getWebGLSampleCount$2(gradient, MAX_STOPS$2)));
2066
2422
  let normalizedStops = stops;
2067
2423
  if (min < 0 || max > 1) {
2068
2424
  const vx = endX - startX;
@@ -2073,17 +2429,17 @@ var ModuleTransformerLinearGradientToCanvasWebGL = class {
2073
2429
  startY = baseStartY + vy * min;
2074
2430
  endX = baseStartX + vx * max;
2075
2431
  endY = baseStartY + vy * max;
2076
- normalizedStops = normalizeStops(stops, min, max);
2432
+ normalizedStops = normalizeStops$1(stops, min, max);
2077
2433
  }
2078
2434
  const startU = startX / width;
2079
2435
  const startV = 1 - startY / height;
2080
2436
  const endU = endX / width;
2081
2437
  const endV = 1 - endY / height;
2082
- const limitedStops = fitStopsToWebGLLimit(normalizedStops, MAX_STOPS);
2083
- const positions = new Float32Array(MAX_STOPS);
2084
- const colors = new Float32Array(MAX_STOPS * 4);
2438
+ const limitedStops = fitStopsToWebGLLimit$2(normalizedStops, MAX_STOPS$2);
2439
+ const positions = new Float32Array(MAX_STOPS$2);
2440
+ const colors = new Float32Array(MAX_STOPS$2 * 4);
2085
2441
  limitedStops.forEach((stop, index) => {
2086
- const color = toWebGLColor(stop.value);
2442
+ const color = toWebGLColor$2(stop.value);
2087
2443
  positions[index] = stop.position;
2088
2444
  colors[index * 4 + 0] = color[0];
2089
2445
  colors[index * 4 + 1] = color[1];
@@ -2102,6 +2458,602 @@ var ModuleTransformerLinearGradientToCanvasWebGL = class {
2102
2458
  }
2103
2459
  };
2104
2460
  //#endregion
2461
+ //#region src/gradient-transformer/modules/webgl/ModuleTransformerConicGradientToWebgl.ts
2462
+ const toRgb$1 = converter("rgb");
2463
+ const MAX_STOPS$1 = 128;
2464
+ const TWO_PI = Math.PI * 2;
2465
+ function toWebGLColor$1(input) {
2466
+ const color = toRgb$1(input);
2467
+ if (!color) throw new Error(`Failed to convert color: ${input}`);
2468
+ return [
2469
+ color.r ?? 0,
2470
+ color.g ?? 0,
2471
+ color.b ?? 0,
2472
+ color.alpha ?? 1
2473
+ ];
2474
+ }
2475
+ function createShader$1(gl, type, source) {
2476
+ const shader = gl.createShader(type);
2477
+ if (!shader) throw new Error("Failed to create WebGL shader.");
2478
+ gl.shaderSource(shader, source);
2479
+ gl.compileShader(shader);
2480
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
2481
+ const error = gl.getShaderInfoLog(shader);
2482
+ gl.deleteShader(shader);
2483
+ throw new Error(`WebGL shader compile error: ${error}`);
2484
+ }
2485
+ return shader;
2486
+ }
2487
+ function createProgram$1(gl, vertexSource, fragmentSource) {
2488
+ const vertexShader = createShader$1(gl, gl.VERTEX_SHADER, vertexSource);
2489
+ const fragmentShader = createShader$1(gl, gl.FRAGMENT_SHADER, fragmentSource);
2490
+ const program = gl.createProgram();
2491
+ if (!program) throw new Error("Failed to create WebGL program.");
2492
+ gl.attachShader(program, vertexShader);
2493
+ gl.attachShader(program, fragmentShader);
2494
+ gl.linkProgram(program);
2495
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
2496
+ const error = gl.getProgramInfoLog(program);
2497
+ gl.deleteProgram(program);
2498
+ throw new Error(`WebGL program link error: ${error}`);
2499
+ }
2500
+ return program;
2501
+ }
2502
+ function getColorStopCount$1(stops) {
2503
+ return stops.filter((stop) => stop.type === "color-stop").length;
2504
+ }
2505
+ function getWebGLSampleCount$1(gradient, maxStops) {
2506
+ const colorStopCount = getColorStopCount$1(gradient.stops);
2507
+ const segmentCount = Math.max(1, colorStopCount - 1);
2508
+ return Math.max(2, Math.floor((maxStops - 1) / segmentCount));
2509
+ }
2510
+ function getColorAtPosition$1(stops, position) {
2511
+ const colorStops = stops.filter((stop) => stop.type === "color-stop" && stop.position != null).sort((a, b) => a.position - b.position);
2512
+ if (colorStops.length === 0) throw new Error("Cannot sample color from empty gradient stops.");
2513
+ if (position <= colorStops[0].position) return colorStops[0].value;
2514
+ const lastStop = colorStops[colorStops.length - 1];
2515
+ if (position >= lastStop.position) return lastStop.value;
2516
+ for (let index = 0; index < colorStops.length - 1; index += 1) {
2517
+ const current = colorStops[index];
2518
+ const next = colorStops[index + 1];
2519
+ if (position >= current.position && position <= next.position) {
2520
+ const range = next.position - current.position || 1;
2521
+ const localT = (position - current.position) / range;
2522
+ return formatRgb(interpolate([current.value, next.value], "rgb")(localT));
2523
+ }
2524
+ }
2525
+ return lastStop.value;
2526
+ }
2527
+ function fitStopsToWebGLLimit$1(stops, maxStops) {
2528
+ const colorStops = stops.filter((stop) => stop.type === "color-stop" && stop.position != null).sort((a, b) => a.position - b.position);
2529
+ if (colorStops.length <= maxStops) return colorStops;
2530
+ const sampledStops = [];
2531
+ for (let index = 0; index < maxStops; index += 1) {
2532
+ const position = index / (maxStops - 1);
2533
+ sampledStops.push({
2534
+ type: "color-stop",
2535
+ value: getColorAtPosition$1(colorStops, position),
2536
+ position
2537
+ });
2538
+ }
2539
+ return sampledStops;
2540
+ }
2541
+ function resolveLengthPercentage(value, reference) {
2542
+ if (value.kind === "percent") return value.value / 100 * reference;
2543
+ if (value.kind === "length") {
2544
+ if (value.unit === "px") return value.value;
2545
+ throw new Error(`Unsupported gradient length unit for WebGL conic gradient: ${value.unit}`);
2546
+ }
2547
+ return value;
2548
+ }
2549
+ function resolveAngleToRadians(angle) {
2550
+ if (angle.unit === "rad") return angle.value;
2551
+ if (angle.unit === "deg") return angle.value / 360 * TWO_PI;
2552
+ if (angle.unit === "turn") return angle.value * TWO_PI;
2553
+ if (angle.unit === "grad") return angle.value / 400 * TWO_PI;
2554
+ return angle.unit;
2555
+ }
2556
+ function resolveKeywordPositionX$1(x, width) {
2557
+ if (x === "left") return 0;
2558
+ if (x === "center") return width / 2;
2559
+ if (x === "right") return width;
2560
+ return width / 2;
2561
+ }
2562
+ function resolveKeywordPositionY$1(y, height) {
2563
+ if (y === "top") return 0;
2564
+ if (y === "center") return height / 2;
2565
+ if (y === "bottom") return height;
2566
+ return height / 2;
2567
+ }
2568
+ function resolveConicCenter(position, width, height) {
2569
+ if (position.kind === "keywords") return {
2570
+ x: resolveKeywordPositionX$1(position.x, width),
2571
+ y: resolveKeywordPositionY$1(position.y, height)
2572
+ };
2573
+ if (position.kind === "values") return {
2574
+ x: resolveLengthPercentage(position.x, width),
2575
+ y: resolveLengthPercentage(position.y, height)
2576
+ };
2577
+ return {
2578
+ x: width / 2,
2579
+ y: height / 2
2580
+ };
2581
+ }
2582
+ var ModuleTransformerConicGradientToCanvasWebGL = class {
2583
+ target = "canvas-webgl";
2584
+ gradientType = "conic-gradient";
2585
+ to(input) {
2586
+ const gradient = input;
2587
+ return { draw: (canvas, width, height) => {
2588
+ const gl = canvas.getContext("webgl");
2589
+ if (!gl) throw new Error("WebGL is not supported.");
2590
+ canvas.width = width;
2591
+ canvas.height = height;
2592
+ gl.viewport(0, 0, width, height);
2593
+ const program = createProgram$1(gl, `
2594
+ attribute vec2 a_position;
2595
+ varying vec2 v_uv;
2596
+
2597
+ void main() {
2598
+ v_uv = a_position * 0.5 + 0.5;
2599
+ gl_Position = vec4(a_position, 0.0, 1.0);
2600
+ }
2601
+ `, `
2602
+ precision mediump float;
2603
+
2604
+ const float PI = 3.141592653589793;
2605
+ const float TWO_PI = 6.283185307179586;
2606
+
2607
+ varying vec2 v_uv;
2608
+
2609
+ uniform vec2 u_center;
2610
+ uniform float u_startAngle;
2611
+ uniform int u_stopCount;
2612
+ uniform float u_positions[${MAX_STOPS$1}];
2613
+ uniform vec4 u_colors[${MAX_STOPS$1}];
2614
+
2615
+ vec4 getGradientColor(float t) {
2616
+ vec4 result = u_colors[0];
2617
+
2618
+ for (int i = 0; i < ${MAX_STOPS$1 - 1}; i++) {
2619
+ if (i >= u_stopCount - 1) {
2620
+ break;
2621
+ }
2622
+
2623
+ float currentPosition = u_positions[i];
2624
+ float nextPosition = u_positions[i + 1];
2625
+
2626
+ if (t <= currentPosition) {
2627
+ return u_colors[i];
2628
+ }
2629
+
2630
+ if (t >= currentPosition && t <= nextPosition) {
2631
+ float localT = (t - currentPosition) / max(nextPosition - currentPosition, 0.00001);
2632
+ return mix(u_colors[i], u_colors[i + 1], localT);
2633
+ }
2634
+
2635
+ result = u_colors[i + 1];
2636
+ }
2637
+
2638
+ return result;
2639
+ }
2640
+
2641
+ void main() {
2642
+ vec2 delta = v_uv - u_center;
2643
+
2644
+ float angle = atan(delta.y, delta.x);
2645
+ float cssAngle = mod((PI * 0.5) - angle + TWO_PI, TWO_PI);
2646
+
2647
+ float t = mod(cssAngle - u_startAngle + TWO_PI, TWO_PI) / TWO_PI;
2648
+
2649
+ gl_FragColor = getGradientColor(t);
2650
+ }
2651
+ `);
2652
+ gl.useProgram(program);
2653
+ const positionBuffer = gl.createBuffer();
2654
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
2655
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
2656
+ -1,
2657
+ -1,
2658
+ 1,
2659
+ -1,
2660
+ -1,
2661
+ 1,
2662
+ -1,
2663
+ 1,
2664
+ 1,
2665
+ -1,
2666
+ 1,
2667
+ 1
2668
+ ]), gl.STATIC_DRAW);
2669
+ const positionLocation = gl.getAttribLocation(program, "a_position");
2670
+ gl.enableVertexAttribArray(positionLocation);
2671
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
2672
+ const center = resolveConicCenter(gradient.config.position, width, height);
2673
+ const limitedStops = fitStopsToWebGLLimit$1(resolveRenderableGradientStops(gradient, getWebGLSampleCount$1(gradient, MAX_STOPS$1)), MAX_STOPS$1);
2674
+ const positions = new Float32Array(MAX_STOPS$1);
2675
+ const colors = new Float32Array(MAX_STOPS$1 * 4);
2676
+ limitedStops.forEach((stop, index) => {
2677
+ const color = toWebGLColor$1(stop.value);
2678
+ positions[index] = stop.position;
2679
+ colors[index * 4 + 0] = color[0];
2680
+ colors[index * 4 + 1] = color[1];
2681
+ colors[index * 4 + 2] = color[2];
2682
+ colors[index * 4 + 3] = color[3];
2683
+ });
2684
+ gl.uniform2f(gl.getUniformLocation(program, "u_center"), center.x / width, 1 - center.y / height);
2685
+ gl.uniform1f(gl.getUniformLocation(program, "u_startAngle"), resolveAngleToRadians(gradient.config.from));
2686
+ gl.uniform1i(gl.getUniformLocation(program, "u_stopCount"), limitedStops.length);
2687
+ gl.uniform1fv(gl.getUniformLocation(program, "u_positions"), positions);
2688
+ gl.uniform4fv(gl.getUniformLocation(program, "u_colors"), colors);
2689
+ gl.clearColor(0, 0, 0, 0);
2690
+ gl.clear(gl.COLOR_BUFFER_BIT);
2691
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
2692
+ } };
2693
+ }
2694
+ };
2695
+ //#endregion
2696
+ //#region src/gradient-transformer/modules/webgl/ModuleTransformerRadialGradientToWebgl.ts
2697
+ const toRgb = converter("rgb");
2698
+ const MAX_STOPS = 128;
2699
+ const MAX_REPEATING_RADIAL_T = 16;
2700
+ function toWebGLColor(input) {
2701
+ const color = toRgb(input);
2702
+ if (!color) throw new Error(`Failed to convert color: ${input}`);
2703
+ return [
2704
+ color.r ?? 0,
2705
+ color.g ?? 0,
2706
+ color.b ?? 0,
2707
+ color.alpha ?? 1
2708
+ ];
2709
+ }
2710
+ function createShader(gl, type, source) {
2711
+ const shader = gl.createShader(type);
2712
+ if (!shader) throw new Error("Failed to create WebGL shader.");
2713
+ gl.shaderSource(shader, source);
2714
+ gl.compileShader(shader);
2715
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
2716
+ const error = gl.getShaderInfoLog(shader);
2717
+ gl.deleteShader(shader);
2718
+ throw new Error(`WebGL shader compile error: ${error}`);
2719
+ }
2720
+ return shader;
2721
+ }
2722
+ function createProgram(gl, vertexSource, fragmentSource) {
2723
+ const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);
2724
+ const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
2725
+ const program = gl.createProgram();
2726
+ if (!program) throw new Error("Failed to create WebGL program.");
2727
+ gl.attachShader(program, vertexShader);
2728
+ gl.attachShader(program, fragmentShader);
2729
+ gl.linkProgram(program);
2730
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
2731
+ const error = gl.getProgramInfoLog(program);
2732
+ gl.deleteProgram(program);
2733
+ throw new Error(`WebGL program link error: ${error}`);
2734
+ }
2735
+ return program;
2736
+ }
2737
+ function getColorStopCount(stops) {
2738
+ return stops.filter((stop) => stop.type === "color-stop").length;
2739
+ }
2740
+ function getWebGLSampleCount(gradient, maxStops) {
2741
+ const colorStopCount = getColorStopCount(gradient.stops);
2742
+ const segmentCount = Math.max(1, colorStopCount - 1);
2743
+ return Math.max(2, Math.floor((maxStops - 1) / segmentCount));
2744
+ }
2745
+ function getColorAtPosition(stops, position) {
2746
+ const colorStops = stops.filter((stop) => stop.type === "color-stop" && stop.position != null).sort((a, b) => a.position - b.position);
2747
+ if (colorStops.length === 0) throw new Error("Cannot sample color from empty gradient stops.");
2748
+ if (position <= colorStops[0].position) return colorStops[0].value;
2749
+ const lastStop = colorStops[colorStops.length - 1];
2750
+ if (position >= lastStop.position) return lastStop.value;
2751
+ for (let index = 0; index < colorStops.length - 1; index += 1) {
2752
+ const current = colorStops[index];
2753
+ const next = colorStops[index + 1];
2754
+ if (position >= current.position && position <= next.position) {
2755
+ const range = next.position - current.position || 1;
2756
+ const localT = (position - current.position) / range;
2757
+ return formatRgb(interpolate([current.value, next.value], "rgb")(localT));
2758
+ }
2759
+ }
2760
+ return lastStop.value;
2761
+ }
2762
+ function fitStopsToWebGLLimit(stops, maxStops) {
2763
+ const colorStops = stops.filter((stop) => stop.type === "color-stop" && stop.position != null).sort((a, b) => a.position - b.position);
2764
+ if (colorStops.length <= maxStops) return colorStops;
2765
+ const sampledStops = [];
2766
+ for (let index = 0; index < maxStops; index += 1) {
2767
+ const position = index / (maxStops - 1);
2768
+ sampledStops.push({
2769
+ type: "color-stop",
2770
+ value: getColorAtPosition(colorStops, position),
2771
+ position
2772
+ });
2773
+ }
2774
+ return sampledStops;
2775
+ }
2776
+ function parseLengthPercentage(value, reference) {
2777
+ if (value.kind === "percent") return value.value / 100 * reference;
2778
+ if (value.kind === "length") {
2779
+ if (value.unit === "px") return value.value;
2780
+ throw new Error(`Unsupported gradient length unit for WebGL radial gradient: ${value.unit}`);
2781
+ }
2782
+ return value;
2783
+ }
2784
+ function resolveKeywordPositionX(x, width) {
2785
+ if (x === "left") return 0;
2786
+ if (x === "center") return width / 2;
2787
+ if (x === "right") return width;
2788
+ return width / 2;
2789
+ }
2790
+ function resolveKeywordPositionY(y, height) {
2791
+ if (y === "top") return 0;
2792
+ if (y === "center") return height / 2;
2793
+ if (y === "bottom") return height;
2794
+ return height / 2;
2795
+ }
2796
+ function resolveRadialCenter(position, width, height) {
2797
+ if (position.kind === "keywords") return {
2798
+ x: resolveKeywordPositionX(position.x, width),
2799
+ y: resolveKeywordPositionY(position.y, height)
2800
+ };
2801
+ if (position.kind === "values") return {
2802
+ x: parseLengthPercentage(position.x, width),
2803
+ y: parseLengthPercentage(position.y, height)
2804
+ };
2805
+ return {
2806
+ x: width / 2,
2807
+ y: height / 2
2808
+ };
2809
+ }
2810
+ function getDistanceToSide(center, width, height, side) {
2811
+ if (side === "left") return center.x;
2812
+ if (side === "right") return width - center.x;
2813
+ if (side === "top") return center.y;
2814
+ return height - center.y;
2815
+ }
2816
+ function getDistanceToCorner(center, corner) {
2817
+ const dx = corner.x - center.x;
2818
+ const dy = corner.y - center.y;
2819
+ return Math.sqrt(dx * dx + dy * dy);
2820
+ }
2821
+ function normalizeStops(stops, min, max) {
2822
+ const range = max - min || 1;
2823
+ return stops.filter((stop) => stop.type === "color-stop" && stop.position != null).map((stop) => ({
2824
+ ...stop,
2825
+ position: (stop.position - min) / range
2826
+ }));
2827
+ }
2828
+ function getCornerDeltas(center, width, height) {
2829
+ return [
2830
+ {
2831
+ dx: -center.x,
2832
+ dy: -center.y
2833
+ },
2834
+ {
2835
+ dx: width - center.x,
2836
+ dy: -center.y
2837
+ },
2838
+ {
2839
+ dx: -center.x,
2840
+ dy: height - center.y
2841
+ },
2842
+ {
2843
+ dx: width - center.x,
2844
+ dy: height - center.y
2845
+ }
2846
+ ];
2847
+ }
2848
+ function scaleEllipseRadiiToCorner(radiusX, radiusY, dx, dy) {
2849
+ const safeRadiusX = Math.max(radiusX, 1e-4);
2850
+ const safeRadiusY = Math.max(radiusY, 1e-4);
2851
+ const scale = Math.sqrt(dx * dx / (safeRadiusX * safeRadiusX) + dy * dy / (safeRadiusY * safeRadiusY));
2852
+ return {
2853
+ x: safeRadiusX * scale,
2854
+ y: safeRadiusY * scale
2855
+ };
2856
+ }
2857
+ function resolveRadialRadii(size, shape, center, width, height) {
2858
+ if (size.kind === "explicit") {
2859
+ const radiusX = parseLengthPercentage(size.x, width);
2860
+ const radiusY = size.y ? parseLengthPercentage(size.y, height) : radiusX;
2861
+ return {
2862
+ x: Math.max(radiusX, 1e-4),
2863
+ y: Math.max(shape === "circle" ? radiusX : radiusY, 1e-4)
2864
+ };
2865
+ }
2866
+ const left = getDistanceToSide(center, width, height, "left");
2867
+ const right = getDistanceToSide(center, width, height, "right");
2868
+ const top = getDistanceToSide(center, width, height, "top");
2869
+ const bottom = getDistanceToSide(center, width, height, "bottom");
2870
+ if (shape === "circle") {
2871
+ const cornerDistances = [
2872
+ {
2873
+ x: 0,
2874
+ y: 0
2875
+ },
2876
+ {
2877
+ x: width,
2878
+ y: 0
2879
+ },
2880
+ {
2881
+ x: 0,
2882
+ y: height
2883
+ },
2884
+ {
2885
+ x: width,
2886
+ y: height
2887
+ }
2888
+ ].map((corner) => getDistanceToCorner(center, corner));
2889
+ if (size.value === "closest-side") {
2890
+ const radius = Math.max(Math.min(left, right, top, bottom), 1e-4);
2891
+ return {
2892
+ x: radius,
2893
+ y: radius
2894
+ };
2895
+ }
2896
+ if (size.value === "farthest-side") {
2897
+ const radius = Math.max(Math.max(left, right, top, bottom), 1e-4);
2898
+ return {
2899
+ x: radius,
2900
+ y: radius
2901
+ };
2902
+ }
2903
+ if (size.value === "closest-corner") {
2904
+ const radius = Math.max(Math.min(...cornerDistances), 1e-4);
2905
+ return {
2906
+ x: radius,
2907
+ y: radius
2908
+ };
2909
+ }
2910
+ const radius = Math.max(Math.max(...cornerDistances), 1e-4);
2911
+ return {
2912
+ x: radius,
2913
+ y: radius
2914
+ };
2915
+ }
2916
+ const closestSideRadiusX = Math.min(left, right);
2917
+ const closestSideRadiusY = Math.min(top, bottom);
2918
+ const farthestSideRadiusX = Math.max(left, right);
2919
+ const farthestSideRadiusY = Math.max(top, bottom);
2920
+ if (size.value === "closest-side") return {
2921
+ x: Math.max(closestSideRadiusX, 1e-4),
2922
+ y: Math.max(closestSideRadiusY, 1e-4)
2923
+ };
2924
+ if (size.value === "farthest-side") return {
2925
+ x: Math.max(farthestSideRadiusX, 1e-4),
2926
+ y: Math.max(farthestSideRadiusY, 1e-4)
2927
+ };
2928
+ const corners = getCornerDeltas(center, width, height);
2929
+ if (size.value === "closest-corner") return corners.map((corner) => scaleEllipseRadiiToCorner(closestSideRadiusX, closestSideRadiusY, corner.dx, corner.dy)).reduce((closest, current) => {
2930
+ const closestArea = closest.x * closest.y;
2931
+ return current.x * current.y < closestArea ? current : closest;
2932
+ });
2933
+ return corners.map((corner) => scaleEllipseRadiiToCorner(farthestSideRadiusX, farthestSideRadiusY, corner.dx, corner.dy)).reduce((farthest, current) => {
2934
+ const farthestArea = farthest.x * farthest.y;
2935
+ return current.x * current.y > farthestArea ? current : farthest;
2936
+ });
2937
+ }
2938
+ var ModuleTransformerRadialGradientToCanvasWebGL = class {
2939
+ target = "canvas-webgl";
2940
+ gradientType = "radial-gradient";
2941
+ to(input) {
2942
+ const gradient = input;
2943
+ return { draw: (canvas, width, height) => {
2944
+ const gl = canvas.getContext("webgl");
2945
+ if (!gl) throw new Error("WebGL is not supported.");
2946
+ canvas.width = width;
2947
+ canvas.height = height;
2948
+ gl.viewport(0, 0, width, height);
2949
+ const program = createProgram(gl, `
2950
+ attribute vec2 a_position;
2951
+ varying vec2 v_uv;
2952
+
2953
+ void main() {
2954
+ v_uv = a_position * 0.5 + 0.5;
2955
+ gl_Position = vec4(a_position, 0.0, 1.0);
2956
+ }
2957
+ `, `
2958
+ precision mediump float;
2959
+
2960
+ varying vec2 v_uv;
2961
+
2962
+ uniform vec2 u_center;
2963
+ uniform vec2 u_radius;
2964
+ uniform int u_stopCount;
2965
+ uniform float u_positions[${MAX_STOPS}];
2966
+ uniform vec4 u_colors[${MAX_STOPS}];
2967
+ uniform float u_tMax;
2968
+
2969
+ vec4 getGradientColor(float t) {
2970
+ vec4 result = u_colors[0];
2971
+
2972
+ for (int i = 0; i < ${MAX_STOPS - 1}; i++) {
2973
+ if (i >= u_stopCount - 1) {
2974
+ break;
2975
+ }
2976
+
2977
+ float currentPosition = u_positions[i];
2978
+ float nextPosition = u_positions[i + 1];
2979
+
2980
+ if (t <= currentPosition) {
2981
+ return u_colors[i];
2982
+ }
2983
+
2984
+ if (t >= currentPosition && t <= nextPosition) {
2985
+ float localT = (t - currentPosition) / max(nextPosition - currentPosition, 0.00001);
2986
+ return mix(u_colors[i], u_colors[i + 1], localT);
2987
+ }
2988
+
2989
+ result = u_colors[i + 1];
2990
+ }
2991
+
2992
+ return result;
2993
+ }
2994
+
2995
+ void main() {
2996
+ vec2 delta = v_uv - u_center;
2997
+ vec2 normalized = delta / max(u_radius, vec2(0.00001));
2998
+ float t = length(normalized);
2999
+
3000
+ t = clamp(t, 0.0, u_tMax);
3001
+ t = t / max(u_tMax, 0.00001);
3002
+
3003
+ gl_FragColor = getGradientColor(t);
3004
+ }
3005
+ `);
3006
+ gl.useProgram(program);
3007
+ const positionBuffer = gl.createBuffer();
3008
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
3009
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
3010
+ -1,
3011
+ -1,
3012
+ 1,
3013
+ -1,
3014
+ -1,
3015
+ 1,
3016
+ -1,
3017
+ 1,
3018
+ 1,
3019
+ -1,
3020
+ 1,
3021
+ 1
3022
+ ]), gl.STATIC_DRAW);
3023
+ const positionLocation = gl.getAttribLocation(program, "a_position");
3024
+ gl.enableVertexAttribArray(positionLocation);
3025
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
3026
+ const center = resolveRadialCenter(gradient.config.position, width, height);
3027
+ const radius = resolveRadialRadii(gradient.config.size, gradient.config.shape, center, width, height);
3028
+ const maxVisibleT = getMaxVisibleRadialT(center, radius, width, height);
3029
+ const baseStops = resolveRenderableGradientStops(gradient, getWebGLSampleCount(gradient, MAX_STOPS));
3030
+ const repeatMaxT = Math.min(maxVisibleT, MAX_REPEATING_RADIAL_T);
3031
+ const maxT = gradient.isRepeating ? repeatMaxT : 1;
3032
+ const renderStops = gradient.isRepeating ? expandRepeatingStopsTo(baseStops, 0, repeatMaxT) : baseStops;
3033
+ const limitedStops = fitStopsToWebGLLimit(gradient.isRepeating ? normalizeStops(renderStops, 0, repeatMaxT) : renderStops, MAX_STOPS);
3034
+ const positions = new Float32Array(MAX_STOPS);
3035
+ const colors = new Float32Array(MAX_STOPS * 4);
3036
+ limitedStops.forEach((stop, index) => {
3037
+ const color = toWebGLColor(stop.value);
3038
+ positions[index] = stop.position;
3039
+ colors[index * 4 + 0] = color[0];
3040
+ colors[index * 4 + 1] = color[1];
3041
+ colors[index * 4 + 2] = color[2];
3042
+ colors[index * 4 + 3] = color[3];
3043
+ });
3044
+ gl.uniform2f(gl.getUniformLocation(program, "u_center"), center.x / width, 1 - center.y / height);
3045
+ gl.uniform2f(gl.getUniformLocation(program, "u_radius"), radius.x / width, radius.y / height);
3046
+ gl.uniform1f(gl.getUniformLocation(program, "u_tMax"), maxT);
3047
+ gl.uniform1i(gl.getUniformLocation(program, "u_stopCount"), limitedStops.length);
3048
+ gl.uniform1fv(gl.getUniformLocation(program, "u_positions"), positions);
3049
+ gl.uniform4fv(gl.getUniformLocation(program, "u_colors"), colors);
3050
+ gl.clearColor(0, 0, 0, 0);
3051
+ gl.clear(gl.COLOR_BUFFER_BIT);
3052
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
3053
+ } };
3054
+ }
3055
+ };
3056
+ //#endregion
2105
3057
  //#region src/gradient-transformer/GradientTransformer.ts
2106
3058
  var GradientTransformer = class {
2107
3059
  static _modules = /* @__PURE__ */ new Map();
@@ -2139,6 +3091,8 @@ var GradientTransformer = class {
2139
3091
  this.add(new ModuleTransformerRadialGradientToCanvas());
2140
3092
  this.add(new ModuleTransformerConicGradientToCanvas());
2141
3093
  this.add(new ModuleTransformerLinearGradientToCanvasWebGL());
3094
+ this.add(new ModuleTransformerRadialGradientToCanvasWebGL());
3095
+ this.add(new ModuleTransformerConicGradientToCanvasWebGL());
2142
3096
  }
2143
3097
  static _getKey(target, gradientType) {
2144
3098
  return `${target}:${gradientType}`;
@@ -2200,4 +3154,4 @@ function transformFrom(target, gradientType, input) {
2200
3154
  return GradientTransformer.from(target, gradientType, input);
2201
3155
  }
2202
3156
  //#endregion
2203
- export { ConicGradient, GRADIENT_COLOR_SPACE, GRADIENT_HUE_INTERPOLATIONS, GRADIENT_POLAR_COLOR_SPACES, GradientBase, GradientFactory, GradientTransformer, LinearGradient, ModuleTransformerConicGradientToCanvas, ModuleTransformerConicGradientToCss, ModuleTransformerLinearGradientToCanvas, ModuleTransformerLinearGradientToCanvasWebGL, ModuleTransformerLinearGradientToCss, ModuleTransformerRadialGradientToCanvas, ModuleTransformerRadialGradientToCss, PatternTokenKind, RadialGradient, angleValueFromString, ceilTo, clamp, degToRad, floorTo, format, fromPercent, gradToRad, isAngle, isAngleUnit, isColorHint, isColorStop, isConfig, isGradient, isGradientColorSpace, isGradientHueInterpolation, isGradientPolarColorSpace, isPatternSyntaxValid, isPatternValid, isValid, matchExpression, normalizeAngleDeg, normalizeAngleRad, parse, parseStringToAbi, radToDeg, roundTo, splitTopLevelByWhitespace, toPercent, tokenizePattern, transformFrom, transformTo, truncTo, turnToRad, validate, validatePattern, validatePatternSemantic, validatePatternStructure, validatePatternSyntax };
3157
+ export { ConicGradient, GRADIENT_COLOR_SPACE, GRADIENT_HUE_INTERPOLATIONS, GRADIENT_POLAR_COLOR_SPACES, GradientBase, GradientFactory, GradientTransformer, LinearGradient, ModuleTransformerConicGradientToCanvas, ModuleTransformerConicGradientToCanvasWebGL, ModuleTransformerConicGradientToCss, ModuleTransformerLinearGradientToCanvas, ModuleTransformerLinearGradientToCanvasWebGL, ModuleTransformerLinearGradientToCss, ModuleTransformerRadialGradientToCanvas, ModuleTransformerRadialGradientToCanvasWebGL, ModuleTransformerRadialGradientToCss, PatternTokenKind, RadialGradient, angleValueFromString, ceilTo, clamp, degToRad, floorTo, format, fromPercent, gradToRad, isAngle, isAngleUnit, isColorHint, isColorStop, isConfig, isGradient, isGradientColorSpace, isGradientHueInterpolation, isGradientPolarColorSpace, isPatternSyntaxValid, isPatternValid, isValid, matchExpression, normalizeAngleDeg, normalizeAngleRad, parse, parseStringToAbi, radToDeg, roundTo, splitTopLevelByWhitespace, toPercent, tokenizePattern, transformFrom, transformTo, truncTo, turnToRad, validate, validatePattern, validatePatternSemantic, validatePatternStructure, validatePatternSyntax };