modern-text 0.2.42 → 0.2.44

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/README.md CHANGED
@@ -21,32 +21,19 @@
21
21
  ## Usage
22
22
 
23
23
  ```ts
24
- import { Text } from 'modern-text'
24
+ import { renderText } from 'modern-text'
25
25
 
26
- const text = new Text({
26
+ const view = document.createElement('canvas')
27
+ document.body.append(view)
28
+
29
+ renderText({
30
+ view,
27
31
  style: {
28
32
  width: 100,
29
33
  height: 200,
30
34
  fontSize: 22,
31
35
  textDecoration: 'underline',
32
36
  },
33
- // content: 'paragraph'
34
- // content: [
35
- // 'paragraph1',
36
- // ['paragraph1', 'paragraph2'],
37
- // { content: 'paragraph2', fontSize: 20 },
38
- // [
39
- // { content: 'fragment1', fontSize: 12 },
40
- // { content: 'fragment2', fontSize: 30 },
41
- // ],
42
- // {
43
- // backgroundColor: 'blue',
44
- // fragments: [
45
- // { content: 'fragment3', color: 'red', fontSize: 12 },
46
- // { content: 'fragment4', color: 'black' },
47
- // ],
48
- // },
49
- // ]
50
37
  content: [
51
38
  {
52
39
  letterSpacing: 3,
@@ -59,10 +46,4 @@ const text = new Text({
59
46
  { content: 'World!', color: 'black' },
60
47
  ],
61
48
  })
62
-
63
- const view = document.createElement('canvas')
64
- text.render({ view })
65
- document.body.append(view) // canvas 2d
66
-
67
- console.log(text.measure()) // boundingBox with computed paragraphs
68
49
  ```
package/dist/index.cjs CHANGED
@@ -122,6 +122,14 @@ const set2 = /* @__PURE__ */ new Set([
122
122
  "\u2019",
123
123
  "\u02DC"
124
124
  ]);
