@clypra/engine 1.1.2 → 1.2.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
@@ -817,6 +817,17 @@ function restoreLetterSpacing(ctx, saved) {
817
817
  function getCanvas2DContext2(canvas) {
818
818
  return canvas.getContext("2d");
819
819
  }
820
+ function ctxSupportsFilter(ctx) {
821
+ try {
822
+ const prev = ctx.filter;
823
+ ctx.filter = "blur(4px)";
824
+ const ok = typeof ctx.filter === "string" && ctx.filter.includes("blur");
825
+ ctx.filter = prev;
826
+ return ok;
827
+ } catch {
828
+ return false;
829
+ }
830
+ }
820
831
  function renderTextEffectCore(ctx, cfg) {
821
832
  if (cfg.customRenderer === "InkBrushEngine") {
822
833
  const engine = new InkBrushEngine(cfg);
@@ -1126,19 +1137,31 @@ function renderTextEffectCore(ctx, cfg) {
1126
1137
  const vpy = cHeight / 2 + (bevelVanishingPointY !== void 0 ? bevelVanishingPointY : 80) / 100 * (cHeight / 2);
1127
1138
  const fl = Math.max(100, bevelFocalLength !== void 0 ? bevelFocalLength : 400);
1128
1139
  if (bevelBlur && bevelBlur > 0) {
1129
- ctx.save();
1130
- ctx.filter = `blur(${bevelBlur}px)`;
1131
1140
  const blurColor = bevelBlurColor || bevelShadow || "#000000";
1132
- for (let i = bevelDepth; i > 0; i -= Math.max(1, Math.floor(bevelDepth / 4))) {
1133
- const scale = fl / (fl + i);
1141
+ if (ctxSupportsFilter(ctx)) {
1134
1142
  ctx.save();
1135
- ctx.translate(vpx, vpy);
1136
- ctx.scale(scale, scale);
1137
- ctx.translate(-vpx, -vpy);
1138
- renderLines("fill", blurColor);
1143
+ ctx.filter = `blur(${bevelBlur}px)`;
1144
+ for (let i = bevelDepth; i > 0; i -= Math.max(1, Math.floor(bevelDepth / 4))) {
1145
+ const scale = fl / (fl + i);
1146
+ ctx.save();
1147
+ ctx.translate(vpx, vpy);
1148
+ ctx.scale(scale, scale);
1149
+ ctx.translate(-vpx, -vpy);
1150
+ renderLines("fill", blurColor);
1151
+ ctx.restore();
1152
+ }
1139
1153
  ctx.restore();
1154
+ } else {
1155
+ for (let i = bevelDepth; i > 0; i -= Math.max(1, Math.floor(bevelDepth / 4))) {
1156
+ const scale = fl / (fl + i);
1157
+ ctx.save();
1158
+ ctx.translate(vpx, vpy);
1159
+ ctx.scale(scale, scale);
1160
+ ctx.translate(-vpx, -vpy);
1161
+ renderWithShadowTrick("fill", blurColor, bevelBlur, 0, 0, 100);
1162
+ ctx.restore();
1163
+ }
1140
1164
  }
1141
- ctx.restore();
1142
1165
  }
1143
1166
  ctx.save();
1144
1167
  for (let i = bevelDepth; i > 0; i--) {
@@ -1185,14 +1208,21 @@ function renderTextEffectCore(ctx, cfg) {
1185
1208
  return { dx: i, dy: i };
1186
1209
  };
1187
1210
  if (bevelBlur && bevelBlur > 0) {
1188
- ctx.save();
1189
- ctx.filter = `blur(${bevelBlur}px)`;
1190
1211
  const blurColor = bevelBlurColor || bevelShadow || "#000000";
1191
- for (let i = bevelDepth; i > 0; i -= Math.max(1, Math.floor(bevelDepth / 4))) {
1192
- const { dx, dy } = getDirOffset(i);
1193
- renderLines("fill", blurColor, dx, dy);
1212
+ if (ctxSupportsFilter(ctx)) {
1213
+ ctx.save();
1214
+ ctx.filter = `blur(${bevelBlur}px)`;
1215
+ for (let i = bevelDepth; i > 0; i -= Math.max(1, Math.floor(bevelDepth / 4))) {
1216
+ const { dx, dy } = getDirOffset(i);
1217
+ renderLines("fill", blurColor, dx, dy);
1218
+ }
1219
+ ctx.restore();
1220
+ } else {
1221
+ for (let i = bevelDepth; i > 0; i -= Math.max(1, Math.floor(bevelDepth / 4))) {
1222
+ const { dx, dy } = getDirOffset(i);
1223
+ renderWithShadowTrick("fill", blurColor, bevelBlur, dx, dy, 100);
1224
+ }
1194
1225
  }
1195
- ctx.restore();
1196
1226
  }
1197
1227
  ctx.save();
1198
1228
  for (let i = bevelDepth; i > 0; i--) {
@@ -1246,24 +1276,51 @@ function renderTextEffectCore(ctx, cfg) {
1246
1276
  customStrokeStyle = grad;
1247
1277
  }
1248
1278
  const drawStrokeLayer = (color, width, blurAmount, opacity, position) => {
1249
- ctx.save();
1250
- ctx.globalAlpha = opacity / 100;
1251
- ctx.strokeStyle = color;
1252
- if (blurAmount > 0) {
1279
+ if (blurAmount > 0 && ctxSupportsFilter(ctx)) {
1280
+ ctx.save();
1281
+ ctx.globalAlpha = opacity / 100;
1282
+ ctx.strokeStyle = color;
1253
1283
  ctx.filter = `blur(${blurAmount}px)`;
1284
+ if (position === "outside") {
1285
+ ctx.lineWidth = width * 2;
1286
+ renderLines("stroke");
1287
+ } else if (position === "center") {
1288
+ ctx.lineWidth = width;
1289
+ renderLines("stroke");
1290
+ } else if (position === "inside") {
1291
+ ctx.globalCompositeOperation = "source-atop";
1292
+ ctx.lineWidth = width * 2;
1293
+ renderLines("stroke");
1294
+ }
1295
+ ctx.restore();
1296
+ } else if (blurAmount > 0) {
1297
+ const colorStr = typeof color === "string" ? color : strokeColor;
1298
+ const spread = position === "center" ? width / 2 : width;
1299
+ if (position === "inside") {
1300
+ ctx.save();
1301
+ ctx.globalCompositeOperation = "source-atop";
1302
+ renderWithShadowTrick("stroke", colorStr, blurAmount, 0, 0, opacity, void 0, spread);
1303
+ ctx.restore();
1304
+ } else {
1305
+ renderWithShadowTrick("stroke", colorStr, blurAmount, 0, 0, opacity, void 0, spread);
1306
+ }
1307
+ } else {
1308
+ ctx.save();
1309
+ ctx.globalAlpha = opacity / 100;
1310
+ ctx.strokeStyle = color;
1311
+ if (position === "outside") {
1312
+ ctx.lineWidth = width * 2;
1313
+ renderLines("stroke");
1314
+ } else if (position === "center") {
1315
+ ctx.lineWidth = width;
1316
+ renderLines("stroke");
1317
+ } else if (position === "inside") {
1318
+ ctx.globalCompositeOperation = "source-atop";
1319
+ ctx.lineWidth = width * 2;
1320
+ renderLines("stroke");
1321
+ }
1322
+ ctx.restore();
1254
1323
  }
1255
- if (position === "outside") {
1256
- ctx.lineWidth = width * 2;
1257
- renderLines("stroke");
1258
- } else if (position === "center") {
1259
- ctx.lineWidth = width;
1260
- renderLines("stroke");
1261
- } else if (position === "inside") {
1262
- ctx.globalCompositeOperation = "source-atop";
1263
- ctx.lineWidth = width * 2;
1264
- renderLines("stroke");
1265
- }
1266
- ctx.restore();
1267
1324
  };
1268
1325
  if (sType === "double") {
1269
1326
  const outerWidth = strokeWidth + sWidthSecondary;