render-tag 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,421 @@
1
+ /**
2
+ * render-tag/path — draw rich text along an SVG path on a 2D canvas.
3
+ *
4
+ * Reuses render-tag's HTML+CSS pipeline (parseHTML, resolveStylesFromCSS) and
5
+ * font primitives (applyFont) so styled spans, fonts, and colors come straight
6
+ * from the input HTML — no separate option surface.
7
+ *
8
+ * import { drawTextOnPath } from 'render-tag/path';
9
+ * drawTextOnPath({
10
+ * html: '<b>Hello</b> <span style="color:red">world</span>',
11
+ * path: 'M0,50 Q200,0 400,50',
12
+ * ctx,
13
+ * align: 'center',
14
+ * });
15
+ *
16
+ * For finer control:
17
+ * const result = layoutTextOnPath({ html, path, align });
18
+ * drawTextOnPathLayout({ layout: result, ctx });
19
+ *
20
+ * Supported styles (matches the main renderer):
21
+ * font-family / size / weight / style / kerning
22
+ * color, -webkit-text-fill-color, -webkit-text-stroke (width + color), paint-order
23
+ * background-color (span backgrounds drawn as curve-following polygons)
24
+ * text-shadow (rotates with glyphs; multi-shadow supported)
25
+ * text-decoration: underline / line-through / overline (solid/dotted/dashed/double/wavy)
26
+ * text-decoration-color, text-decoration-style
27
+ * background-clip:text + background-image:linear-gradient (gradient flows along the path)
28
+ * letter-spacing, direction: rtl, dir="rtl"
29
+ * Arabic / Hebrew / Indic / Thai / Khmer / Myanmar — shaped runs are
30
+ * rendered as a unit so cursive joining and reordering work correctly.
31
+ */
32
+ import { parseHTML } from '../parse.js';
33
+ import { resolveStylesFromCSS, paintOrderHasStrokeFirst } from '../css-resolver.js';
34
+ import { applyFont, isTransparent } from '../layout.js';
35
+ import { parseTextShadows, parseLinearGradient, drawDecorationLine, } from '../render.js';
36
+ import { pathFromString } from './svg-path.js';
37
+ import { flattenSegments, layoutGlyphsOnPath, baselineLocalY, } from './glyph-layout.js';
38
+ /**
39
+ * Compute glyph placements for rich text along a path, without drawing.
40
+ * Useful for inspection, hit-testing, or rendering the same layout multiple times.
41
+ * The HTML's CSS resolves against an infinite-width container, so wrapping
42
+ * does not happen — all text flows along the path as one logical line.
43
+ *
44
+ * The caller's ctx (when passed) has its `font`, `fontKerning`, and
45
+ * `letterSpacing` state saved+restored around the measurement work; nothing
46
+ * leaks to the caller.
47
+ */
48
+ export function layoutTextOnPath(config) {
49
+ const { html, align = 'left', textBaseline = 'alphabetic' } = config;
50
+ const path = typeof config.path === 'string' ? pathFromString(config.path) : config.path;
51
+ const measureCtx = config.ctx ?? createMeasureCtx();
52
+ const ownsCtx = config.ctx === undefined;
53
+ const { fragment, css } = parseHTML(html);
54
+ const { tree, cleanup } = resolveStylesFromCSS(fragment, css, Number.MAX_SAFE_INTEGER);
55
+ if (!ownsCtx)
56
+ measureCtx.save();
57
+ try {
58
+ const segments = flattenSegments(tree);
59
+ return layoutGlyphsOnPath({ segments, path, ctx: measureCtx, align, textBaseline });
60
+ }
61
+ finally {
62
+ if (!ownsCtx)
63
+ measureCtx.restore();
64
+ cleanup();
65
+ }
66
+ }
67
+ /**
68
+ * Draw a pre-computed layout onto a canvas context.
69
+ *
70
+ * Rendering passes (matching CSS painting order):
71
+ * 1. Span backgrounds (background-color, curve-following polygons)
72
+ * 2. Text shadows (per glyph, multi-shadow supported, rotates with glyph)
73
+ * 3. Glyph fill + stroke (paint-order aware; gradient text via slicing)
74
+ * 4. Text decoration (underline / line-through / overline)
75
+ *
76
+ * ctx state is saved+restored around the entire batch — nothing leaks.
77
+ */
78
+ export function drawTextOnPathLayout(config) {
79
+ const { layout, ctx } = config;
80
+ if (layout.glyphs.length === 0)
81
+ return;
82
+ const tb = layout.textBaseline;
83
+ ctx.save();
84
+ try {
85
+ drawBackgrounds(ctx, layout.glyphs, tb);
86
+ drawShadowsAndGlyphs(ctx, layout.glyphs, layout.textWidth, tb);
87
+ drawDecorations(ctx, layout.glyphs, tb);
88
+ }
89
+ finally {
90
+ ctx.restore();
91
+ }
92
+ }
93
+ /**
94
+ * Convenience: compute layout and draw in a single call.
95
+ */
96
+ export function drawTextOnPath(config) {
97
+ const layout = layoutTextOnPath({
98
+ html: config.html,
99
+ path: config.path,
100
+ align: config.align,
101
+ textBaseline: config.textBaseline,
102
+ ctx: config.ctx,
103
+ });
104
+ drawTextOnPathLayout({ layout, ctx: config.ctx });
105
+ return layout;
106
+ }
107
+ function createMeasureCtx() {
108
+ const canvas = typeof OffscreenCanvas !== 'undefined'
109
+ ? new OffscreenCanvas(1, 1)
110
+ : document.createElement('canvas');
111
+ return canvas.getContext('2d');
112
+ }
113
+ // ─── Pass 1: Backgrounds ──────────────────────────────────────────────
114
+ /**
115
+ * Round-trip a color through `ctx.fillStyle` to get the browser's
116
+ * canonical form. This makes `red` and `rgb(255, 0, 0)` and `#f00`
117
+ * compare equal so adjacent spans with semantically-identical colors
118
+ * group into one polygon / one stroke (no visible seam, dash phase
119
+ * continuous). Results cached so we don't pay the round-trip per glyph.
120
+ */
121
+ const _colorCanonicalCache = new WeakMap();
122
+ function canonicalColor(ctx, color) {
123
+ if (!color)
124
+ return '';
125
+ let perCtx = _colorCanonicalCache.get(ctx);
126
+ if (!perCtx) {
127
+ perCtx = new Map();
128
+ _colorCanonicalCache.set(ctx, perCtx);
129
+ }
130
+ const cached = perCtx.get(color);
131
+ if (cached !== undefined)
132
+ return cached;
133
+ // ctx.fillStyle returns the canonical form when read back.
134
+ const prev = ctx.fillStyle;
135
+ try {
136
+ ctx.fillStyle = color;
137
+ const canon = typeof ctx.fillStyle === 'string' ? ctx.fillStyle : color;
138
+ perCtx.set(color, canon);
139
+ return canon;
140
+ }
141
+ catch {
142
+ perCtx.set(color, color);
143
+ return color;
144
+ }
145
+ finally {
146
+ ctx.fillStyle = prev;
147
+ }
148
+ }
149
+ /**
150
+ * Group consecutive glyphs sharing a visible background color and draw each
151
+ * group as a curve-following polygon (top edge + bottom edge).
152
+ */
153
+ function drawBackgrounds(ctx, glyphs, tb) {
154
+ let i = 0;
155
+ while (i < glyphs.length) {
156
+ const bg = glyphs[i].style.backgroundColor;
157
+ if (!bg || isTransparent(bg)) {
158
+ i++;
159
+ continue;
160
+ }
161
+ const canon = canonicalColor(ctx, bg);
162
+ let j = i + 1;
163
+ while (j < glyphs.length &&
164
+ canonicalColor(ctx, glyphs[j].style.backgroundColor) === canon)
165
+ j++;
166
+ fillGlyphPolygon(ctx, glyphs.slice(i, j), bg, tb);
167
+ i = j;
168
+ }
169
+ }
170
+ /**
171
+ * Build the four-corner box of one glyph in world coordinates. Local y=0 is
172
+ * the path point — actual baseline sits at `baselineLocalY(tb, ascent, descent)`.
173
+ * The polygon spans `[baseY - ascent, baseY + descent]` so it hugs the painted
174
+ * glyph extent regardless of which textBaseline anchor was chosen.
175
+ */
176
+ function glyphCorners(g, tb) {
177
+ const c = Math.cos(g.rotation);
178
+ const s = Math.sin(g.rotation);
179
+ const baseY = baselineLocalY(tb, g.ascent, g.descent);
180
+ const top = baseY - g.ascent;
181
+ const bottom = baseY + g.descent;
182
+ const w = g.width;
183
+ return {
184
+ tl: { x: g.x + (-s) * top, y: g.y + c * top },
185
+ tr: { x: g.x + c * w + (-s) * top, y: g.y + s * w + c * top },
186
+ br: { x: g.x + c * w + (-s) * bottom, y: g.y + s * w + c * bottom },
187
+ bl: { x: g.x + (-s) * bottom, y: g.y + c * bottom },
188
+ };
189
+ }
190
+ /** Fill a polygon hugging the path through a sequence of consecutive glyphs. */
191
+ function fillGlyphPolygon(ctx, group, fill, tb) {
192
+ if (group.length === 0)
193
+ return;
194
+ ctx.save();
195
+ ctx.fillStyle = fill;
196
+ ctx.beginPath();
197
+ const first = glyphCorners(group[0], tb);
198
+ ctx.moveTo(first.tl.x, first.tl.y);
199
+ for (let i = 0; i < group.length; i++) {
200
+ const c = glyphCorners(group[i], tb);
201
+ ctx.lineTo(c.tl.x, c.tl.y);
202
+ ctx.lineTo(c.tr.x, c.tr.y);
203
+ }
204
+ for (let i = group.length - 1; i >= 0; i--) {
205
+ const c = glyphCorners(group[i], tb);
206
+ ctx.lineTo(c.br.x, c.br.y);
207
+ ctx.lineTo(c.bl.x, c.bl.y);
208
+ }
209
+ ctx.closePath();
210
+ ctx.fill();
211
+ ctx.restore();
212
+ }
213
+ // ─── Pass 2: Shadows + glyph fill/stroke ─────────────────────────────
214
+ /**
215
+ * Iterate glyphs once. For each: draw the configured text-shadow stack (if
216
+ * any), then fill (possibly through a sliced gradient) and stroke per
217
+ * paint-order.
218
+ */
219
+ function drawShadowsAndGlyphs(ctx, glyphs, textWidth, tb) {
220
+ for (const g of glyphs) {
221
+ ctx.save();
222
+ ctx.translate(g.x, g.y);
223
+ ctx.rotate(g.rotation);
224
+ applyFont(ctx, g.style);
225
+ // Keep ctx.textBaseline at 'alphabetic' and offset fillText's y instead.
226
+ // This keeps our bounds / decoration / background math in agreement with
227
+ // what fillText actually paints, regardless of which textBaseline the
228
+ // caller picked.
229
+ ctx.textBaseline = 'alphabetic';
230
+ // Mirror the letter-spacing used at measurement time. Without this,
231
+ // shaped runs (Arabic / Indic / Thai) whose `g.width` was measured WITH
232
+ // letter-spacing render visibly tighter than the reserved width.
233
+ // Always assign so a stale value from earlier glyphs doesn't leak.
234
+ ctx.letterSpacing = `${g.style.letterSpacing || 0}px`;
235
+ const baseY = baselineLocalY(tb, g.ascent, g.descent);
236
+ // Shadow pass — drawn underneath the glyph fill. Multi-shadow stacks
237
+ // paint last-listed-first so the first declared shadow is on top.
238
+ const shadows = parseTextShadows(g.style.textShadow);
239
+ if (shadows.length > 0) {
240
+ for (let i = shadows.length - 1; i >= 0; i--) {
241
+ const sh = shadows[i];
242
+ ctx.save();
243
+ ctx.shadowOffsetX = sh.offsetX;
244
+ ctx.shadowOffsetY = sh.offsetY;
245
+ ctx.shadowBlur = sh.blur;
246
+ ctx.shadowColor = sh.color;
247
+ ctx.fillStyle = effectiveFillColor(g.style);
248
+ ctx.fillText(g.char, 0, baseY);
249
+ ctx.restore();
250
+ }
251
+ }
252
+ drawGlyphFillAndStroke(ctx, g, textWidth, baseY);
253
+ ctx.restore();
254
+ }
255
+ }
256
+ function drawGlyphFillAndStroke(ctx, g, textWidth, baseY) {
257
+ const { style } = g;
258
+ // Mirror the main renderer's transparency check: EITHER -webkit-text-fill-color
259
+ // or color being 'transparent' suppresses the fill. effectiveFillColor alone
260
+ // would only catch one of the two by falling back through the precedence.
261
+ const fillTransparent = style.webkitTextFillColor === 'transparent' ||
262
+ style.color === 'transparent' ||
263
+ isTransparent(effectiveFillColor(style));
264
+ const isStroked = style.webkitTextStrokeWidth > 0;
265
+ const usesGradient = style.webkitBackgroundClip === 'text' &&
266
+ style.backgroundImage && style.backgroundImage !== 'none';
267
+ // Use the canonical helper instead of an ad-hoc regex — paint-order tokens
268
+ // are positional ("fill stroke" = fill first), not a flag bag.
269
+ const paintStrokeFirst = paintOrderHasStrokeFirst(style.paintOrder || '');
270
+ const drawFill = () => {
271
+ if (usesGradient) {
272
+ drawGradientGlyph(ctx, g, textWidth, baseY);
273
+ return;
274
+ }
275
+ if (fillTransparent) {
276
+ if (isStroked)
277
+ return;
278
+ ctx.fillStyle = 'transparent';
279
+ ctx.fillText(g.char, 0, baseY);
280
+ return;
281
+ }
282
+ ctx.fillStyle = effectiveFillColor(style);
283
+ ctx.fillText(g.char, 0, baseY);
284
+ };
285
+ const drawStroke = () => {
286
+ if (!isStroked)
287
+ return;
288
+ ctx.save();
289
+ ctx.lineJoin = 'round';
290
+ ctx.lineWidth = style.webkitTextStrokeWidth;
291
+ ctx.strokeStyle = style.webkitTextStrokeColor || style.color;
292
+ ctx.strokeText(g.char, 0, baseY);
293
+ ctx.restore();
294
+ };
295
+ if (paintStrokeFirst) {
296
+ drawStroke();
297
+ drawFill();
298
+ }
299
+ else {
300
+ drawFill();
301
+ drawStroke();
302
+ }
303
+ }
304
+ /**
305
+ * Render one glyph with a gradient fill that flows along the path. The
306
+ * gradient is created once per glyph spanning the FULL text width in the
307
+ * glyph's local rotated frame, offset so the glyph's slice lines up with
308
+ * the global gradient. Neighbouring glyphs stitch into one continuous color
309
+ * curve when viewed along the path.
310
+ */
311
+ function drawGradientGlyph(ctx, g, textWidth, baseY) {
312
+ // The gradient is laid out from (-pathOffset, *) to (textWidth-pathOffset, *)
313
+ // in this glyph's local frame, so global gradient at fraction t/textWidth
314
+ // matches what neighbouring glyphs render. The vertical band tracks the
315
+ // glyph's full extent around the baseline anchor.
316
+ const gradient = parseLinearGradient(ctx, g.style.backgroundImage, -g.pathOffset, textWidth, baseY - g.ascent, g.ascent + g.descent);
317
+ if (!gradient) {
318
+ ctx.fillStyle = effectiveFillColor(g.style);
319
+ ctx.fillText(g.char, 0, baseY);
320
+ return;
321
+ }
322
+ ctx.fillStyle = gradient;
323
+ ctx.fillText(g.char, 0, baseY);
324
+ }
325
+ // ─── Pass 3: Decorations ─────────────────────────────────────────────
326
+ /**
327
+ * Underline / line-through / overline: stroke a curve that follows the path
328
+ * at the appropriate vertical offset. Groups consecutive glyphs sharing
329
+ * decoration-line + style + color.
330
+ */
331
+ function drawDecorations(ctx, glyphs, tb) {
332
+ const lines = ['underline', 'line-through', 'overline'];
333
+ for (const lineKind of lines) {
334
+ let i = 0;
335
+ while (i < glyphs.length) {
336
+ const style = glyphs[i].style;
337
+ if (!style.textDecorationLine || !style.textDecorationLine.includes(lineKind)) {
338
+ i++;
339
+ continue;
340
+ }
341
+ const color = style.textDecorationColor || style.color;
342
+ const decoStyle = style.textDecorationStyle || 'solid';
343
+ const colorCanon = canonicalColor(ctx, color);
344
+ let j = i + 1;
345
+ while (j < glyphs.length &&
346
+ glyphs[j].style.textDecorationLine &&
347
+ glyphs[j].style.textDecorationLine.includes(lineKind) &&
348
+ canonicalColor(ctx, glyphs[j].style.textDecorationColor || glyphs[j].style.color) === colorCanon &&
349
+ (glyphs[j].style.textDecorationStyle || 'solid') === decoStyle)
350
+ j++;
351
+ strokeDecorationAlongGlyphs(ctx, glyphs.slice(i, j), lineKind, decoStyle, color, tb);
352
+ i = j;
353
+ }
354
+ }
355
+ }
356
+ function strokeDecorationAlongGlyphs(ctx, group, lineKind, decoStyle, color, tb) {
357
+ if (group.length === 0)
358
+ return;
359
+ const lineWidth = Math.max(1, group[0].style.fontSize / 15);
360
+ // Per-glyph local y for this decoration kind. The decoration position is
361
+ // baseline-relative, so we shift by the baseline's local-y under the
362
+ // current textBaseline to land in the right spot on the canvas.
363
+ const localY = (g) => {
364
+ const baseY = baselineLocalY(tb, g.ascent, g.descent);
365
+ if (lineKind === 'underline')
366
+ return baseY + g.descent * 0.5;
367
+ if (lineKind === 'line-through')
368
+ return baseY - g.ascent * 0.3;
369
+ return baseY - g.ascent * 0.9; // overline
370
+ };
371
+ if (decoStyle === 'double' || decoStyle === 'wavy') {
372
+ // For double/wavy we draw each glyph segment independently using the
373
+ // shared helper so the visual matches the main renderer.
374
+ for (const g of group) {
375
+ ctx.save();
376
+ ctx.translate(g.x, g.y);
377
+ ctx.rotate(g.rotation);
378
+ drawDecorationLine(ctx, 0, localY(g), g.width, lineWidth, decoStyle, color);
379
+ ctx.restore();
380
+ }
381
+ return;
382
+ }
383
+ // Solid / dotted / dashed: a single continuous polyline through (left,
384
+ // right) endpoints of each glyph projected into world space. Stroking
385
+ // once keeps the dash phase continuous across the whole decoration run.
386
+ ctx.save();
387
+ ctx.strokeStyle = color;
388
+ ctx.lineWidth = lineWidth;
389
+ if (decoStyle === 'dotted')
390
+ ctx.setLineDash([lineWidth, lineWidth * 2]);
391
+ else if (decoStyle === 'dashed')
392
+ ctx.setLineDash([lineWidth * 3, lineWidth * 2]);
393
+ ctx.beginPath();
394
+ for (let i = 0; i < group.length; i++) {
395
+ const g = group[i];
396
+ const yOff = localY(g);
397
+ const c = Math.cos(g.rotation);
398
+ const s = Math.sin(g.rotation);
399
+ const left = { x: g.x + (-s) * yOff, y: g.y + c * yOff };
400
+ const right = {
401
+ x: g.x + c * g.width + (-s) * yOff,
402
+ y: g.y + s * g.width + c * yOff,
403
+ };
404
+ if (i === 0)
405
+ ctx.moveTo(left.x, left.y);
406
+ else
407
+ ctx.lineTo(left.x, left.y);
408
+ ctx.lineTo(right.x, right.y);
409
+ }
410
+ ctx.stroke();
411
+ ctx.setLineDash([]);
412
+ ctx.restore();
413
+ }
414
+ // ─── Style helpers ───────────────────────────────────────────────────
415
+ function effectiveFillColor(style) {
416
+ if (style.webkitTextFillColor && style.webkitTextFillColor !== 'transparent') {
417
+ return style.webkitTextFillColor;
418
+ }
419
+ return style.color;
420
+ }
421
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/path/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Minimal SVG path 'd' attribute parser + arc-length tabulation.
3
+ * Supports: M m L l H h V v C c S s Q q T t A a Z z.
4
+ *
5
+ * Curves are sampled uniformly in parameter space and the cumulative
6
+ * arc-length is tabulated. `getPointAtLength` binary-searches that table
7
+ * and lerps between adjacent samples. Accuracy is "good enough for visual
8
+ * rendering" — not for hit-testing or precise length math.
9
+ */
10
+ export interface Point {
11
+ x: number;
12
+ y: number;
13
+ }
14
+ export interface PathLike {
15
+ length: number;
16
+ /** Returns the (x, y) on the path at arc length `t`, or null if `t` is out of range. */
17
+ getPointAtLength(t: number): Point | null;
18
+ }
19
+ type Seg = {
20
+ type: 'L';
21
+ x0: number;
22
+ y0: number;
23
+ x1: number;
24
+ y1: number;
25
+ } | {
26
+ type: 'C';
27
+ x0: number;
28
+ y0: number;
29
+ c1x: number;
30
+ c1y: number;
31
+ c2x: number;
32
+ c2y: number;
33
+ x1: number;
34
+ y1: number;
35
+ } | {
36
+ type: 'Q';
37
+ x0: number;
38
+ y0: number;
39
+ cx: number;
40
+ cy: number;
41
+ x1: number;
42
+ y1: number;
43
+ } | {
44
+ type: 'A';
45
+ x0: number;
46
+ y0: number;
47
+ rx: number;
48
+ ry: number;
49
+ xAxisRotation: number;
50
+ largeArc: boolean;
51
+ sweep: boolean;
52
+ x1: number;
53
+ y1: number;
54
+ };
55
+ /**
56
+ * Parse path data into an array of normalized absolute-coordinate segments.
57
+ * Drops moveTo commands (they don't draw); inserts a closing line for Z.
58
+ */
59
+ export declare function parsePathData(d: string): Seg[];
60
+ /**
61
+ * Build a PathLike interface from normalized segments.
62
+ * Tabulates cumulative arc-length per segment for O(log N) length-to-point lookup.
63
+ */
64
+ export declare function buildPathLike(segs: Seg[]): PathLike;
65
+ /** Convenience: parse a path string and build a PathLike in one call. */
66
+ export declare function pathFromString(d: string): PathLike;
67
+ export {};
68
+ //# sourceMappingURL=svg-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg-path.d.ts","sourceRoot":"","sources":["../../src/path/svg-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;CAC3C;AAED,KAAK,GAAG,GACJ;IAAE,IAAI,EAAE,GAAG,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7D;IACE,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;CACxB,GACD;IACE,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;CACxB,GACD;IACE,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;CACxB,CAAC;AAiCN;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE,CAuK9C;AAqGD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAgFnD;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAElD"}