125
+ const fsSelectionMap = {
126
+ 1: "italic",
127
+ 32: "bold"
128
+ };
129
+ const macStyleMap = {
130
+ 1: "italic",
131
+ 2: "bold"
132
+ };
125
133
  const fontWeightMap = {
126
134
  100: -0.2,
127
135
  200: -0.1,
@@ -201,17 +209,19 @@ class Character {
201
209
  if (!font) {
202
210
  return this;
203
211
  }
212
+ this.updateGlyph(font);
204
213
  const {
205
214
  isVertical,
206
215
  content,
207
- computedStyle,
216
+ computedStyle: style,
208
217
  baseline,
209
218
  inlineBox
210
- } = this.updateGlyph(font);
211
- const { os2, ascender, descender } = font;
219
+ } = this;
220
+ const { os2, head, ascender, descender } = font;
212
221
  const typoAscender = os2.sTypoAscender;
222
+ const fontStyle = fsSelectionMap[os2.fsSelection] ?? macStyleMap[head.macStyle];
213
223
  const { left, top } = inlineBox;
214
- const { fontSize, fontStyle } = computedStyle;
224
+ const needsItalic = style.fontStyle === "italic" && fontStyle !== "italic";
215
225
  let x = left;
216
226
  let y = top + baseline;
217
227
  let glyphIndex;
@@ -225,13 +235,13 @@ class Character {
225
235
  }
226
236
  if (isVertical && !set1.has(content) && (content.codePointAt(0) <= 256 || set2.has(content))) {
227
237
  path.addCommands(
228
- font.getPathCommands(content, x, top + baseline - (inlineBox.height - inlineBox.width) / 2, fontSize) ?? []
238
+ font.getPathCommands(content, x, top + baseline - (inlineBox.height - inlineBox.width) / 2, style.fontSize) ?? []
229
239
  );
230
240
  const point = {
231
241
  y: top - (inlineBox.height - inlineBox.width) / 2 + inlineBox.height / 2,
232
242
  x: x + inlineBox.width / 2
233
243
  };
234
- if (fontStyle === "italic") {
244
+ if (needsItalic) {
235
245
  this._italic(
236
246
  path,
237
247
  isVertical ? {
@@ -244,9 +254,9 @@ class Character {
244
254
  } else {
245
255
  if (glyphIndex !== void 0) {
246
256
  path.addCommands(
247
- font.glyphs.get(glyphIndex).getPathCommands(x, y, fontSize)
257
+ font.glyphs.get(glyphIndex).getPathCommands(x, y, style.fontSize)
248
258
  );
249
- if (fontStyle === "italic") {
259
+ if (needsItalic) {
250
260
  this._italic(
251
261
  path,
252
262
  isVertical ? {
@@ -257,9 +267,9 @@ class Character {
257
267
  }
258
268
  } else {
259
269
  path.addCommands(
260
- font.getPathCommands(content, x, y, fontSize) ?? []
270
+ font.getPathCommands(content, x, y, style.fontSize) ?? []
261
271
  );
262
- if (fontStyle === "italic") {
272
+ if (needsItalic) {
263
273
  this._italic(
264
274
  path,
265
275
  isVertical ? { x: x + inlineBox.height / 2, y } : void 0
@@ -268,14 +278,14 @@ class Character {
268
278
  }
269
279
  }
270
280
  path.addCommands(this._decoration());
271
- const fontWeight = computedStyle.fontWeight ?? 400;
272
- if (fontWeight in fontWeightMap) {
273
- path.bold(fontWeightMap[fontWeight] * fontSize * 0.05);
281
+ const fontWeight = style.fontWeight ?? 400;
282
+ if (fontWeight in fontWeightMap && ((fontWeight === 700 || fontWeight === "bold") && fontStyle !== "bold")) {
283
+ path.bold(fontWeightMap[fontWeight] * style.fontSize * 0.05);
274
284
  }
275
285
  path.style = {
276
- fill: computedStyle.color,
277
- stroke: computedStyle.textStrokeWidth ? computedStyle.textStrokeColor : "none",
278
- strokeWidth: computedStyle.textStrokeWidth ? computedStyle.textStrokeWidth * fontSize * 0.03 : 0
286
+ fill: style.color,
287
+ stroke: style.textStrokeWidth ? style.textStrokeColor : "none",
288
+ strokeWidth: style.textStrokeWidth ? style.textStrokeWidth * style.fontSize * 0.03 : 0
279
289
  };
280
290
  this.path = path;
281
291
  this.glyphBox = this.getGlyphBoundingBox();
@@ -453,6 +463,7 @@ class Measurer {
453
463
  "fontSize",
454
464
  "letterSpacing",
455
465
  "textStrokeWidth",
466
+ "textIndent",
456
467
  "shadowOffsetX",
457
468
  "shadowOffsetY",
458
469
  "shadowBlur"
@@ -778,7 +789,7 @@ function highlight() {
778
789
  characters.forEach((character) => {
779
790
  const { isVertical, computedStyle: style } = character;
780
791
  if (!isNone(style.highlightImage) && character.glyphBox) {
781
- if (style.highlightSize !== "1rem" && prevStyle?.highlightImage === style.highlightImage && prevStyle?.highlightSize === style.highlightSize && prevStyle?.highlightStrokeWidth === style.highlightStrokeWidth && prevStyle?.highlightOverflow === style.highlightOverflow && group.length && (isVertical ? group[0].inlineBox.left === character.inlineBox.left : group[0].inlineBox.top === character.inlineBox.top) && group[0].fontSize === character.fontSize) {
792
+ if (style.highlightSize !== "1rem" && prevStyle?.highlightImage === style.highlightImage && prevStyle?.highlightSize === style.highlightSize && prevStyle?.highlightStrokeWidth === style.highlightStrokeWidth && prevStyle?.highlightOverflow === style.highlightOverflow && group?.length && (isVertical ? group[0].inlineBox.left === character.inlineBox.left : group[0].inlineBox.top === character.inlineBox.top) && group[0].fontSize === character.fontSize) {
782
793
  group.push(character);
783
794
  } else {
784
795
  group = [];
@@ -880,57 +891,50 @@ function listStyle() {
880
891
  paths,
881
892
  update: (text) => {
882
893
  paths.length = 0;
883
- const { paragraphs, computedStyle: style, isVertical } = text;
884
- let fontSize = text.fontSize;
885
- paragraphs.forEach((p) => {
886
- p.fragments.forEach((f) => {
887
- f.characters.forEach((c) => {
888
- fontSize = Math.max(fontSize, c.computedStyle.fontSize);
889
- });
890
- });
891
- });
892
- let listStyleSize = style.listStyleSize;
893
- let image;
894
- if (!isNone(style.listStyleImage)) {
895
- image = style.listStyleImage;
896
- } else if (!isNone(style.listStyleType)) {
897
- const r = fontSize * 0.38 / 2;
898
- listStyleSize = listStyleSize === "cover" ? r * 2 : listStyleSize;
899
- switch (style.listStyleType) {
900
- case "disc":
901
- image = `<svg width="${r * 2}" height="${r * 2}" xmlns="http://www.w3.org/2000/svg">
894
+ const { paragraphs, isVertical, fontSize } = text;
895
+ const padding = fontSize * 0.45;
896
+ paragraphs.forEach((paragraph) => {
897
+ const { computedStyle: style } = paragraph;
898
+ let listStyleSize = style.listStyleSize;
899
+ let image;
900
+ if (!isNone(style.listStyleImage)) {
901
+ image = style.listStyleImage;
902
+ } else if (!isNone(style.listStyleType)) {
903
+ const r = fontSize * 0.38 / 2;
904
+ listStyleSize = listStyleSize === "cover" ? r * 2 : listStyleSize;
905
+ switch (style.listStyleType) {
906
+ case "disc":
907
+ image = `<svg width="${r * 2}" height="${r * 2}" xmlns="http://www.w3.org/2000/svg">
902
908
  <circle cx="${r}" cy="${r}" r="${r}" fill="${style.color}" />
903
909
  </svg>`;
904
- break;
910
+ break;
911
+ }
905
912
  }
906
- }
907
- if (!image) {
908
- return;
909
- }
910
- const padding = fontSize * 0.45;
911
- const imagePaths = modernPath2d.parseSvg(image);
912
- const imageBox = modernPath2d.getPathsBoundingBox(imagePaths);
913
- paragraphs.forEach((paragraph) => {
913
+ if (!image) {
914
+ return;
915
+ }
916
+ const imagePaths = modernPath2d.parseSvg(image);
917
+ const imageBox = modernPath2d.getPathsBoundingBox(imagePaths);
914
918
  const box = paragraph.lineBox;
915
- const cBox = paragraph.fragments[0].inlineBox;
916
- if (cBox) {
919
+ const fBox = paragraph.fragments[0].inlineBox;
920
+ if (fBox) {
917
921
  const m = new modernPath2d.Matrix3();
918
922
  if (isVertical) {
919
- const scale = parseScale(listStyleSize, style.fontSize, fontSize);
923
+ const scale = parseScale(listStyleSize, fontSize, fontSize);
920
924
  const reScale = fontSize / imageBox.height * scale;
921
925
  m.translate(-imageBox.left, -imageBox.top);
922
926
  m.rotate(Math.PI / 2);
923
927
  m.scale(reScale, reScale);
924
928
  m.translate(fontSize / 2 - imageBox.height * reScale / 2, 0);
925
- m.translate(box.left + (box.width - fontSize) / 2, cBox.top - padding);
929
+ m.translate(box.left + (box.width - fontSize) / 2, fBox.top - padding);
926
930
  } else {
927
- const scale = parseScale(listStyleSize, style.fontSize, fontSize);
931
+ const scale = parseScale(listStyleSize, fontSize, fontSize);
928
932
  const reScale = fontSize / imageBox.height * scale;
929
933
  m.translate(-imageBox.left, -imageBox.top);
930
934
  m.translate(-imageBox.width, 0);
931
935
  m.scale(reScale, reScale);
932
936
  m.translate(0, fontSize / 2 - imageBox.height * reScale / 2);
933
- m.translate(cBox.left - padding, box.top + (box.height - fontSize) / 2);
937
+ m.translate(fBox.left - padding, box.top + (box.height - fontSize) / 2);
934
938
  }
935
939
  paths.push(...imagePaths.map((p) => p.clone().matrix(m)));
936
940
  }
@@ -1020,8 +1024,8 @@ function render() {
1020
1024
  }
1021
1025
  function getTransform2D(text, style) {
1022
1026
  const { fontSize, renderBoundingBox } = text;
1023
- const offsetX = (style.offsetX ?? 0) * fontSize;
1024
- const offsetY = (style.offsetY ?? 0) * fontSize;
1027
+ const translateX = (style.translateX ?? 0) * fontSize;
1028
+ const translateY = (style.translateY ?? 0) * fontSize;
1025
1029
  const PI_2 = Math.PI * 2;
1026
1030
  const skewX = (style.skewX ?? 0) / 360 * PI_2;
1027
1031
  const skewY = (style.skewY ?? 0) / 360 * PI_2;
@@ -1029,7 +1033,7 @@ function getTransform2D(text, style) {
1029
1033
  const centerX = left + width / 2;
1030
1034
  const centerY = top + height / 2;
1031
1035
  tempM1.identity();
1032
- tempM2.makeTranslation(offsetX, offsetY);
1036
+ tempM2.makeTranslation(translateX, translateY);
1033
1037
  tempM1.multiply(tempM2);
1034
1038
  tempM2.makeTranslation(centerX, centerY);
1035
1039
  tempM1.multiply(tempM2);
@@ -1049,7 +1053,7 @@ var __publicField = (obj, key, value) => {
1049
1053
  const defaultTextStyles = {
1050
1054
  writingMode: "horizontal-tb",
1051
1055
  verticalAlign: "baseline",
1052
- lineHeight: 1,
1056
+ lineHeight: 1.2,
1053
1057
  letterSpacing: 0,
1054
1058
  // font
1055
1059
  fontSize: 14,
@@ -1060,21 +1064,16 @@ const defaultTextStyles = {
1060
1064
  // text
1061
1065
  textWrap: "wrap",
1062
1066
  textAlign: "start",
1067
+ textIndent: 0,
1063
1068
  textTransform: "none",
1064
1069
  textOrientation: "mixed",
1065
- // color
1066
- color: "#000",
1067
- backgroundColor: "rgba(0, 0, 0, 0)",
1068
- // text
1069
1070
  textDecoration: "none",
1070
1071
  // textStroke
1071
1072
  textStrokeWidth: 0,
1072
1073
  textStrokeColor: "#000",
1073
- // shadow
1074
- shadowColor: "rgba(0, 0, 0, 0)",
1075
- shadowOffsetX: 0,
1076
- shadowOffsetY: 0,
1077
- shadowBlur: 0,
1074
+ // color
1075
+ color: "#000",
1076
+ backgroundColor: "rgba(0, 0, 0, 0)",
1078
1077
  // listStyle
1079
1078
  listStyleType: "none",
1080
1079
  listStyleImage: "none",
@@ -1085,7 +1084,16 @@ const defaultTextStyles = {
1085
1084
  highlightImage: "none",
1086
1085
  highlightSize: "cover",
1087
1086
  highlightStrokeWidth: "100%",
1088
- highlightOverflow: "none"
1087
+ highlightOverflow: "none",
1088
+ // shadow
1089
+ shadowColor: "rgba(0, 0, 0, 0)",
1090
+ shadowOffsetX: 0,
1091
+ shadowOffsetY: 0,
1092
+ shadowBlur: 0,
1093
+ translateX: 0,
1094
+ translateY: 0,
1095
+ skewX: 0,
1096
+ skewY: 0
1089
1097
  };
1090
1098
  class Text {
1091
1099
  constructor(options = {}) {
@@ -1123,20 +1131,10 @@ class Text {
1123
1131
  }
1124
1132
  measure(dom = this.measureDom) {
1125
1133
  this.computedStyle = { ...defaultTextStyles, ...this.style };
1126
- const old = this.paragraphs;
1134
+ const oldParagraphs = this.paragraphs;
1135
+ const oldRenderBoundingBox = this.renderBoundingBox;
1127
1136
  this.paragraphs = this.parser.parse();
1128
1137
  const result = this.measurer.measure(dom);
1129
- this.paragraphs = old;
1130
- return result;
1131
- }
1132
- requestUpdate() {
1133
- this.needsUpdate = true;
1134
- return this;
1135
- }
1136
- update() {
1137
- const { paragraphs, boundingBox } = this.measure();
1138
- this.paragraphs = paragraphs;
1139
- this.boundingBox = boundingBox;
1140
1138
  const characters = this.characters;
1141
1139
  characters.forEach((c) => c.update());
1142
1140
  const plugins = [...this.plugins.values()];
@@ -1164,6 +1162,20 @@ class Text {
1164
1162
  return modernPath2d.getPathsBoundingBox(plugin.paths ?? []);
1165
1163
  }).filter(Boolean)
1166
1164
  );
1165
+ result.renderBoundingBox = this.renderBoundingBox;
1166
+ this.paragraphs = oldParagraphs;
1167
+ this.renderBoundingBox = oldRenderBoundingBox;
1168
+ return result;
1169
+ }
1170
+ requestUpdate() {
1171
+ this.needsUpdate = true;
1172
+ return this;
1173
+ }
1174
+ update() {
1175
+ const { paragraphs, boundingBox, renderBoundingBox } = this.measure();
1176
+ this.paragraphs = paragraphs;
1177
+ this.boundingBox = boundingBox;
1178
+ this.renderBoundingBox = renderBoundingBox;
1167
1179
  return this;
1168
1180
  }
1169
1181
  render(options) {
@@ -1195,6 +1207,14 @@ class Text {
1195
1207
  }
1196
1208
  }
1197
1209
 
1210
+ function measureText(options) {
1211
+ return new Text(options).measure();
1212
+ }
1213
+
1214
+ function renderText(options) {
1215
+ return new Text(options).render(options);
1216
+ }
1217
+
1198
1218
  exports.Character = Character;
1199
1219
  exports.Fragment = Fragment;
1200
1220
  exports.Measurer = Measurer;
@@ -1209,8 +1229,10 @@ exports.getTransform2D = getTransform2D;
1209
1229
  exports.highlight = highlight;
1210
1230
  exports.isNone = isNone;
1211
1231
  exports.listStyle = listStyle;
1232
+ exports.measureText = measureText;
1212
1233
  exports.parseColor = parseColor;
1213
1234
  exports.render = render;
1235
+ exports.renderText = renderText;
1214
1236
  exports.setupView = setupView;
1215
1237
  exports.uploadColor = uploadColor;
1216
1238
  exports.uploadColors = uploadColors;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { BoundingBox, Vector2, Path2D, VectorLike, Matrix3 } from 'modern-path2d';
1
+ import { BoundingBox, Path2D, Vector2, VectorLike, Matrix3 } from 'modern-path2d';
2
2
  export * from 'modern-path2d';
3
3
  import { Sfnt, GlyphPathCommand } from 'modern-font';
4
4
  export * from 'modern-font';
@@ -22,46 +22,49 @@ type HighlightImage = 'none' | string;
22
22
  type HighlightSize = 'cover' | Sizeable;
23
23
  type HighlightStrokeWidth = Sizeable;
24
24
  type HighlightOverflow = 'none' | 'visible' | 'hidden';
25
- interface TextLayoutStyle {
25
+ interface TextLineStyle {
26
26
  writingMode: WritingMode;
27
- verticalAlign: VerticalAlign;
27
+ textWrap: TextWrap;
28
+ textAlign: TextAlign;
29
+ textIndent: number;
28
30
  lineHeight: number;
31
+ listStyleType: ListStyleType;
32
+ listStyleImage: ListStyleImage;
33
+ listStyleSize: ListStyleSize;
34
+ listStylePosition: ListStylePosition;
35
+ }
36
+ interface TextInlineStyle {
37
+ verticalAlign: VerticalAlign;
29
38
  letterSpacing: number;
30
39
  fontSize: number;
31
40
  fontWeight: FontWeight;
32
41
  fontFamily: string;
33
42
  fontStyle: FontStyle;
34
43
  fontKerning?: FontKerning;
35
- textWrap: TextWrap;
36
- textAlign: TextAlign;
37
44
  textTransform: TextTransform;
38
45
  textOrientation: TextOrientation;
46
+ textDecoration: TextDecoration;
47
+ highlightReferImage: HighlightImage;
48
+ highlightImage: HighlightImage;
49
+ highlightSize: HighlightSize;
50
+ highlightStrokeWidth: HighlightStrokeWidth;
51
+ highlightOverflow: HighlightOverflow;
39
52
  }
40
53
  interface TextDrawStyle {
41
54
  color: string | CanvasGradient | CanvasPattern;
42
55
  backgroundColor: string | CanvasGradient | CanvasPattern;
43
- textDecoration: TextDecoration;
44
56
  textStrokeWidth: number;
45
57
  textStrokeColor: string | CanvasGradient | CanvasPattern;
46
58
  shadowColor: string;
47
59
  shadowOffsetX: number;
48
60
  shadowOffsetY: number;
49
61
  shadowBlur: number;
62
+ translateX: number;
63
+ translateY: number;
64
+ skewX: number;
65
+ skewY: number;
50
66
  }
51
- interface TextListStyle {
52
- listStyleType: ListStyleType;
53
- listStyleImage: ListStyleImage;
54
- listStyleSize: ListStyleSize;
55
- listStylePosition: ListStylePosition;
56
- }
57
- interface TextHighlightStyle {
58
- highlightReferImage: HighlightImage;
59
- highlightImage: HighlightImage;
60
- highlightSize: HighlightSize;
61
- highlightStrokeWidth: HighlightStrokeWidth;
62
- highlightOverflow: HighlightOverflow;
63
- }
64
- interface TextStyle extends TextLayoutStyle, TextDrawStyle, TextListStyle, TextHighlightStyle {
67
+ interface TextStyle extends TextLineStyle, TextInlineStyle, TextDrawStyle {
65
68
  }
66
69
  interface FragmentContent extends Partial<TextStyle> {
67
70
  content: string;
@@ -72,7 +75,7 @@ interface ParagraphContent extends Partial<TextStyle> {
72
75
  type TextContent = string | FragmentContent | ParagraphContent | (string | FragmentContent | ParagraphContent | (string | FragmentContent)[])[];
73
76
 
74
77
  declare function parseColor(ctx: CanvasRenderingContext2D, source: string | CanvasGradient | CanvasPattern, box: BoundingBox): string | CanvasGradient | CanvasPattern;
75
- declare function uploadColor(style: Partial<TextDrawStyle>, box: BoundingBox, ctx: CanvasRenderingContext2D): void;
78
+ declare function uploadColor(style: Partial<TextStyle>, box: BoundingBox, ctx: CanvasRenderingContext2D): void;
76
79
  interface LinearGradient {
77
80
  x0: number;
78
81
  y0: number;
@@ -84,6 +87,16 @@ interface LinearGradient {
84
87
  }[];
85
88
  }
86
89
 
90
+ interface DrawShapePathsOptions extends Partial<TextStyle> {
91
+ ctx: CanvasRenderingContext2D;
92
+ path: Path2D;
93
+ fontSize: number;
94
+ clipRect?: BoundingBox;
95
+ }
96
+ declare function drawPath(options: DrawShapePathsOptions): void;
97
+
98
+ declare function setupView(ctx: CanvasRenderingContext2D, pixelRatio: number, boundingBox: BoundingBox): void;
99
+
87
100
  declare class Fragment {
88
101
  content: string;
89
102
  style: Partial<TextStyle>;
@@ -128,7 +141,7 @@ declare class Character {
128
141
  max: Vector2;
129
142
  } | undefined;
130
143
  getGlyphBoundingBox(withStyle?: boolean): BoundingBox | undefined;
131
- drawTo(ctx: CanvasRenderingContext2D, config?: Partial<TextEffect>): void;
144
+ drawTo(ctx: CanvasRenderingContext2D, config?: Partial<TextStyle>): void;
132
145
  }
133
146
 
134
147
  declare class Paragraph {
@@ -170,7 +183,7 @@ interface MeasuredCharacter {
170
183
  textHeight: number;
171
184
  textWidth: number;
172
185
  }
173
- interface MeasuredResult {
186
+ interface MeasureDomResult {
174
187
  paragraphs: Paragraph[];
175
188
  boundingBox: BoundingBox;
176
189
  }
@@ -197,10 +210,22 @@ declare class Measurer {
197
210
  fragments: MeasuredFragment[];
198
211
  characters: MeasuredCharacter[];
199
212
  };
200
- measureDom(dom: HTMLElement): MeasuredResult;
201
- measure(dom?: HTMLElement): MeasuredResult;
213
+ measureDom(dom: HTMLElement): MeasureDomResult;
214
+ measure(dom?: HTMLElement): MeasureDomResult;
202
215
  }
203
216
 
217
+ type PromiseLike<T> = T | Promise<T>;
218
+ interface Plugin {
219
+ name: string;
220
+ paths?: Path2D[];
221
+ getBoundingBox?: (text: Text) => BoundingBox | undefined;
222
+ updateOrder?: number;
223
+ update?: (text: Text) => PromiseLike<void>;
224
+ renderOrder?: number;
225
+ render?: (ctx: CanvasRenderingContext2D, text: Text) => PromiseLike<void>;
226
+ }
227
+ declare function definePlugin(options: Plugin): Plugin;
228
+
204
229
  declare class Parser {
205
230
  protected _text: Text;
206
231
  constructor(_text: Text);
@@ -215,48 +240,19 @@ interface TextOptions {
215
240
  content?: TextContent;
216
241
  style?: Partial<TextStyle>;
217
242
  measureDom?: HTMLElement;
218
- effects?: TextEffect[];
243
+ effects?: Partial<TextStyle>[];
219
244
  }
245
+ type MeasureResult = MeasureDomResult & {
246
+ renderBoundingBox: BoundingBox;
247
+ };
220
248
  declare const defaultTextStyles: TextStyle;
221
249
  declare class Text {
222
250
  content: TextContent;
223
251
  style: Partial<TextStyle>;
224
- effects?: TextEffect[];
252
+ effects?: Partial<TextStyle>[];
225
253
  measureDom?: HTMLElement;
226
254
  needsUpdate: boolean;
227
- computedStyle: {
228
- writingMode: WritingMode;
229
- verticalAlign: VerticalAlign;
230
- lineHeight: number;
231
- letterSpacing: number;
232
- fontSize: number;
233
- fontWeight: FontWeight;
234
- fontFamily: string;
235
- fontStyle: FontStyle;
236
- fontKerning?: FontKerning;
237
- textWrap: TextWrap;
238
- textAlign: TextAlign;
239
- textTransform: TextTransform;
240
- textOrientation: TextOrientation;
241
- color: string | CanvasGradient | CanvasPattern;
242
- backgroundColor: string | CanvasGradient | CanvasPattern;
243
- textDecoration: TextDecoration;
244
- textStrokeWidth: number;
245
- textStrokeColor: string | CanvasGradient | CanvasPattern;
246
- shadowColor: string;
247
- shadowOffsetX: number;
248
- shadowOffsetY: number;
249
- shadowBlur: number;
250
- listStyleType: ListStyleType;
251
- listStyleImage: ListStyleImage;
252
- listStyleSize: ListStyleSize;
253
- listStylePosition: ListStylePosition;
254
- highlightReferImage: HighlightImage;
255
- highlightImage: HighlightImage;
256
- highlightSize: HighlightSize;
257
- highlightStrokeWidth: HighlightStrokeWidth;
258
- highlightOverflow: HighlightOverflow;
259
- };
255
+ computedStyle: TextStyle;
260
256
  paragraphs: Paragraph[];
261
257
  boundingBox: BoundingBox;
262
258
  renderBoundingBox: BoundingBox;
@@ -268,50 +264,26 @@ declare class Text {
268
264
  get characters(): Character[];
269
265
  constructor(options?: TextOptions);
270
266
  use(plugin: Plugin): this;
271
- measure(dom?: HTMLElement | undefined): MeasuredResult;
267
+ measure(dom?: HTMLElement | undefined): MeasureResult;
272
268
  requestUpdate(): this;
273
269
  update(): this;
274
270
  render(options: TextRenderOptions): this;
275
271
  }
276
272
 
277
- type PromiseLike<T> = T | Promise<T>;
278
- interface Plugin {
279
- name: string;
280
- paths?: Path2D[];
281
- getBoundingBox?: (text: Text) => BoundingBox | undefined;
282
- updateOrder?: number;
283
- update?: (text: Text) => PromiseLike<void>;
284
- renderOrder?: number;
285
- render?: (ctx: CanvasRenderingContext2D, text: Text) => PromiseLike<void>;
286
- }
287
- declare function definePlugin(options: Plugin): Plugin;
273
+ declare function uploadColors(ctx: CanvasRenderingContext2D, text: Text): void;
274
+
275
+ declare function measureText(options: TextOptions): MeasureResult;
288
276
 
289
277
  declare function highlight(): Plugin;
290
278
 
291
279
  declare function listStyle(): Plugin;
292
280
 
293
- type TextEffect = Partial<TextDrawStyle & {
294
- offsetX: number;
295
- offsetY: number;
296
- skewX: number;
297
- skewY: number;
298
- }>;
299
281
  declare function render(): Plugin;
300
- declare function getTransform2D(text: Text, style: TextEffect): Matrix3;
282
+ declare function getTransform2D(text: Text, style: Partial<TextStyle>): Matrix3;
301
283
 
302
- interface DrawShapePathsOptions extends Partial<TextEffect> {
303
- ctx: CanvasRenderingContext2D;
304
- path: Path2D;
305
- fontSize: number;
306
- clipRect?: BoundingBox;
307
- }
308
- declare function drawPath(options: DrawShapePathsOptions): void;
309
-
310
- declare function setupView(ctx: CanvasRenderingContext2D, pixelRatio: number, boundingBox: BoundingBox): void;
311
-
312
- declare function uploadColors(ctx: CanvasRenderingContext2D, text: Text): void;
284
+ declare function renderText(options: TextOptions & TextRenderOptions): Text;
313
285
 
314
286
  declare function isNone(val: string | undefined): boolean;
315
287
  declare function filterEmpty(val: Record<string, any> | undefined): Record<string, any> | undefined;
316
288
 
317
- export { Character, type DrawShapePathsOptions, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type HighlightImage, type HighlightOverflow, type HighlightSize, type HighlightStrokeWidth, type LinearGradient, type ListStyleImage, type ListStylePosition, type ListStyleSize, type ListStyleType, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, type MeasuredResult, Measurer, Paragraph, type ParagraphContent, Parser, type Plugin, type Sizeable, Text, type TextAlign, type TextContent, type TextDecoration, type TextDrawStyle, type TextEffect, type TextHighlightStyle, type TextLayoutStyle, type TextListStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, highlight, isNone, listStyle, parseColor, render, setupView, uploadColor, uploadColors };
289
+ export { Character, type DrawShapePathsOptions, type FontKerning, type FontStyle, type FontWeight, Fragment, type FragmentContent, type HighlightImage, type HighlightOverflow, type HighlightSize, type HighlightStrokeWidth, type LinearGradient, type ListStyleImage, type ListStylePosition, type ListStyleSize, type ListStyleType, type MeasureDomResult, type MeasureResult, type MeasuredCharacter, type MeasuredFragment, type MeasuredParagraph, Measurer, Paragraph, type ParagraphContent, Parser, type Plugin, type Sizeable, Text, type TextAlign, type TextContent, type TextDecoration, type TextDrawStyle, type TextInlineStyle, type TextLineStyle, type TextOptions, type TextOrientation, type TextRenderOptions, type TextStyle, type TextTransform, type TextWrap, type VerticalAlign, type WritingMode, defaultTextStyles, definePlugin, drawPath, filterEmpty, getTransform2D, highlight, isNone, listStyle, measureText, parseColor, render, renderText, setupView, uploadColor, uploadColors };