modern-text 0.2.5 → 0.2.6

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.cjs CHANGED
@@ -171,7 +171,6 @@ class Character {
171
171
  this.index = index;
172
172
  this.parent = parent;
173
173
  __publicField$4(this, "boundingBox", new modernPath2d.BoundingBox());
174
- __publicField$4(this, "path", new modernPath2d.Path2D());
175
174
  __publicField$4(this, "textWidth", 0);
176
175
  __publicField$4(this, "textHeight", 0);
177
176
  // glyph
@@ -193,11 +192,14 @@ class Character {
193
192
  }
194
193
  return void 0;
195
194
  }
196
- _updateGlyph(font) {
195
+ updateGlyph(font = this._font()) {
196
+ if (!font) {
197
+ return this;
198
+ }
199
+ const { unitsPerEm, ascender, descender, os2, post } = font;
197
200
  const { content, computedStyle, boundingBox, isVertical } = this;
198
201
  const { left, top, height } = boundingBox;
199
202
  const { fontSize } = computedStyle;
200
- const { unitsPerEm, ascender, descender, os2, post } = font;
201
203
  const rate = unitsPerEm / fontSize;
202
204
  const glyphWidth = font.getAdvanceWidth(content, fontSize);
203
205
  const glyphHeight = (ascender + Math.abs(descender)) / rate;
@@ -218,84 +220,7 @@ class Character {
218
220
  this.centerPoint = this.glyphBox.getCenterPoint();
219
221
  return this;
220
222
  }
221
- _decoration() {
222
- const { isVertical, underlinePosition, yStrikeoutPosition } = this;
223
- const { textDecoration, fontSize } = this.computedStyle;
224
- const { left, top, width, height } = this.boundingBox;
225
- const lineWidth = 0.1 * fontSize;
226
- let start;
227
- switch (textDecoration) {
228
- case "underline":
229
- if (isVertical) {
230
- start = left;
231
- } else {
232
- start = top + underlinePosition;
233
- }
234
- break;
235
- case "line-through":
236
- if (isVertical) {
237
- start = left + width / 2;
238
- } else {
239
- start = top + yStrikeoutPosition;
240
- }
241
- break;
242
- case "none":
243
- default:
244
- return [];
245
- }
246
- if (isVertical) {
247
- return [
248
- { type: "M", x: start, y: top },
249
- { type: "L", x: start, y: top + height },
250
- { type: "L", x: start + lineWidth, y: top + height },
251
- { type: "L", x: start + lineWidth, y: top },
252
- { type: "Z" }
253
- ];
254
- } else {
255
- return [
256
- { type: "M", x: left, y: start },
257
- { type: "L", x: left + width, y: start },
258
- { type: "L", x: left + width, y: start + lineWidth },
259
- { type: "L", x: left, y: start + lineWidth },
260
- { type: "Z" }
261
- ];
262
- }
263
- }
264
- _transform(commands, cb) {
265
- return commands.map((rawCmd) => {
266
- const cmd = { ...rawCmd };
267
- switch (cmd.type) {
268
- case "L":
269
- case "M":
270
- [cmd.x, cmd.y] = cb(cmd.x, cmd.y);
271
- break;
272
- case "Q":
273
- [cmd.x1, cmd.y1] = cb(cmd.x1, cmd.y1);
274
- [cmd.x, cmd.y] = cb(cmd.x, cmd.y);
275
- break;
276
- }
277
- return cmd;
278
- });
279
- }
280
- _italic(commands, startPoint) {
281
- const { baseline, glyphWidth } = this;
282
- const { left, top } = this.boundingBox;
283
- const _startPoint = startPoint || {
284
- y: top + baseline,
285
- x: left + glyphWidth / 2
286
- };
287
- return this._transform(commands, (x, y) => {
288
- const p = getSkewPoint({ x, y }, _startPoint, -0.24, 0);
289
- return [p.x, p.y];
290
- });
291
- }
292
- _rotation90(commands, point) {
293
- return this._transform(commands, (x, y) => {
294
- const p = getPointPosition({ x, y }, point, 90);
295
- return [p.x, p.y];
296
- });
297
- }
298
- updatePath() {
223
+ updateCommands() {
299
224
  const font = this._font();
300
225
  if (!font) {
301
226
  return this;
@@ -310,7 +235,7 @@ class Character {
310
235
  baseline,
311
236
  glyphHeight,
312
237
  glyphWidth
313
- } = this._updateGlyph(font);
238
+ } = this.updateGlyph(font);
314
239
  const { os2, ascender, descender } = font;
315
240
  const usWinAscent = ascender;
316
241
  const usWinDescent = descender;
@@ -368,11 +293,120 @@ class Character {
368
293
  }
369
294
  commands.push(...this._decoration());
370
295
  this.commands = commands;
371
- this.path = new modernPath2d.Path2D(commands);
372
296
  return this;
373
297
  }
374
298
  update() {
375
- this.updatePath();
299
+ this.updateCommands();
300
+ return this;
301
+ }
302
+ _decoration() {
303
+ const { isVertical, underlinePosition, yStrikeoutPosition } = this;
304
+ const { textDecoration, fontSize } = this.computedStyle;
305
+ const { left, top, width, height } = this.boundingBox;
306
+ const lineWidth = 0.1 * fontSize;
307
+ let start;
308
+ switch (textDecoration) {
309
+ case "underline":
310
+ if (isVertical) {
311
+ start = left;
312
+ } else {
313
+ start = top + underlinePosition;
314
+ }
315
+ break;
316
+ case "line-through":
317
+ if (isVertical) {
318
+ start = left + width / 2;
319
+ } else {
320
+ start = top + yStrikeoutPosition;
321
+ }
322
+ break;
323
+ case "none":
324
+ default:
325
+ return [];
326
+ }
327
+ if (isVertical) {
328
+ return [
329
+ { type: "M", x: start, y: top },
330
+ { type: "L", x: start, y: top + height },
331
+ { type: "L", x: start + lineWidth, y: top + height },
332
+ { type: "L", x: start + lineWidth, y: top },
333
+ { type: "Z" }
334
+ ];
335
+ } else {
336
+ return [
337
+ { type: "M", x: left, y: start },
338
+ { type: "L", x: left + width, y: start },
339
+ { type: "L", x: left + width, y: start + lineWidth },
340
+ { type: "L", x: left, y: start + lineWidth },
341
+ { type: "Z" }
342
+ ];
343
+ }
344
+ }
345
+ _italic(commands, startPoint) {
346
+ const { baseline, glyphWidth } = this;
347
+ const { left, top } = this.boundingBox;
348
+ const _startPoint = startPoint || {
349
+ y: top + baseline,
350
+ x: left + glyphWidth / 2
351
+ };
352
+ return this._transform(commands, (x, y) => {
353
+ const p = getSkewPoint({ x, y }, _startPoint, -0.24, 0);
354
+ return [p.x, p.y];
355
+ });
356
+ }
357
+ _rotation90(commands, point) {
358
+ return this._transform(commands, (x, y) => {
359
+ const p = getPointPosition({ x, y }, point, 90);
360
+ return [p.x, p.y];
361
+ });
362
+ }
363
+ _transform(commands, cb) {
364
+ return commands.map((rawCmd) => {
365
+ const cmd = { ...rawCmd };
366
+ switch (cmd.type) {
367
+ case "L":
368
+ case "M":
369
+ [cmd.x, cmd.y] = cb(cmd.x, cmd.y);
370
+ break;
371
+ case "Q":
372
+ [cmd.x1, cmd.y1] = cb(cmd.x1, cmd.y1);
373
+ [cmd.x, cmd.y] = cb(cmd.x, cmd.y);
374
+ break;
375
+ }
376
+ return cmd;
377
+ });
378
+ }
379
+ forEachCommand(cb) {
380
+ const commands = this.commands;
381
+ const last = { x: 0, y: 0 };
382
+ const first = { x: 0, y: 0 };
383
+ let isFirst = true;
384
+ let doSetFirstPoint = false;
385
+ for (let i = 0, len = commands.length; i < len; i++) {
386
+ if (isFirst) {
387
+ doSetFirstPoint = true;
388
+ isFirst = false;
389
+ }
390
+ let command = commands[i];
391
+ command = cb(command, i, { last, first }) ?? command;
392
+ switch (command.type) {
393
+ case "M":
394
+ case "L":
395
+ case "Q":
396
+ last.x = command.x;
397
+ last.y = command.y;
398
+ if (doSetFirstPoint) {
399
+ first.x = last.x;
400
+ first.y = last.y;
401
+ }
402
+ break;
403
+ case "Z":
404
+ last.x = first.x;
405
+ last.y = first.y;
406
+ isFirst = true;
407
+ break;
408
+ }
409
+ }
376
410
  return this;
377
411
  }
378
412
  getMinMax(min = modernPath2d.Point2D.MAX, max = modernPath2d.Point2D.MIN) {
@@ -406,7 +440,7 @@ class Character {
406
440
  drawTo(ctx, config = {}) {
407
441
  drawPaths({
408
442
  ctx,
409
- paths: [this.path],
443
+ paths: [new modernPath2d.Path2D(this.commands)],
410
444
  fontSize: this.computedStyle.fontSize,
411
445
  color: this.computedStyle.color,
412
446
  ...config
@@ -572,7 +606,7 @@ class Highlighter extends Feature {
572
606
  this.paths = groups.filter((characters2) => characters2.length).map((characters2) => {
573
607
  return {
574
608
  url: characters2[0].parent.highlight.url,
575
- box: modernPath2d.BoundingBox.from(...characters2.map((c) => c.glyphBox)),
609
+ box: modernPath2d.BoundingBox.from(...characters2.map((c) => c.boundingBox)),
576
610
  baseline: Math.max(...characters2.map((c) => c.baseline))
577
611
  };
578
612
  }).map((group2) => this._parseGroup(group2, fontSize)).flat();
@@ -1041,14 +1075,15 @@ class Text {
1041
1075
  const { paragraphs, boundingBox } = this.measure();
1042
1076
  this.paragraphs = paragraphs;
1043
1077
  this.boundingBox = boundingBox;
1044
- this.characters.forEach((c) => c.update());
1078
+ const characters = this.characters;
1079
+ characters.forEach((c) => c.update());
1045
1080
  if (this.deformation) {
1046
1081
  this._deformer.deform();
1047
1082
  }
1048
1083
  this._highlighter.highlight();
1049
1084
  const min = modernPath2d.Point2D.MAX;
1050
1085
  const max = modernPath2d.Point2D.MIN;
1051
- this.characters.forEach((c) => c.getMinMax(min, max));
1086
+ characters.forEach((c) => c.getMinMax(min, max));
1052
1087
  this.renderBoundingBox = new modernPath2d.BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
1053
1088
  return this;
1054
1089
  }
package/dist/index.d.cts CHANGED
@@ -12,6 +12,10 @@ type TextAlign = 'center' | 'end' | 'left' | 'right' | 'start';
12
12
  type VerticalAlign = 'baseline' | 'top' | 'middle' | 'bottom' | 'sub' | 'super' | 'text-top' | 'text-bottom';
13
13
  type TextTransform = 'uppercase' | 'lowercase' | 'none';
14
14
  type TextDecoration = 'none' | 'underline' | 'line-through';
15
+ interface PointLike {
16
+ x: number;
17
+ y: number;
18
+ }
15
19
  interface TextLayoutStyle {
16
20
  writingMode: WritingMode;
17
21
  textOrientation: TextOrientation;
@@ -97,7 +101,6 @@ declare class Character {
97
101
  index: number;
98
102
  parent: Fragment;
99
103
  boundingBox: BoundingBox;
100
- path: Path2D<any>;
101
104
  textWidth: number;
102
105
  textHeight: number;
103
106
  commands: GlyphPathCommand[];
@@ -110,28 +113,23 @@ declare class Character {
110
113
  baseline: number;
111
114
  centerDiviation: number;
112
115
  glyphBox: BoundingBox;
113
- centerPoint: {
114
- x: number;
115
- y: number;
116
- };
116
+ centerPoint: PointLike;
117
117
  get computedStyle(): TextStyle;
118
118
  get isVertical(): boolean;
119
119
  get fontSize(): number;
120
120
  constructor(content: string, index: number, parent: Fragment);
121
121
  protected _font(): Sfnt | undefined;
122
- protected _updateGlyph(font: Sfnt): this;
122
+ updateGlyph(font?: Sfnt | undefined): this;
123
+ updateCommands(): this;
124
+ update(): this;
123
125
  protected _decoration(): GlyphPathCommand[];
126
+ protected _italic(commands: GlyphPathCommand[], startPoint?: PointLike): GlyphPathCommand[];
127
+ protected _rotation90(commands: GlyphPathCommand[], point: PointLike): GlyphPathCommand[];
124
128
  protected _transform(commands: GlyphPathCommand[], cb: (x: number, y: number) => number[]): GlyphPathCommand[];
125
- protected _italic(commands: GlyphPathCommand[], startPoint?: {
126
- x: number;
127
- y: number;
128
- }): GlyphPathCommand[];
129
- protected _rotation90(commands: GlyphPathCommand[], point: {
130
- x: number;
131
- y: number;
132
- }): GlyphPathCommand[];
133
- updatePath(): this;
134
- update(): this;
129
+ forEachCommand(cb: (command: GlyphPathCommand, index: number, context: {
130
+ first: PointLike;
131
+ last: PointLike;
132
+ }) => void | GlyphPathCommand): this;
135
133
  getMinMax(min?: Point2D, max?: Point2D): {
136
134
  min: Point2D;
137
135
  max: Point2D;
@@ -346,4 +344,4 @@ declare function getPointPosition(point: {
346
344
  y: number;
347
345
  };
348
346
 
349
- export { Character, Deformer, type DrawShapePathsOptions, type EffectOptions, Effector, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type FragmentHighlight, Highlighter, type LinearGradient, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, type MeasuredResult, Measurer, Paragraph, type ParagraphContent, Parser, Reflector, type Render2dOptions, Renderer2D, Text, type TextAlign, type TextContent, type TextDecoration, type TextDeformation, type TextDrawStyle, type TextEffect, type TextLayoutStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, drawPaths, filterEmpty, getPointPosition, getRotationPoint, getScalePoint, getSkewPoint, parseColor, uploadColor };
347
+ export { Character, Deformer, type DrawShapePathsOptions, type EffectOptions, Effector, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type FragmentHighlight, Highlighter, type LinearGradient, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, type MeasuredResult, Measurer, Paragraph, type ParagraphContent, Parser, type PointLike, Reflector, type Render2dOptions, Renderer2D, Text, type TextAlign, type TextContent, type TextDecoration, type TextDeformation, type TextDrawStyle, type TextEffect, type TextLayoutStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, drawPaths, filterEmpty, getPointPosition, getRotationPoint, getScalePoint, getSkewPoint, parseColor, uploadColor };
package/dist/index.d.mts CHANGED
@@ -12,6 +12,10 @@ type TextAlign = 'center' | 'end' | 'left' | 'right' | 'start';
12
12
  type VerticalAlign = 'baseline' | 'top' | 'middle' | 'bottom' | 'sub' | 'super' | 'text-top' | 'text-bottom';
13
13
  type TextTransform = 'uppercase' | 'lowercase' | 'none';
14
14
  type TextDecoration = 'none' | 'underline' | 'line-through';
15
+ interface PointLike {
16
+ x: number;
17
+ y: number;
18
+ }
15
19
  interface TextLayoutStyle {
16
20
  writingMode: WritingMode;
17
21
  textOrientation: TextOrientation;
@@ -97,7 +101,6 @@ declare class Character {
97
101
  index: number;
98
102
  parent: Fragment;
99
103
  boundingBox: BoundingBox;
100
- path: Path2D<any>;
101
104
  textWidth: number;
102
105
  textHeight: number;
103
106
  commands: GlyphPathCommand[];
@@ -110,28 +113,23 @@ declare class Character {
110
113
  baseline: number;
111
114
  centerDiviation: number;
112
115
  glyphBox: BoundingBox;
113
- centerPoint: {
114
- x: number;
115
- y: number;
116
- };
116
+ centerPoint: PointLike;
117
117
  get computedStyle(): TextStyle;
118
118
  get isVertical(): boolean;
119
119
  get fontSize(): number;
120
120
  constructor(content: string, index: number, parent: Fragment);
121
121
  protected _font(): Sfnt | undefined;
122
- protected _updateGlyph(font: Sfnt): this;
122
+ updateGlyph(font?: Sfnt | undefined): this;
123
+ updateCommands(): this;
124
+ update(): this;
123
125
  protected _decoration(): GlyphPathCommand[];
126
+ protected _italic(commands: GlyphPathCommand[], startPoint?: PointLike): GlyphPathCommand[];
127
+ protected _rotation90(commands: GlyphPathCommand[], point: PointLike): GlyphPathCommand[];
124
128
  protected _transform(commands: GlyphPathCommand[], cb: (x: number, y: number) => number[]): GlyphPathCommand[];
125
- protected _italic(commands: GlyphPathCommand[], startPoint?: {
126
- x: number;
127
- y: number;
128
- }): GlyphPathCommand[];
129
- protected _rotation90(commands: GlyphPathCommand[], point: {
130
- x: number;
131
- y: number;
132
- }): GlyphPathCommand[];
133
- updatePath(): this;
134
- update(): this;
129
+ forEachCommand(cb: (command: GlyphPathCommand, index: number, context: {
130
+ first: PointLike;
131
+ last: PointLike;
132
+ }) => void | GlyphPathCommand): this;
135
133
  getMinMax(min?: Point2D, max?: Point2D): {
136
134
  min: Point2D;
137
135
  max: Point2D;
@@ -346,4 +344,4 @@ declare function getPointPosition(point: {
346
344
  y: number;
347
345
  };
348
346
 
349
- export { Character, Deformer, type DrawShapePathsOptions, type EffectOptions, Effector, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type FragmentHighlight, Highlighter, type LinearGradient, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, type MeasuredResult, Measurer, Paragraph, type ParagraphContent, Parser, Reflector, type Render2dOptions, Renderer2D, Text, type TextAlign, type TextContent, type TextDecoration, type TextDeformation, type TextDrawStyle, type TextEffect, type TextLayoutStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, drawPaths, filterEmpty, getPointPosition, getRotationPoint, getScalePoint, getSkewPoint, parseColor, uploadColor };
347
+ export { Character, Deformer, type DrawShapePathsOptions, type EffectOptions, Effector, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type FragmentHighlight, Highlighter, type LinearGradient, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, type MeasuredResult, Measurer, Paragraph, type ParagraphContent, Parser, type PointLike, Reflector, type Render2dOptions, Renderer2D, Text, type TextAlign, type TextContent, type TextDecoration, type TextDeformation, type TextDrawStyle, type TextEffect, type TextLayoutStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, drawPaths, filterEmpty, getPointPosition, getRotationPoint, getScalePoint, getSkewPoint, parseColor, uploadColor };
package/dist/index.d.ts CHANGED
@@ -12,6 +12,10 @@ type TextAlign = 'center' | 'end' | 'left' | 'right' | 'start';
12
12
  type VerticalAlign = 'baseline' | 'top' | 'middle' | 'bottom' | 'sub' | 'super' | 'text-top' | 'text-bottom';
13
13
  type TextTransform = 'uppercase' | 'lowercase' | 'none';
14
14
  type TextDecoration = 'none' | 'underline' | 'line-through';
15
+ interface PointLike {
16
+ x: number;
17
+ y: number;
18
+ }
15
19
  interface TextLayoutStyle {
16
20
  writingMode: WritingMode;
17
21
  textOrientation: TextOrientation;
@@ -97,7 +101,6 @@ declare class Character {
97
101
  index: number;
98
102
  parent: Fragment;
99
103
  boundingBox: BoundingBox;
100
- path: Path2D<any>;
101
104
  textWidth: number;
102
105
  textHeight: number;
103
106
  commands: GlyphPathCommand[];
@@ -110,28 +113,23 @@ declare class Character {
110
113
  baseline: number;
111
114
  centerDiviation: number;
112
115
  glyphBox: BoundingBox;
113
- centerPoint: {
114
- x: number;
115
- y: number;
116
- };
116
+ centerPoint: PointLike;
117
117
  get computedStyle(): TextStyle;
118
118
  get isVertical(): boolean;
119
119
  get fontSize(): number;
120
120
  constructor(content: string, index: number, parent: Fragment);
121
121
  protected _font(): Sfnt | undefined;
122
- protected _updateGlyph(font: Sfnt): this;
122
+ updateGlyph(font?: Sfnt | undefined): this;
123
+ updateCommands(): this;
124
+ update(): this;
123
125
  protected _decoration(): GlyphPathCommand[];
126
+ protected _italic(commands: GlyphPathCommand[], startPoint?: PointLike): GlyphPathCommand[];
127
+ protected _rotation90(commands: GlyphPathCommand[], point: PointLike): GlyphPathCommand[];
124
128
  protected _transform(commands: GlyphPathCommand[], cb: (x: number, y: number) => number[]): GlyphPathCommand[];
125
- protected _italic(commands: GlyphPathCommand[], startPoint?: {
126
- x: number;
127
- y: number;
128
- }): GlyphPathCommand[];
129
- protected _rotation90(commands: GlyphPathCommand[], point: {
130
- x: number;
131
- y: number;
132
- }): GlyphPathCommand[];
133
- updatePath(): this;
134
- update(): this;
129
+ forEachCommand(cb: (command: GlyphPathCommand, index: number, context: {
130
+ first: PointLike;
131
+ last: PointLike;
132
+ }) => void | GlyphPathCommand): this;
135
133
  getMinMax(min?: Point2D, max?: Point2D): {
136
134
  min: Point2D;
137
135
  max: Point2D;
@@ -346,4 +344,4 @@ declare function getPointPosition(point: {
346
344
  y: number;
347
345
  };
348
346
 
349
- export { Character, Deformer, type DrawShapePathsOptions, type EffectOptions, Effector, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type FragmentHighlight, Highlighter, type LinearGradient, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, type MeasuredResult, Measurer, Paragraph, type ParagraphContent, Parser, Reflector, type Render2dOptions, Renderer2D, Text, type TextAlign, type TextContent, type TextDecoration, type TextDeformation, type TextDrawStyle, type TextEffect, type TextLayoutStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, drawPaths, filterEmpty, getPointPosition, getRotationPoint, getScalePoint, getSkewPoint, parseColor, uploadColor };
347
+ export { Character, Deformer, type DrawShapePathsOptions, type EffectOptions, Effector, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type FragmentHighlight, Highlighter, type LinearGradient, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, type MeasuredResult, Measurer, Paragraph, type ParagraphContent, Parser, type PointLike, Reflector, type Render2dOptions, Renderer2D, Text, type TextAlign, type TextContent, type TextDecoration, type TextDeformation, type TextDrawStyle, type TextEffect, type TextLayoutStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, drawPaths, filterEmpty, getPointPosition, getRotationPoint, getScalePoint, getSkewPoint, parseColor, uploadColor };