@xterm/addon-webgl 0.20.0-beta.3 → 0.20.0-beta.5

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,378 @@
1
+ /**
2
+ * Copyright (c) 2021 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
7
+ import { customGlyphDefinitions } from './CustomGlyphDefinitions';
8
+ import { CustomGlyphDefinitionType, CustomGlyphVectorType, type CustomGlyphPathDrawFunctionDefinition, type CustomGlyphPatternDefinition, type CustomGlyphRegionDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from './Types';
9
+
10
+ /**
11
+ * Try drawing a custom block element or box drawing character, returning whether it was
12
+ * successfully drawn.
13
+ */
14
+ export function tryDrawCustomGlyph(
15
+ ctx: CanvasRenderingContext2D,
16
+ c: string,
17
+ xOffset: number,
18
+ yOffset: number,
19
+ deviceCellWidth: number,
20
+ deviceCellHeight: number,
21
+ fontSize: number,
22
+ devicePixelRatio: number
23
+ ): boolean {
24
+ const unifiedCharDefinition = customGlyphDefinitions[c];
25
+ if (unifiedCharDefinition) {
26
+ switch (unifiedCharDefinition.type) {
27
+ case CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR:
28
+ drawBlockVectorChar(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
29
+ return true;
30
+ case CustomGlyphDefinitionType.BLOCK_PATTERN:
31
+ drawPatternChar(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
32
+ return true;
33
+ case CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION:
34
+ drawBlockPatternWithRegion(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
35
+ return true;
36
+ case CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR:
37
+ drawBlockPatternWithRegion(ctx, unifiedCharDefinition.data.pattern, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
38
+ drawBlockVectorChar(ctx, unifiedCharDefinition.data.vectors, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
39
+ return true;
40
+ case CustomGlyphDefinitionType.PATH_FUNCTION:
41
+ case CustomGlyphDefinitionType.PATH:
42
+ drawPathDefinitionCharacter(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
43
+ return true;
44
+ case CustomGlyphDefinitionType.VECTOR_SHAPE:
45
+ drawVectorShape(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight, fontSize, devicePixelRatio);
46
+ return true;
47
+ case CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT:
48
+ drawPathDefinitionCharacterWithWeight(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight, devicePixelRatio);
49
+ return true;
50
+ }
51
+ }
52
+
53
+ return false;
54
+ }
55
+
56
+ function drawBlockVectorChar(
57
+ ctx: CanvasRenderingContext2D,
58
+ charDefinition: ICustomGlyphSolidOctantBlockVector[],
59
+ xOffset: number,
60
+ yOffset: number,
61
+ deviceCellWidth: number,
62
+ deviceCellHeight: number
63
+ ): void {
64
+ for (let i = 0; i < charDefinition.length; i++) {
65
+ const box = charDefinition[i];
66
+ const xEighth = deviceCellWidth / 8;
67
+ const yEighth = deviceCellHeight / 8;
68
+ ctx.fillRect(
69
+ xOffset + box.x * xEighth,
70
+ yOffset + box.y * yEighth,
71
+ box.w * xEighth,
72
+ box.h * yEighth
73
+ );
74
+ }
75
+ }
76
+
77
+ function drawPathDefinitionCharacter(
78
+ ctx: CanvasRenderingContext2D,
79
+ charDefinition: CustomGlyphPathDrawFunctionDefinition | string,
80
+ xOffset: number,
81
+ yOffset: number,
82
+ deviceCellWidth: number,
83
+ deviceCellHeight: number
84
+ ): void {
85
+ const instructions = typeof charDefinition === 'string' ? charDefinition : charDefinition(0, 0);
86
+ ctx.beginPath();
87
+ for (const instruction of instructions.split(' ')) {
88
+ const type = instruction[0];
89
+ const args: string[] = instruction.substring(1).split(',');
90
+ if (!args[0] || !args[1]) {
91
+ if (type === 'Z') {
92
+ ctx.closePath();
93
+ }
94
+ continue;
95
+ }
96
+ const translatedArgs = args.map((e, i) => {
97
+ const val = parseFloat(e);
98
+ return i % 2 === 0
99
+ ? xOffset + val * deviceCellWidth
100
+ : yOffset + val * deviceCellHeight;
101
+ });
102
+ if (type === 'M') {
103
+ ctx.moveTo(translatedArgs[0], translatedArgs[1]);
104
+ } else if (type === 'L') {
105
+ ctx.lineTo(translatedArgs[0], translatedArgs[1]);
106
+ }
107
+ }
108
+ ctx.fill();
109
+ }
110
+
111
+ const cachedPatterns: Map<CustomGlyphPatternDefinition, Map</* fillStyle */string, CanvasPattern>> = new Map();
112
+
113
+ function drawPatternChar(
114
+ ctx: CanvasRenderingContext2D,
115
+ charDefinition: number[][],
116
+ xOffset: number,
117
+ yOffset: number,
118
+ deviceCellWidth: number,
119
+ deviceCellHeight: number
120
+ ): void {
121
+ let patternSet = cachedPatterns.get(charDefinition);
122
+ if (!patternSet) {
123
+ patternSet = new Map();
124
+ cachedPatterns.set(charDefinition, patternSet);
125
+ }
126
+ const fillStyle = ctx.fillStyle;
127
+ if (typeof fillStyle !== 'string') {
128
+ throw new Error(`Unexpected fillStyle type "${fillStyle}"`);
129
+ }
130
+ let pattern = patternSet.get(fillStyle);
131
+ if (!pattern) {
132
+ const width = charDefinition[0].length;
133
+ const height = charDefinition.length;
134
+ const tmpCanvas = ctx.canvas.ownerDocument.createElement('canvas');
135
+ tmpCanvas.width = width;
136
+ tmpCanvas.height = height;
137
+ const tmpCtx = throwIfFalsy(tmpCanvas.getContext('2d'));
138
+ const imageData = new ImageData(width, height);
139
+
140
+ // Extract rgba from fillStyle
141
+ let r: number;
142
+ let g: number;
143
+ let b: number;
144
+ let a: number;
145
+ if (fillStyle.startsWith('#')) {
146
+ r = parseInt(fillStyle.slice(1, 3), 16);
147
+ g = parseInt(fillStyle.slice(3, 5), 16);
148
+ b = parseInt(fillStyle.slice(5, 7), 16);
149
+ a = fillStyle.length > 7 && parseInt(fillStyle.slice(7, 9), 16) || 1;
150
+ } else if (fillStyle.startsWith('rgba')) {
151
+ ([r, g, b, a] = fillStyle.substring(5, fillStyle.length - 1).split(',').map(e => parseFloat(e)));
152
+ } else {
153
+ throw new Error(`Unexpected fillStyle color format "${fillStyle}" when drawing pattern glyph`);
154
+ }
155
+
156
+ for (let y = 0; y < height; y++) {
157
+ for (let x = 0; x < width; x++) {
158
+ imageData.data[(y * width + x) * 4 ] = r;
159
+ imageData.data[(y * width + x) * 4 + 1] = g;
160
+ imageData.data[(y * width + x) * 4 + 2] = b;
161
+ imageData.data[(y * width + x) * 4 + 3] = charDefinition[y][x] * (a * 255);
162
+ }
163
+ }
164
+ tmpCtx.putImageData(imageData, 0, 0);
165
+ pattern = throwIfFalsy(ctx.createPattern(tmpCanvas, null));
166
+ patternSet.set(fillStyle, pattern);
167
+ }
168
+ ctx.fillStyle = pattern;
169
+ ctx.fillRect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
170
+ }
171
+
172
+ /**
173
+ * Draws rectangular shade characters - medium shade pattern clipped to a region.
174
+ * Uses a checkerboard pattern that shifts 1px each row (same as medium shade U+2592).
175
+ */
176
+ function drawBlockPatternWithRegion(
177
+ ctx: CanvasRenderingContext2D,
178
+ definition: [pattern: CustomGlyphPatternDefinition, region: CustomGlyphRegionDefinition],
179
+ xOffset: number,
180
+ yOffset: number,
181
+ deviceCellWidth: number,
182
+ deviceCellHeight: number
183
+ ): void {
184
+ const [pattern, region] = definition;
185
+ const [rx, ry, rw, rh] = region;
186
+ const regionX = Math.round(xOffset + rx * deviceCellWidth);
187
+ const regionY = Math.round(yOffset + ry * deviceCellHeight);
188
+ const regionW = Math.round(rw * deviceCellWidth);
189
+ const regionH = Math.round(rh * deviceCellHeight);
190
+
191
+ // Save context state
192
+ ctx.save();
193
+
194
+ // Clip to the region
195
+ ctx.beginPath();
196
+ ctx.rect(regionX, regionY, regionW, regionH);
197
+ ctx.clip();
198
+
199
+ // Draw the pattern
200
+ drawPatternChar(ctx, pattern, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
201
+
202
+ // Restore context state
203
+ ctx.restore();
204
+ }
205
+
206
+ /**
207
+ * Draws the following box drawing characters by mapping a subset of SVG d attribute instructions to
208
+ * canvas draw calls.
209
+ *
210
+ * Box styles: ┎┰┒┍┯┑╓╥╖╒╤╕ ┏┳┓┌┲┓┌┬┐┏┱┐
211
+ * ┌─┬─┐ ┏━┳━┓ ╔═╦═╗ ┠╂┨┝┿┥╟╫╢╞╪╡ ┡╇┩├╊┫┢╈┪┣╉┤
212
+ * │ │ │ ┃ ┃ ┃ ║ ║ ║ ┖┸┚┕┷┙╙╨╜╘╧╛ └┴┘└┺┛┗┻┛┗┹┘
213
+ * ├─┼─┤ ┣━╋━┫ ╠═╬═╣ ┏┱┐┌┲┓┌┬┐┌┬┐ ┏┳┓┌┮┓┌┬┐┏┭┐
214
+ * │ │ │ ┃ ┃ ┃ ║ ║ ║ ┡╃┤├╄┩├╆┪┢╅┤ ┞╀┦├┾┫┟╁┧┣┽┤
215
+ * └─┴─┘ ┗━┻━┛ ╚═╩═╝ └┴┘└┴┘└┺┛┗┹┘ └┴┘└┶┛┗┻┛┗┵┘
216
+ *
217
+ * Other:
218
+ * ╭─╮ ╲ ╱ ╷╻╎╏┆┇┊┋ ╺╾╴ ╌╌╌ ┄┄┄ ┈┈┈
219
+ * │ │ ╳ ╽╿╎╏┆┇┊┋ ╶╼╸ ╍╍╍ ┅┅┅ ┉┉┉
220
+ * ╰─╯ ╱ ╲ ╹╵╎╏┆┇┊┋
221
+ *
222
+ * All box drawing characters:
223
+ * ─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏
224
+ * ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟
225
+ * ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯
226
+ * ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿
227
+ * ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏
228
+ * ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟
229
+ * ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯
230
+ * ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿
231
+ *
232
+ * ---
233
+ *
234
+ * Box drawing alignment tests: █
235
+ * ▉
236
+ * ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
237
+ * ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
238
+ * ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
239
+ * ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
240
+ * ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
241
+ * ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
242
+ * ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
243
+ *
244
+ * Source: https://www.w3.org/2001/06/utf-8-test/UTF-8-demo.html
245
+ */
246
+ function drawPathDefinitionCharacterWithWeight(
247
+ ctx: CanvasRenderingContext2D,
248
+ charDefinition: { [fontWeight: number]: string | ((xp: number, yp: number) => string) },
249
+ xOffset: number,
250
+ yOffset: number,
251
+ deviceCellWidth: number,
252
+ deviceCellHeight: number,
253
+ devicePixelRatio: number
254
+ ): void {
255
+ ctx.strokeStyle = ctx.fillStyle;
256
+ for (const [fontWeight, instructions] of Object.entries(charDefinition)) {
257
+ ctx.beginPath();
258
+ ctx.lineWidth = devicePixelRatio * Number.parseInt(fontWeight);
259
+ let actualInstructions: string;
260
+ if (typeof instructions === 'function') {
261
+ const xp = .15;
262
+ const yp = .15 / deviceCellHeight * deviceCellWidth;
263
+ actualInstructions = instructions(xp, yp);
264
+ } else {
265
+ actualInstructions = instructions;
266
+ }
267
+ for (const instruction of actualInstructions.split(' ')) {
268
+ const type = instruction[0];
269
+ const f = svgToCanvasInstructionMap[type];
270
+ if (!f) {
271
+ console.error(`Could not find drawing instructions for "${type}"`);
272
+ continue;
273
+ }
274
+ const args: string[] = instruction.substring(1).split(',');
275
+ if (!args[0] || !args[1]) {
276
+ continue;
277
+ }
278
+ f(ctx, translateArgs(args, deviceCellWidth, deviceCellHeight, xOffset, yOffset, true, devicePixelRatio));
279
+ }
280
+ ctx.stroke();
281
+ ctx.closePath();
282
+ }
283
+ }
284
+
285
+ function drawVectorShape(
286
+ ctx: CanvasRenderingContext2D,
287
+ charDefinition: ICustomGlyphVectorShape,
288
+ xOffset: number,
289
+ yOffset: number,
290
+ deviceCellWidth: number,
291
+ deviceCellHeight: number,
292
+ fontSize: number,
293
+ devicePixelRatio: number
294
+ ): void {
295
+ // Clip the cell to make sure drawing doesn't occur beyond bounds
296
+ const clipRegion = new Path2D();
297
+ clipRegion.rect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
298
+ ctx.clip(clipRegion);
299
+
300
+ ctx.beginPath();
301
+ // Scale the stroke with DPR and font size
302
+ const cssLineWidth = fontSize / 12;
303
+ ctx.lineWidth = devicePixelRatio * cssLineWidth;
304
+ for (const instruction of charDefinition.d.split(' ')) {
305
+ const type = instruction[0];
306
+ const f = svgToCanvasInstructionMap[type];
307
+ if (!f) {
308
+ console.error(`Could not find drawing instructions for "${type}"`);
309
+ continue;
310
+ }
311
+ const args: string[] = instruction.substring(1).split(',');
312
+ if (!args[0] || !args[1]) {
313
+ continue;
314
+ }
315
+ f(ctx, translateArgs(
316
+ args,
317
+ deviceCellWidth,
318
+ deviceCellHeight,
319
+ xOffset,
320
+ yOffset,
321
+ false,
322
+ devicePixelRatio,
323
+ (charDefinition.leftPadding ?? 0) * (cssLineWidth / 2),
324
+ (charDefinition.rightPadding ?? 0) * (cssLineWidth / 2)
325
+ ));
326
+ }
327
+ if (charDefinition.type === CustomGlyphVectorType.STROKE) {
328
+ ctx.strokeStyle = ctx.fillStyle;
329
+ ctx.stroke();
330
+ } else {
331
+ ctx.fill();
332
+ }
333
+ ctx.closePath();
334
+ }
335
+
336
+ function clamp(value: number, max: number, min: number = 0): number {
337
+ return Math.max(Math.min(value, max), min);
338
+ }
339
+
340
+ const svgToCanvasInstructionMap: { [index: string]: any } = {
341
+ 'C': (ctx: CanvasRenderingContext2D, args: number[]) => ctx.bezierCurveTo(args[0], args[1], args[2], args[3], args[4], args[5]),
342
+ 'L': (ctx: CanvasRenderingContext2D, args: number[]) => ctx.lineTo(args[0], args[1]),
343
+ 'M': (ctx: CanvasRenderingContext2D, args: number[]) => ctx.moveTo(args[0], args[1])
344
+ };
345
+
346
+ function translateArgs(args: string[], cellWidth: number, cellHeight: number, xOffset: number, yOffset: number, doClamp: boolean, devicePixelRatio: number, leftPadding: number = 0, rightPadding: number = 0): number[] {
347
+ const result = args.map(e => parseFloat(e) || parseInt(e));
348
+
349
+ if (result.length < 2) {
350
+ throw new Error('Too few arguments for instruction');
351
+ }
352
+
353
+ for (let x = 0; x < result.length; x += 2) {
354
+ // Translate from 0-1 to 0-cellWidth
355
+ result[x] *= cellWidth - (leftPadding * devicePixelRatio) - (rightPadding * devicePixelRatio);
356
+ // Ensure coordinate doesn't escape cell bounds and round to the nearest 0.5 to ensure a crisp
357
+ // line at 100% devicePixelRatio
358
+ if (doClamp && result[x] !== 0) {
359
+ result[x] = clamp(Math.round(result[x] + 0.5) - 0.5, cellWidth, 0);
360
+ }
361
+ // Apply the cell's offset (ie. x*cellWidth)
362
+ result[x] += xOffset + (leftPadding * devicePixelRatio);
363
+ }
364
+
365
+ for (let y = 1; y < result.length; y += 2) {
366
+ // Translate from 0-1 to 0-cellHeight
367
+ result[y] *= cellHeight;
368
+ // Ensure coordinate doesn't escape cell bounds and round to the nearest 0.5 to ensure a crisp
369
+ // line at 100% devicePixelRatio
370
+ if (doClamp && result[y] !== 0) {
371
+ result[y] = clamp(Math.round(result[y] + 0.5) - 0.5, cellHeight, 0);
372
+ }
373
+ // Apply the cell's offset (ie. x*cellHeight)
374
+ result[y] += yOffset;
375
+ }
376
+
377
+ return result;
378
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright (c) 2021 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ export interface ICustomGlyphSolidOctantBlockVector {
7
+ x: number;
8
+ y: number;
9
+ w: number;
10
+ h: number;
11
+ }
12
+
13
+ /**
14
+ * @param xp The percentage of 15% of the x axis.
15
+ * @param yp The percentage of 15% of the x axis on the y axis.
16
+ */
17
+ export type CustomGlyphPathDrawFunctionDefinition = (xp: number, yp: number) => string;
18
+
19
+ export interface ICustomGlyphVectorShape {
20
+ d: string;
21
+ type: CustomGlyphVectorType;
22
+ leftPadding?: number;
23
+ rightPadding?: number;
24
+ }
25
+
26
+ export const enum CustomGlyphVectorType {
27
+ FILL,
28
+ STROKE
29
+ }
30
+
31
+ export type CustomGlyphPatternDefinition = number[][];
32
+
33
+ export const enum CustomGlyphDefinitionType {
34
+ SOLID_OCTANT_BLOCK_VECTOR,
35
+ BLOCK_PATTERN,
36
+ BLOCK_PATTERN_WITH_REGION,
37
+ BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR,
38
+ PATH_FUNCTION,
39
+ PATH_FUNCTION_WITH_WEIGHT,
40
+ PATH,
41
+ VECTOR_SHAPE,
42
+ }
43
+
44
+ export type CustomGlyphRegionDefinition = [x: number, y: number, w: number, h: number];
45
+
46
+ export type CustomGlyphCharacterDefinition = (
47
+ { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: ICustomGlyphSolidOctantBlockVector[] } |
48
+ { type: CustomGlyphDefinitionType.BLOCK_PATTERN, data: CustomGlyphPatternDefinition } |
49
+ { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [pattern: CustomGlyphPatternDefinition, region: CustomGlyphRegionDefinition] } |
50
+ // TODO: Consolidate these, draws should be possible via regions/clipping instead of special
51
+ // casing
52
+ { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR, data: { pattern: [pattern: CustomGlyphPatternDefinition, region: CustomGlyphRegionDefinition], vectors: ICustomGlyphSolidOctantBlockVector[] } } |
53
+ { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: CustomGlyphPathDrawFunctionDefinition } |
54
+ { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [fontWeight: number]: string | CustomGlyphPathDrawFunctionDefinition } } |
55
+ { type: CustomGlyphDefinitionType.PATH, data: string } |
56
+ { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: ICustomGlyphVectorShape }
57
+ );