@pixodesk/svg-animator-react 1.0.18 → 1.0.19

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.umd.js CHANGED
@@ -2770,8 +2770,9 @@ var PixodeskAnimatorReact = (() => {
2770
2770
  gradientTransform: px.string().optional()
2771
2771
  }));
2772
2772
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
2773
- var PxTextAlongPathEffectSchema = implementsInterface()(px.object({
2774
- href: px.string(),
2773
+ var PxTextPathEffectSchema = implementsInterface()(px.object({
2774
+ path: px.string(),
2775
+ pathOverflow: px.string().optional(),
2775
2776
  lengthAdjust: px.string().optional(),
2776
2777
  method: px.string().optional(),
2777
2778
  spacing: px.string().optional(),
@@ -2790,7 +2791,7 @@ var PixodeskAnimatorReact = (() => {
2790
2791
  isCombinedShape: px.boolean().optional(),
2791
2792
  fillGradient: PxFillGradientEffectSchema.optional(),
2792
2793
  strokeGradient: PxStrokeGradientEffectSchema.optional(),
2793
- textAlongPath: PxTextAlongPathEffectSchema.optional(),
2794
+ textPath: PxTextPathEffectSchema.optional(),
2794
2795
  text: PxTextEffectSchema.optional()
2795
2796
  }));
2796
2797
  function validateNodeEffects(root, opts) {
@@ -3641,97 +3642,6 @@ var PixodeskAnimatorReact = (() => {
3641
3642
  }
3642
3643
  }
3643
3644
  }
3644
- function applyTextAlongPathEffect(node, fx, _ctx) {
3645
- var _a;
3646
- if (!fx) return node;
3647
- const href = typeof fx.href === "string" && !fx.href.startsWith("#") ? "#" + fx.href : fx.href;
3648
- const textPath = {
3649
- type: "textPath",
3650
- href,
3651
- children: (_a = node.children) != null ? _a : []
3652
- };
3653
- if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
3654
- if (fx.method !== void 0) textPath.method = fx.method;
3655
- if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
3656
- applyAnimatableNumber(textPath, "startOffset", fx.startOffset);
3657
- applyAnimatableNumber(textPath, "textLength", fx.textLength);
3658
- node.children = [textPath];
3659
- return node;
3660
- }
3661
- function applyAnimatableNumber(node, attrName, raw) {
3662
- if (raw === void 0 || raw === null) return;
3663
- if (typeof raw === "number") {
3664
- node[attrName] = String(raw);
3665
- return;
3666
- }
3667
- if (typeof raw === "object" && raw !== null) {
3668
- const obj = raw;
3669
- if (Array.isArray(obj.keyframes)) {
3670
- const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
3671
- const animate = __spreadValues({}, prevAnimate || {});
3672
- const block = { keyframes: obj.keyframes };
3673
- if (obj.loop !== void 0) block.loop = obj.loop;
3674
- animate[attrName] = block;
3675
- node.animate = animate;
3676
- return;
3677
- }
3678
- if (typeof obj.value === "number") {
3679
- node[attrName] = String(obj.value);
3680
- return;
3681
- }
3682
- }
3683
- }
3684
- var jsonElementFactory = (type, props, children) => {
3685
- const node = { type };
3686
- for (const k in props) if (props[k] !== void 0) node[k] = props[k];
3687
- const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
3688
- if (arr.length) node.children = arr;
3689
- return node;
3690
- };
3691
- function fmt(v, decimals) {
3692
- return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
3693
- }
3694
- function pack(nums, decimals) {
3695
- let s = "";
3696
- for (let i = 0; i < nums.length; i++) {
3697
- const str2 = fmt(nums[i], decimals);
3698
- if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
3699
- s += str2;
3700
- }
3701
- return s;
3702
- }
3703
- function apply(m, x, y) {
3704
- return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
3705
- }
3706
- var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
3707
- function transformPathData(d, m, decimals = 2) {
3708
- const tokens = [];
3709
- let match;
3710
- TOKEN_RE.lastIndex = 0;
3711
- while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
3712
- let out = "";
3713
- let i = 0;
3714
- const num2 = () => parseFloat(tokens[i++]);
3715
- while (i < tokens.length) {
3716
- const cmd = tokens[i++];
3717
- if (cmd === "M" || cmd === "L") {
3718
- const [x, y] = apply(m, num2(), num2());
3719
- out += cmd + pack([x, y], decimals);
3720
- } else if (cmd === "C") {
3721
- const [x1, y1] = apply(m, num2(), num2());
3722
- const [x2, y2] = apply(m, num2(), num2());
3723
- const [x, y] = apply(m, num2(), num2());
3724
- out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
3725
- } else if (cmd === "Q") {
3726
- const [x1, y1] = apply(m, num2(), num2());
3727
- const [x, y] = apply(m, num2(), num2());
3728
- out += "Q" + pack([x1, y1, x, y], decimals);
3729
- } else if (cmd === "Z" || cmd === "z") {
3730
- out += "Z";
3731
- }
3732
- }
3733
- return out;
3734
- }
3735
3645
  function bezierToSvgPath(path) {
3736
3646
  var _a, _b, _c, _d;
3737
3647
  const v = path.v;
@@ -4273,6 +4183,7 @@ var PixodeskAnimatorReact = (() => {
4273
4183
  };
4274
4184
  return {
4275
4185
  totalLength,
4186
+ closed,
4276
4187
  sampleAtDistance(dist) {
4277
4188
  if (!closed && (dist < 0 || dist > totalLength)) {
4278
4189
  const edge = dist < 0 ? 0 : totalLength;
@@ -4284,6 +4195,167 @@ var PixodeskAnimatorReact = (() => {
4284
4195
  }
4285
4196
  };
4286
4197
  }
4198
+ var EXTEND_MARGIN_FRAC = 0.15;
4199
+ function numRange(v) {
4200
+ if (typeof v === "number") return { min: v, max: v };
4201
+ if (v && typeof v === "object") {
4202
+ const o = v;
4203
+ if (typeof o.value === "number") return { min: o.value, max: o.value };
4204
+ if (Array.isArray(o.keyframes) && o.keyframes.length) {
4205
+ const vals = o.keyframes.map((k) => Number(k.value) || 0);
4206
+ return { min: Math.min(...vals), max: Math.max(...vals) };
4207
+ }
4208
+ }
4209
+ return { min: 0, max: 0 };
4210
+ }
4211
+ function estimateTextAdvance(node) {
4212
+ let chars = 0, maxFont = 16;
4213
+ const walk = (el) => {
4214
+ var _a, _b;
4215
+ const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
4216
+ if (fs) maxFont = Math.max(maxFont, fs);
4217
+ const t = (_b = el.text) != null ? _b : el.textContent;
4218
+ if (typeof t === "string") chars += t.length;
4219
+ if (el.children) for (const c of el.children) walk(c);
4220
+ };
4221
+ walk(node);
4222
+ return chars * maxFont;
4223
+ }
4224
+ var r3 = (n) => Math.round(n * 1e3) / 1e3;
4225
+ function shiftAnimatable(v, by) {
4226
+ if (!by || v === void 0 || v === null) return v;
4227
+ if (typeof v === "number") return v + by;
4228
+ const o = v;
4229
+ if (typeof o.value === "number") return __spreadProps(__spreadValues({}, o), { value: o.value + by });
4230
+ if (Array.isArray(o.keyframes)) return __spreadProps(__spreadValues({}, o), { keyframes: o.keyframes.map((k) => __spreadProps(__spreadValues({}, k), { value: (Number(k.value) || 0) + by })) });
4231
+ return v;
4232
+ }
4233
+ function extendedPathForBrowser(pathD, opts) {
4234
+ var _a;
4235
+ if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
4236
+ const sampler = createPathSampler(pathD);
4237
+ if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
4238
+ const L = sampler.totalLength;
4239
+ const margin = EXTEND_MARGIN_FRAC * L;
4240
+ const so = numRange(opts.startOffset);
4241
+ const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
4242
+ const startOverflow = Math.max(0, -so.min);
4243
+ const endOverflow = Math.max(0, so.max + runWidth - L);
4244
+ const startExt = startOverflow > 0 ? startOverflow + margin : 0;
4245
+ const endExt = endOverflow > 0 ? endOverflow + margin : 0;
4246
+ if (endExt <= 0 && startExt <= 0) return { d: pathD, startShift: 0 };
4247
+ const s = sampler.sampleAtDistance(0);
4248
+ const e = sampler.sampleAtDistance(L);
4249
+ let d = pathD;
4250
+ if (startExt > 0) {
4251
+ const sx = s.x - Math.cos(s.angle) * startExt, sy = s.y - Math.sin(s.angle) * startExt;
4252
+ const rest = pathD.replace(/^\s*[Mm]\s*-?[\d.]+[\s,]+-?[\d.]+/, "");
4253
+ d = "M" + r3(sx) + "," + r3(sy) + "L" + r3(s.x) + "," + r3(s.y) + rest;
4254
+ }
4255
+ if (endExt > 0) {
4256
+ const ex = e.x + Math.cos(e.angle) * endExt, ey = e.y + Math.sin(e.angle) * endExt;
4257
+ d += "L" + r3(ex) + "," + r3(ey);
4258
+ }
4259
+ return { d, startShift: startExt };
4260
+ }
4261
+ function applyTextPathEffect(node, fx, ctx) {
4262
+ var _a;
4263
+ if (!fx || typeof fx.path !== "string" || !fx.path) return node;
4264
+ const pathId = genId(ctx, "tpath");
4265
+ const { d, startShift } = extendedPathForBrowser(fx.path, {
4266
+ pathOverflow: fx.pathOverflow,
4267
+ startOffset: fx.startOffset,
4268
+ textLength: fx.textLength,
4269
+ advance: estimateTextAdvance(node)
4270
+ });
4271
+ ctx.defs.push({ type: "path", id: pathId, d });
4272
+ const textPath = {
4273
+ type: "textPath",
4274
+ href: "#" + pathId,
4275
+ children: (_a = node.children) != null ? _a : []
4276
+ };
4277
+ if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
4278
+ if (fx.method !== void 0) textPath.method = fx.method;
4279
+ if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
4280
+ applyAnimatableNumber(textPath, "startOffset", shiftAnimatable(fx.startOffset, startShift));
4281
+ applyAnimatableNumber(textPath, "textLength", fx.textLength);
4282
+ node.children = [textPath];
4283
+ return node;
4284
+ }
4285
+ function applyAnimatableNumber(node, attrName, raw) {
4286
+ if (raw === void 0 || raw === null) return;
4287
+ if (typeof raw === "number") {
4288
+ node[attrName] = String(raw);
4289
+ return;
4290
+ }
4291
+ if (typeof raw === "object" && raw !== null) {
4292
+ const obj = raw;
4293
+ if (Array.isArray(obj.keyframes)) {
4294
+ const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
4295
+ const animate = __spreadValues({}, prevAnimate || {});
4296
+ const block = { keyframes: obj.keyframes };
4297
+ if (obj.loop !== void 0) block.loop = obj.loop;
4298
+ animate[attrName] = block;
4299
+ node.animate = animate;
4300
+ return;
4301
+ }
4302
+ if (typeof obj.value === "number") {
4303
+ node[attrName] = String(obj.value);
4304
+ return;
4305
+ }
4306
+ }
4307
+ }
4308
+ var jsonElementFactory = (type, props, children) => {
4309
+ const node = { type };
4310
+ for (const k in props) if (props[k] !== void 0) node[k] = props[k];
4311
+ const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
4312
+ if (arr.length) node.children = arr;
4313
+ return node;
4314
+ };
4315
+ function fmt(v, decimals) {
4316
+ return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
4317
+ }
4318
+ function pack(nums, decimals) {
4319
+ let s = "";
4320
+ for (let i = 0; i < nums.length; i++) {
4321
+ const str2 = fmt(nums[i], decimals);
4322
+ if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
4323
+ s += str2;
4324
+ }
4325
+ return s;
4326
+ }
4327
+ function apply(m, x, y) {
4328
+ return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
4329
+ }
4330
+ var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
4331
+ function transformPathData(d, m, decimals = 2) {
4332
+ const tokens = [];
4333
+ let match;
4334
+ TOKEN_RE.lastIndex = 0;
4335
+ while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
4336
+ let out = "";
4337
+ let i = 0;
4338
+ const num2 = () => parseFloat(tokens[i++]);
4339
+ while (i < tokens.length) {
4340
+ const cmd = tokens[i++];
4341
+ if (cmd === "M" || cmd === "L") {
4342
+ const [x, y] = apply(m, num2(), num2());
4343
+ out += cmd + pack([x, y], decimals);
4344
+ } else if (cmd === "C") {
4345
+ const [x1, y1] = apply(m, num2(), num2());
4346
+ const [x2, y2] = apply(m, num2(), num2());
4347
+ const [x, y] = apply(m, num2(), num2());
4348
+ out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
4349
+ } else if (cmd === "Q") {
4350
+ const [x1, y1] = apply(m, num2(), num2());
4351
+ const [x, y] = apply(m, num2(), num2());
4352
+ out += "Q" + pack([x1, y1, x, y], decimals);
4353
+ } else if (cmd === "Z" || cmd === "z") {
4354
+ out += "Z";
4355
+ }
4356
+ }
4357
+ return out;
4358
+ }
4287
4359
  var DEFAULT_FONT_SIZE = 16;
4288
4360
  var TEXT_ATTR_KEYS = [
4289
4361
  "fontFamily",
@@ -4444,7 +4516,7 @@ var PixodeskAnimatorReact = (() => {
4444
4516
  const cos = Math.cos(angle), sin = Math.sin(angle), hw = widthEm / 2;
4445
4517
  return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw, y - scale * sin * hw];
4446
4518
  }
4447
- function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength) {
4519
+ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
4448
4520
  var _a;
4449
4521
  const { glyphs, create = jsonElementFactory, warnings } = opts;
4450
4522
  const sampler = pathD ? createPathSampler(pathD) : null;
@@ -4459,12 +4531,17 @@ var PixodeskAnimatorReact = (() => {
4459
4531
  const k = textLength / width;
4460
4532
  for (const c of cells) c.midBase *= k;
4461
4533
  }
4534
+ const isClip = pathOverflow === "clip" && !sampler.closed;
4462
4535
  const so = readAnimatable(startOffset);
4463
4536
  if (so.kind === "animated" && so.keyframes.length >= 2) {
4464
- return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create), create);
4537
+ return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create, isClip), create);
4465
4538
  }
4466
4539
  const base = so.kind === "animated" ? Number((_a = so.keyframes[0]) == null ? void 0 : _a.value) || 0 : so.kind === "static" ? Number(so.value) || 0 : 0;
4467
- const placements = cells.map((c) => ({
4540
+ const placeCells = isClip ? cells.filter((c) => {
4541
+ const d = base + c.midBase;
4542
+ return d >= 0 && d <= sampler.totalLength;
4543
+ }) : cells;
4544
+ const placements = placeCells.map((c) => ({
4468
4545
  glyphD: c.glyphD,
4469
4546
  paint: c.paint,
4470
4547
  m: alongAffine(sampler, base + c.midBase, c.scale, c.widthEm)
@@ -4477,10 +4554,11 @@ var PixodeskAnimatorReact = (() => {
4477
4554
  const f = __pow(10, n);
4478
4555
  return Math.round(v * f) / f;
4479
4556
  }
4480
- function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create) {
4557
+ function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create, isClip) {
4481
4558
  const step = Math.max(sampler.totalLength / ALONG_PATH_MAX_STEPS, 0.5);
4482
4559
  const timeOf = (kf) => Number(kf.time) || 0;
4483
4560
  const offOf = (kf) => Number(kf.value) || 0;
4561
+ const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
4484
4562
  const out = [];
4485
4563
  for (const c of cells) {
4486
4564
  const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
@@ -4501,19 +4579,31 @@ var PixodeskAnimatorReact = (() => {
4501
4579
  }
4502
4580
  };
4503
4581
  };
4504
- const kfs = [sampleKf(offOf(sokfs[0]) + c.midBase, timeOf(sokfs[0]))];
4582
+ const kfs = [];
4583
+ const opKfs = [];
4584
+ const pushKf = (dist, time) => {
4585
+ kfs.push(sampleKf(dist, time));
4586
+ if (isClip) opKfs.push({ time, value: onPath(dist) ? 1 : 0 });
4587
+ };
4588
+ pushKf(offOf(sokfs[0]) + c.midBase, timeOf(sokfs[0]));
4505
4589
  for (let k = 1; k < sokfs.length; k++) {
4506
4590
  const t0 = timeOf(sokfs[k - 1]), t1 = timeOf(sokfs[k]);
4507
4591
  const o0 = offOf(sokfs[k - 1]), o1 = offOf(sokfs[k]);
4508
4592
  const n = Math.min(ALONG_PATH_MAX_STEPS_PER_SEGMENT, Math.max(1, Math.ceil(Math.abs(o1 - o0) / step)));
4509
4593
  for (let s = 1; s <= n; s++) {
4510
4594
  const f = s / n;
4511
- kfs.push(sampleKf(o0 + f * (o1 - o0) + c.midBase, t0 + f * (t1 - t0)));
4595
+ pushKf(o0 + f * (o1 - o0) + c.midBase, t0 + f * (t1 - t0));
4512
4596
  }
4513
4597
  }
4514
4598
  const transform = { keyframes: kfs };
4515
4599
  if (loop !== void 0) transform.loop = loop;
4516
- out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate: { transform } }), []));
4600
+ const animate = { transform };
4601
+ if (isClip && opKfs.some((k) => k.value === 0)) {
4602
+ const op = { keyframes: opKfs };
4603
+ if (loop !== void 0) op.loop = loop;
4604
+ animate.opacity = op;
4605
+ }
4606
+ out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate }), []));
4517
4607
  }
4518
4608
  return out;
4519
4609
  }
@@ -4564,12 +4654,12 @@ var PixodeskAnimatorReact = (() => {
4564
4654
  }
4565
4655
  return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
4566
4656
  }
4567
- function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength) {
4657
+ function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
4568
4658
  if (!ctx.glyphs) {
4569
4659
  ctx.warnings.push("textGlyphs: no definitions.glyphs");
4570
4660
  return null;
4571
4661
  }
4572
- return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength);
4662
+ return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
4573
4663
  }
4574
4664
  function getKfTranslate(kf) {
4575
4665
  var _a;
@@ -5967,18 +6057,17 @@ var PixodeskAnimatorReact = (() => {
5967
6057
  const originalId = typeof node.id === "string" ? node.id : void 0;
5968
6058
  const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
5969
6059
  if (!fx && !innerIdForContentRef) return node;
5970
- const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textAlongPath, text } = fx != null ? fx : {};
6060
+ const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
5971
6061
  const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
5972
6062
  if (fx) delete node.effects;
5973
6063
  let n = node;
5974
6064
  let consumedByGlyphs = false;
5975
6065
  if (text == null ? void 0 : text.useGlyphs) {
5976
- if (textAlongPath) {
5977
- const pathNode = typeof textAlongPath.href === "string" ? ctx.idMap.get(textAlongPath.href) : void 0;
5978
- const pathD = pathNode && typeof pathNode.d === "string" ? pathNode.d : void 0;
5979
- const rawTL = textAlongPath.textLength;
6066
+ if (textPath) {
6067
+ const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
6068
+ const rawTL = textPath.textLength;
5980
6069
  const textLength = typeof rawTL === "number" ? rawTL : rawTL && typeof rawTL === "object" ? typeof rawTL.value === "number" ? rawTL.value : Array.isArray(rawTL.keyframes) && rawTL.keyframes.length ? Number((_a = rawTL.keyframes[0]) == null ? void 0 : _a.value) : void 0 : void 0;
5981
- const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textAlongPath.startOffset, textLength);
6070
+ const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textLength, textPath.pathOverflow);
5982
6071
  if (glyphed) {
5983
6072
  n = glyphed;
5984
6073
  consumedByGlyphs = true;
@@ -5988,7 +6077,7 @@ var PixodeskAnimatorReact = (() => {
5988
6077
  consumedByGlyphs = true;
5989
6078
  }
5990
6079
  }
5991
- if (!consumedByGlyphs) n = applyTextAlongPathEffect(n, textAlongPath, ctx);
6080
+ if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
5992
6081
  n = applyFillGradientEffect(n, fillGradient, ctx);
5993
6082
  n = applyStrokeGradientEffect(n, strokeGradient, ctx);
5994
6083
  n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);