modern-text 1.9.1 → 1.10.0
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 +4 -8
- package/dist/index.d.cts +19 -44
- package/dist/index.d.mts +19 -44
- package/dist/index.d.ts +19 -44
- package/dist/index.js +8 -8
- package/dist/index.mjs +2 -2
- package/dist/shared/{modern-text.B2pcGP3X.mjs → modern-text.BD1kUWDw.mjs} +229 -204
- package/dist/shared/{modern-text.BmTeQ51D.cjs → modern-text.BUyl2x8m.cjs} +229 -208
- package/dist/shared/{modern-text.WbWB6f3d.d.ts → modern-text.D_VtaVfs.d.cts} +52 -33
- package/dist/shared/{modern-text.WbWB6f3d.d.cts → modern-text.D_VtaVfs.d.mts} +52 -33
- package/dist/shared/{modern-text.WbWB6f3d.d.mts → modern-text.D_VtaVfs.d.ts} +52 -33
- package/dist/web-components/index.cjs +1 -1
- package/dist/web-components/index.d.cts +2 -2
- package/dist/web-components/index.d.mts +2 -2
- package/dist/web-components/index.d.ts +2 -2
- package/dist/web-components/index.mjs +1 -1
- package/package.json +7 -16
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as Text } from './shared/modern-text.
|
|
2
|
-
export { C as Character, F as Fragment, M as Measurer, P as Paragraph,
|
|
1
|
+
import { T as Text } from './shared/modern-text.BD1kUWDw.mjs';
|
|
2
|
+
export { C as Canvas2DRenderer, a as Character, F as Fragment, M as Measurer, P as Paragraph, b as backgroundPlugin, f as createSvgLoader, i as createSvgParser, d as definePlugin, q as filterEmpty, g as getHighlightStyle, c as getTransform2D, n as hexToRgb, h as highlightPlugin, k as isEqualObject, m as isEqualValue, l as listStylePlugin, o as outlinePlugin, j as parseColormap, p as parseValueNumber, r as renderPlugin, t as textDecorationPlugin, e as textDefaultStyle } from './shared/modern-text.BD1kUWDw.mjs';
|
|
3
3
|
import 'modern-idoc';
|
|
4
4
|
import 'modern-path2d';
|
|
5
5
|
import 'modern-font';
|
|
@@ -1,107 +1,176 @@
|
|
|
1
|
-
import { isNone, getDefaultStyle, Reactivable, normalizeText, property } from 'modern-idoc';
|
|
2
|
-
import { Path2D, BoundingBox,
|
|
1
|
+
import { isGradient, parseGradient, isNone, getDefaultStyle, Reactivable, normalizeText, property } from 'modern-idoc';
|
|
2
|
+
import { setCanvasContext, Path2D, BoundingBox, svgToDom, svgToPath2DSet, Path2DSet, Vector2, Matrix3 } from 'modern-path2d';
|
|
3
3
|
import { fonts } from 'modern-font';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
stops.forEach((stop) => gradient.addColorStop(stop.offset, stop.color));
|
|
10
|
-
return gradient;
|
|
5
|
+
class Canvas2DRenderer {
|
|
6
|
+
constructor(text, context) {
|
|
7
|
+
this.text = text;
|
|
8
|
+
this.context = context;
|
|
11
9
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
10
|
+
pixelRatio = window?.devicePixelRatio || 1;
|
|
11
|
+
_setupView = () => {
|
|
12
|
+
const pixelRatio = this.pixelRatio;
|
|
13
|
+
const ctx = this.context;
|
|
14
|
+
const { left, top, width, height } = this.text.boundingBox;
|
|
15
|
+
const view = ctx.canvas;
|
|
16
|
+
view.dataset.viewBox = String(`${left} ${top} ${width} ${height}`);
|
|
17
|
+
view.dataset.pixelRatio = String(pixelRatio);
|
|
18
|
+
const canvasWidth = width;
|
|
19
|
+
const canvasHeight = height;
|
|
20
|
+
view.width = Math.max(1, Math.ceil(canvasWidth * pixelRatio));
|
|
21
|
+
view.height = Math.max(1, Math.ceil(canvasHeight * pixelRatio));
|
|
22
|
+
view.style.width = `${canvasWidth}px`;
|
|
23
|
+
view.style.height = `${canvasHeight}px`;
|
|
24
|
+
ctx.clearRect(0, 0, view.width, view.height);
|
|
25
|
+
ctx.scale(pixelRatio, pixelRatio);
|
|
26
|
+
ctx.translate(-left, -top);
|
|
27
|
+
};
|
|
28
|
+
_setupColors = () => {
|
|
29
|
+
const { paragraphs, computedStyle, glyphBox } = this.text;
|
|
30
|
+
this.uploadColor(computedStyle, glyphBox);
|
|
31
|
+
paragraphs.forEach((paragraph) => {
|
|
32
|
+
this.uploadColor(paragraph.computedStyle, paragraph.lineBox);
|
|
33
|
+
paragraph.fragments.forEach((fragment) => {
|
|
34
|
+
this.uploadColor(fragment.computedStyle, fragment.inlineBox);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
setup = () => {
|
|
39
|
+
this._setupView();
|
|
40
|
+
this._setupColors();
|
|
41
|
+
return this;
|
|
42
|
+
};
|
|
43
|
+
_parseColor = (source, box) => {
|
|
44
|
+
if (typeof source === "string" && isGradient(source)) {
|
|
45
|
+
const gradient = parseGradient(source)[0];
|
|
46
|
+
if (gradient) {
|
|
47
|
+
switch (gradient.type) {
|
|
48
|
+
case "linear-gradient": {
|
|
49
|
+
let deg = 0;
|
|
50
|
+
if (gradient.orientation) {
|
|
51
|
+
switch (gradient.orientation.type) {
|
|
52
|
+
case "angular":
|
|
53
|
+
deg = Number(gradient.orientation.value);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const { left, top, width, height } = box;
|
|
58
|
+
const rad = deg * Math.PI / 180;
|
|
59
|
+
const offsetX = width * Math.sin(rad);
|
|
60
|
+
const offsetY = height * Math.cos(rad);
|
|
61
|
+
const canvasGradient = this.context.createLinearGradient(
|
|
62
|
+
left + width / 2 - offsetX,
|
|
63
|
+
top + height / 2 + offsetY,
|
|
64
|
+
left + width / 2 + offsetX,
|
|
65
|
+
top + height / 2 - offsetY
|
|
66
|
+
);
|
|
67
|
+
gradient.colorStops.forEach((colorStop) => {
|
|
68
|
+
let offset = 0;
|
|
69
|
+
if (colorStop.length) {
|
|
70
|
+
switch (colorStop.length.type) {
|
|
71
|
+
case "%":
|
|
72
|
+
offset = Number(colorStop.length.value) / 100;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
switch (colorStop.type) {
|
|
77
|
+
case "rgb":
|
|
78
|
+
canvasGradient.addColorStop(offset, `rgb(${colorStop.value.join(", ")})`);
|
|
79
|
+
break;
|
|
80
|
+
case "rgba":
|
|
81
|
+
canvasGradient.addColorStop(offset, `rgba(${colorStop.value.join(", ")})`);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return canvasGradient;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
45
88
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
color
|
|
49
|
-
};
|
|
50
|
-
})
|
|
89
|
+
}
|
|
90
|
+
return source;
|
|
51
91
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
fill: options.color ?? pathStyle.fill,
|
|
62
|
-
stroke: options.textStrokeColor ?? pathStyle.stroke,
|
|
63
|
-
strokeWidth: options.textStrokeWidth ? options.textStrokeWidth * fontSize : pathStyle.strokeWidth,
|
|
64
|
-
strokeLinecap: "round",
|
|
65
|
-
strokeLinejoin: "round",
|
|
66
|
-
shadowOffsetX: (options.shadowOffsetX ?? 0) * fontSize,
|
|
67
|
-
shadowOffsetY: (options.shadowOffsetY ?? 0) * fontSize,
|
|
68
|
-
shadowBlur: (options.shadowBlur ?? 0) * fontSize,
|
|
69
|
-
shadowColor: options.shadowColor
|
|
92
|
+
_uploadedStyles = [
|
|
93
|
+
"color",
|
|
94
|
+
"backgroundColor",
|
|
95
|
+
"textStrokeColor"
|
|
96
|
+
];
|
|
97
|
+
uploadColor = (style, box) => {
|
|
98
|
+
this._uploadedStyles.forEach((key) => {
|
|
99
|
+
style[key] = this._parseColor(style[key], box);
|
|
100
|
+
});
|
|
70
101
|
};
|
|
71
|
-
|
|
72
|
-
ctx
|
|
73
|
-
|
|
102
|
+
drawPath = (path, options = {}) => {
|
|
103
|
+
const ctx = this.context;
|
|
104
|
+
const {
|
|
105
|
+
fontSize = this.text.computedStyle.fontSize,
|
|
106
|
+
clipRect
|
|
107
|
+
} = options;
|
|
108
|
+
ctx.save();
|
|
74
109
|
ctx.beginPath();
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function uploadColors(ctx, text) {
|
|
97
|
-
const { paragraphs, computedStyle: style, glyphBox } = text;
|
|
98
|
-
uploadColor(style, glyphBox, ctx);
|
|
99
|
-
paragraphs.forEach((paragraph) => {
|
|
100
|
-
uploadColor(paragraph.computedStyle, paragraph.lineBox, ctx);
|
|
101
|
-
paragraph.fragments.forEach((fragment) => {
|
|
102
|
-
uploadColor(fragment.computedStyle, fragment.inlineBox, ctx);
|
|
110
|
+
if (clipRect) {
|
|
111
|
+
ctx.rect(clipRect.left, clipRect.top, clipRect.width, clipRect.height);
|
|
112
|
+
ctx.clip();
|
|
113
|
+
ctx.beginPath();
|
|
114
|
+
}
|
|
115
|
+
const pathStyle = path.style;
|
|
116
|
+
const stroke = options.textStrokeColor ?? pathStyle.stroke;
|
|
117
|
+
const strokeWidth = options.textStrokeWidth ? options.textStrokeWidth * fontSize : pathStyle.strokeWidth;
|
|
118
|
+
path.drawTo(ctx, {
|
|
119
|
+
...pathStyle,
|
|
120
|
+
fill: options.color ?? pathStyle.fill,
|
|
121
|
+
stroke: strokeWidth === void 0 || strokeWidth > 0 ? stroke : void 0,
|
|
122
|
+
strokeWidth,
|
|
123
|
+
strokeLinecap: "round",
|
|
124
|
+
strokeLinejoin: "round",
|
|
125
|
+
shadowOffsetX: (options.shadowOffsetX ?? 0) * fontSize,
|
|
126
|
+
shadowOffsetY: (options.shadowOffsetY ?? 0) * fontSize,
|
|
127
|
+
shadowBlur: (options.shadowBlur ?? 0) * fontSize,
|
|
128
|
+
shadowColor: options.shadowColor
|
|
103
129
|
});
|
|
104
|
-
|
|
130
|
+
ctx.restore();
|
|
131
|
+
};
|
|
132
|
+
drawCharacter = (character, userStyle = {}) => {
|
|
133
|
+
const ctx = this.context;
|
|
134
|
+
const {
|
|
135
|
+
computedStyle,
|
|
136
|
+
path,
|
|
137
|
+
glyphBox,
|
|
138
|
+
isVertical,
|
|
139
|
+
content,
|
|
140
|
+
inlineBox,
|
|
141
|
+
baseline
|
|
142
|
+
} = character;
|
|
143
|
+
const style = {
|
|
144
|
+
...computedStyle,
|
|
145
|
+
...userStyle
|
|
146
|
+
};
|
|
147
|
+
if (glyphBox) {
|
|
148
|
+
this.drawPath(path, style);
|
|
149
|
+
} else {
|
|
150
|
+
ctx.save();
|
|
151
|
+
ctx.beginPath();
|
|
152
|
+
const pathStyle = path.style;
|
|
153
|
+
setCanvasContext(ctx, {
|
|
154
|
+
...pathStyle,
|
|
155
|
+
fill: style.color ?? pathStyle.fill,
|
|
156
|
+
stroke: style.textStrokeColor ?? pathStyle.stroke,
|
|
157
|
+
strokeWidth: style.textStrokeWidth ? style.textStrokeWidth * style.fontSize : pathStyle.strokeWidth,
|
|
158
|
+
shadowOffsetX: (style.shadowOffsetX ?? 0) * style.fontSize,
|
|
159
|
+
shadowOffsetY: (style.shadowOffsetY ?? 0) * style.fontSize,
|
|
160
|
+
shadowBlur: (style.shadowBlur ?? 0) * style.fontSize,
|
|
161
|
+
shadowColor: style.shadowColor
|
|
162
|
+
});
|
|
163
|
+
ctx.font = `${style.fontSize}px ${style.fontFamily}`;
|
|
164
|
+
if (isVertical) {
|
|
165
|
+
ctx.textBaseline = "middle";
|
|
166
|
+
ctx.fillText(content, inlineBox.left, inlineBox.top + inlineBox.height / 2);
|
|
167
|
+
} else {
|
|
168
|
+
ctx.textBaseline = "alphabetic";
|
|
169
|
+
ctx.fillText(content, inlineBox.left, inlineBox.top + baseline);
|
|
170
|
+
}
|
|
171
|
+
ctx.restore();
|
|
172
|
+
}
|
|
173
|
+
};
|
|
105
174
|
}
|
|
106
175
|
|
|
107
176
|
const set1 = /* @__PURE__ */ new Set(["\xA9", "\xAE", "\xF7"]);
|
|
@@ -361,46 +430,9 @@ class Character {
|
|
|
361
430
|
const { min, max } = minMax;
|
|
362
431
|
return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
363
432
|
}
|
|
364
|
-
drawTo(ctx, config = {}) {
|
|
365
|
-
const style = this.computedStyle;
|
|
366
|
-
const options = {
|
|
367
|
-
ctx,
|
|
368
|
-
path: this.path,
|
|
369
|
-
fontSize: style.fontSize,
|
|
370
|
-
color: style.color,
|
|
371
|
-
...config
|
|
372
|
-
};
|
|
373
|
-
if (this.glyphBox) {
|
|
374
|
-
drawPath(options);
|
|
375
|
-
} else {
|
|
376
|
-
ctx.save();
|
|
377
|
-
ctx.beginPath();
|
|
378
|
-
const pathStyle = this.path.style;
|
|
379
|
-
const _style = {
|
|
380
|
-
...pathStyle,
|
|
381
|
-
fill: options.color ?? pathStyle.fill,
|
|
382
|
-
stroke: options.textStrokeColor ?? pathStyle.stroke,
|
|
383
|
-
strokeWidth: options.textStrokeWidth ? options.textStrokeWidth * options.fontSize : pathStyle.strokeWidth,
|
|
384
|
-
shadowOffsetX: (options.shadowOffsetX ?? 0) * options.fontSize,
|
|
385
|
-
shadowOffsetY: (options.shadowOffsetY ?? 0) * options.fontSize,
|
|
386
|
-
shadowBlur: (options.shadowBlur ?? 0) * options.fontSize,
|
|
387
|
-
shadowColor: options.shadowColor
|
|
388
|
-
};
|
|
389
|
-
setCanvasContext(ctx, _style);
|
|
390
|
-
ctx.font = `${options.fontSize}px ${options.fontFamily}`;
|
|
391
|
-
if (this.isVertical) {
|
|
392
|
-
ctx.textBaseline = "middle";
|
|
393
|
-
ctx.fillText(this.content, this.inlineBox.left, this.inlineBox.top + this.inlineBox.height / 2);
|
|
394
|
-
} else {
|
|
395
|
-
ctx.textBaseline = "alphabetic";
|
|
396
|
-
ctx.fillText(this.content, this.inlineBox.left, this.inlineBox.top + this.baseline);
|
|
397
|
-
}
|
|
398
|
-
ctx.restore();
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
433
|
}
|
|
402
434
|
|
|
403
|
-
function
|
|
435
|
+
function createSvgLoader() {
|
|
404
436
|
const loaded = /* @__PURE__ */ new Map();
|
|
405
437
|
async function load(svg) {
|
|
406
438
|
if (!loaded.has(svg)) {
|
|
@@ -423,7 +455,7 @@ function createSVGLoader() {
|
|
|
423
455
|
};
|
|
424
456
|
}
|
|
425
457
|
|
|
426
|
-
function
|
|
458
|
+
function createSvgParser(loader) {
|
|
427
459
|
const parsed = /* @__PURE__ */ new Map();
|
|
428
460
|
function parse(svg) {
|
|
429
461
|
let result = parsed.get(svg);
|
|
@@ -851,8 +883,8 @@ class Measurer {
|
|
|
851
883
|
|
|
852
884
|
function backgroundPlugin() {
|
|
853
885
|
const pathSet = new Path2DSet();
|
|
854
|
-
const loader =
|
|
855
|
-
const parser =
|
|
886
|
+
const loader = createSvgLoader();
|
|
887
|
+
const parser = createSvgParser(loader);
|
|
856
888
|
return {
|
|
857
889
|
name: "background",
|
|
858
890
|
pathSet,
|
|
@@ -932,32 +964,33 @@ function backgroundPlugin() {
|
|
|
932
964
|
pathSet.paths.push(...paths);
|
|
933
965
|
},
|
|
934
966
|
renderOrder: -2,
|
|
935
|
-
render: (
|
|
967
|
+
render: (renderer) => {
|
|
968
|
+
const { text, context } = renderer;
|
|
936
969
|
const { boundingBox, computedStyle: style } = text;
|
|
937
970
|
if (!isNone(style.backgroundColor)) {
|
|
938
|
-
|
|
939
|
-
|
|
971
|
+
context.fillStyle = style.backgroundColor;
|
|
972
|
+
context.fillRect(...boundingBox.array);
|
|
940
973
|
}
|
|
941
974
|
pathSet.paths.forEach((path) => {
|
|
942
|
-
drawPath(
|
|
975
|
+
renderer.drawPath(path);
|
|
943
976
|
if (text.debug) {
|
|
944
977
|
const box = new Path2DSet([path]).getBoundingBox();
|
|
945
978
|
if (box) {
|
|
946
|
-
|
|
979
|
+
context.strokeRect(box.x, box.y, box.width, box.height);
|
|
947
980
|
}
|
|
948
981
|
}
|
|
949
982
|
});
|
|
950
983
|
text.paragraphs.forEach((p) => {
|
|
951
984
|
const { lineBox, style: style2 } = p;
|
|
952
985
|
if (!isNone(style2.backgroundColor)) {
|
|
953
|
-
|
|
954
|
-
|
|
986
|
+
context.fillStyle = style2.backgroundColor;
|
|
987
|
+
context.fillRect(...lineBox.array);
|
|
955
988
|
}
|
|
956
989
|
p.fragments.forEach((f) => {
|
|
957
990
|
const { inlineBox, style: style3 } = f;
|
|
958
991
|
if (!isNone(style3.backgroundColor)) {
|
|
959
|
-
|
|
960
|
-
|
|
992
|
+
context.fillStyle = style3.backgroundColor;
|
|
993
|
+
context.fillRect(...inlineBox.array);
|
|
961
994
|
}
|
|
962
995
|
});
|
|
963
996
|
});
|
|
@@ -987,8 +1020,8 @@ function getHighlightStyle(style) {
|
|
|
987
1020
|
function highlightPlugin() {
|
|
988
1021
|
const pathSet = new Path2DSet();
|
|
989
1022
|
const clipRects = [];
|
|
990
|
-
const loader =
|
|
991
|
-
const parser =
|
|
1023
|
+
const loader = createSvgLoader();
|
|
1024
|
+
const parser = createSvgParser(loader);
|
|
992
1025
|
return definePlugin({
|
|
993
1026
|
name: "highlight",
|
|
994
1027
|
pathSet,
|
|
@@ -1231,18 +1264,14 @@ function highlightPlugin() {
|
|
|
1231
1264
|
});
|
|
1232
1265
|
return BoundingBox.from(...boundingBoxs);
|
|
1233
1266
|
},
|
|
1234
|
-
render: (
|
|
1267
|
+
render: (renderer) => {
|
|
1268
|
+
const { text, context } = renderer;
|
|
1235
1269
|
pathSet.paths.forEach((path, index) => {
|
|
1236
|
-
drawPath({
|
|
1237
|
-
ctx,
|
|
1238
|
-
path,
|
|
1239
|
-
fontSize: text.computedStyle.fontSize,
|
|
1240
|
-
clipRect: clipRects[index]
|
|
1241
|
-
});
|
|
1270
|
+
renderer.drawPath(path, { clipRect: clipRects[index] });
|
|
1242
1271
|
if (text.debug) {
|
|
1243
1272
|
const box = new Path2DSet([path]).getBoundingBox();
|
|
1244
1273
|
if (box) {
|
|
1245
|
-
|
|
1274
|
+
context.strokeRect(box.x, box.y, box.width, box.height);
|
|
1246
1275
|
}
|
|
1247
1276
|
}
|
|
1248
1277
|
});
|
|
@@ -1357,10 +1386,10 @@ function renderPlugin() {
|
|
|
1357
1386
|
});
|
|
1358
1387
|
},
|
|
1359
1388
|
getBoundingBox: (text) => {
|
|
1360
|
-
const { characters, fontSize,
|
|
1389
|
+
const { characters, fontSize, computedEffects } = text;
|
|
1361
1390
|
const boxes = [];
|
|
1362
1391
|
characters.forEach((character) => {
|
|
1363
|
-
|
|
1392
|
+
computedEffects.forEach((style) => {
|
|
1364
1393
|
if (!character.glyphBox) {
|
|
1365
1394
|
return;
|
|
1366
1395
|
}
|
|
@@ -1386,31 +1415,37 @@ function renderPlugin() {
|
|
|
1386
1415
|
});
|
|
1387
1416
|
return boxes.length ? BoundingBox.from(...boxes) : void 0;
|
|
1388
1417
|
},
|
|
1389
|
-
render: (
|
|
1390
|
-
const {
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1418
|
+
render: (renderer) => {
|
|
1419
|
+
const { text, context } = renderer;
|
|
1420
|
+
const { paragraphs, glyphBox, computedEffects } = text;
|
|
1421
|
+
if (computedEffects.length) {
|
|
1422
|
+
computedEffects.forEach((style) => {
|
|
1423
|
+
renderer.uploadColor(style, glyphBox);
|
|
1424
|
+
context.save();
|
|
1395
1425
|
const [a, c, e, b, d, f] = getTransform2D(text, style).transpose().elements;
|
|
1396
|
-
|
|
1426
|
+
context.transform(a, b, c, d, e, f);
|
|
1397
1427
|
text.forEachCharacter((character) => {
|
|
1398
|
-
|
|
1428
|
+
renderer.drawCharacter(character, style);
|
|
1399
1429
|
});
|
|
1400
|
-
|
|
1430
|
+
context.restore();
|
|
1401
1431
|
});
|
|
1402
1432
|
} else {
|
|
1403
1433
|
paragraphs.forEach((paragraph) => {
|
|
1404
1434
|
paragraph.fragments.forEach((fragment) => {
|
|
1405
1435
|
fragment.characters.forEach((character) => {
|
|
1406
|
-
|
|
1436
|
+
renderer.drawCharacter(character);
|
|
1407
1437
|
});
|
|
1408
1438
|
});
|
|
1409
1439
|
});
|
|
1410
1440
|
}
|
|
1411
1441
|
if (text.debug) {
|
|
1412
1442
|
paragraphs.forEach((paragraph) => {
|
|
1413
|
-
|
|
1443
|
+
context.strokeRect(
|
|
1444
|
+
paragraph.lineBox.x,
|
|
1445
|
+
paragraph.lineBox.y,
|
|
1446
|
+
paragraph.lineBox.width,
|
|
1447
|
+
paragraph.lineBox.height
|
|
1448
|
+
);
|
|
1414
1449
|
});
|
|
1415
1450
|
}
|
|
1416
1451
|
}
|
|
@@ -1544,30 +1579,22 @@ function textDecorationPlugin() {
|
|
|
1544
1579
|
pathSet.paths.push(path);
|
|
1545
1580
|
});
|
|
1546
1581
|
},
|
|
1547
|
-
render: (
|
|
1548
|
-
const {
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1582
|
+
render: (renderer) => {
|
|
1583
|
+
const { text, context } = renderer;
|
|
1584
|
+
const { computedEffects } = text;
|
|
1585
|
+
if (computedEffects.length) {
|
|
1586
|
+
computedEffects.forEach((effectStyle) => {
|
|
1587
|
+
context.save();
|
|
1552
1588
|
const [a, c, e, b, d, f] = getTransform2D(text, effectStyle).transpose().elements;
|
|
1553
|
-
|
|
1589
|
+
context.transform(a, b, c, d, e, f);
|
|
1554
1590
|
pathSet.paths.forEach((path) => {
|
|
1555
|
-
drawPath(
|
|
1556
|
-
ctx,
|
|
1557
|
-
path,
|
|
1558
|
-
fontSize: style.fontSize,
|
|
1559
|
-
...effectStyle
|
|
1560
|
-
});
|
|
1591
|
+
renderer.drawPath(path, effectStyle);
|
|
1561
1592
|
});
|
|
1562
|
-
|
|
1593
|
+
context.restore();
|
|
1563
1594
|
});
|
|
1564
1595
|
} else {
|
|
1565
1596
|
pathSet.paths.forEach((path) => {
|
|
1566
|
-
drawPath(
|
|
1567
|
-
ctx,
|
|
1568
|
-
path,
|
|
1569
|
-
fontSize: style.fontSize
|
|
1570
|
-
});
|
|
1597
|
+
renderer.drawPath(path);
|
|
1571
1598
|
});
|
|
1572
1599
|
}
|
|
1573
1600
|
}
|
|
@@ -1587,6 +1614,7 @@ const textDefaultStyle = getDefaultStyle();
|
|
|
1587
1614
|
class Text extends Reactivable {
|
|
1588
1615
|
needsUpdate = true;
|
|
1589
1616
|
computedStyle = { ...textDefaultStyle };
|
|
1617
|
+
computedEffects = [];
|
|
1590
1618
|
paragraphs = [];
|
|
1591
1619
|
lineBox = new BoundingBox();
|
|
1592
1620
|
rawGlyphBox = new BoundingBox();
|
|
@@ -1631,7 +1659,7 @@ class Text extends Reactivable {
|
|
|
1631
1659
|
(options.plugins ?? []).forEach((plugin) => {
|
|
1632
1660
|
this.use(plugin);
|
|
1633
1661
|
});
|
|
1634
|
-
this.
|
|
1662
|
+
this._update();
|
|
1635
1663
|
}
|
|
1636
1664
|
use(plugin) {
|
|
1637
1665
|
this.plugins.set(plugin.name, plugin);
|
|
@@ -1650,8 +1678,9 @@ class Text extends Reactivable {
|
|
|
1650
1678
|
async load() {
|
|
1651
1679
|
await Promise.all(Array.from(this.plugins.values()).map((p) => p.load?.(this)));
|
|
1652
1680
|
}
|
|
1653
|
-
|
|
1681
|
+
_update() {
|
|
1654
1682
|
this.computedStyle = { ...textDefaultStyle, ...this.style };
|
|
1683
|
+
this.computedEffects = this.effects?.map((v) => ({ ...v })) ?? [];
|
|
1655
1684
|
const { content } = this;
|
|
1656
1685
|
const paragraphs = [];
|
|
1657
1686
|
content.forEach((p, pIndex) => {
|
|
@@ -1674,7 +1703,7 @@ class Text extends Reactivable {
|
|
|
1674
1703
|
return this;
|
|
1675
1704
|
}
|
|
1676
1705
|
createDom() {
|
|
1677
|
-
this.
|
|
1706
|
+
this._update();
|
|
1678
1707
|
return this.measurer.createDom(this.paragraphs, this.computedStyle);
|
|
1679
1708
|
}
|
|
1680
1709
|
measure(dom = this.measureDom) {
|
|
@@ -1686,7 +1715,7 @@ class Text extends Reactivable {
|
|
|
1686
1715
|
pathBox: this.pathBox,
|
|
1687
1716
|
boundingBox: this.boundingBox
|
|
1688
1717
|
};
|
|
1689
|
-
this.
|
|
1718
|
+
this._update();
|
|
1690
1719
|
const result = this.measurer.measure(this.paragraphs, this.computedStyle, dom);
|
|
1691
1720
|
this.paragraphs = result.paragraphs;
|
|
1692
1721
|
this.lineBox = result.boundingBox;
|
|
@@ -1704,7 +1733,7 @@ class Text extends Reactivable {
|
|
|
1704
1733
|
}
|
|
1705
1734
|
});
|
|
1706
1735
|
this.glyphBox = this.getGlyphBox();
|
|
1707
|
-
this.
|
|
1736
|
+
this._updatePathBox()._updateBoundingBox();
|
|
1708
1737
|
for (const key in old) {
|
|
1709
1738
|
result[key] = this[key];
|
|
1710
1739
|
this[key] = old[key];
|
|
@@ -1732,7 +1761,7 @@ class Text extends Reactivable {
|
|
|
1732
1761
|
max.y - min.y
|
|
1733
1762
|
);
|
|
1734
1763
|
}
|
|
1735
|
-
|
|
1764
|
+
_updatePathBox() {
|
|
1736
1765
|
this.pathBox = BoundingBox.from(
|
|
1737
1766
|
this.glyphBox,
|
|
1738
1767
|
...Array.from(this.plugins.values()).map((plugin) => {
|
|
@@ -1741,7 +1770,7 @@ class Text extends Reactivable {
|
|
|
1741
1770
|
);
|
|
1742
1771
|
return this;
|
|
1743
1772
|
}
|
|
1744
|
-
|
|
1773
|
+
_updateBoundingBox() {
|
|
1745
1774
|
this.boundingBox = BoundingBox.from(
|
|
1746
1775
|
this.rawGlyphBox,
|
|
1747
1776
|
this.lineBox,
|
|
@@ -1771,19 +1800,15 @@ class Text extends Reactivable {
|
|
|
1771
1800
|
if (this.needsUpdate) {
|
|
1772
1801
|
this.update();
|
|
1773
1802
|
}
|
|
1774
|
-
|
|
1775
|
-
|
|
1803
|
+
const renderer = new Canvas2DRenderer(this, ctx);
|
|
1804
|
+
renderer.pixelRatio = pixelRatio;
|
|
1805
|
+
renderer.setup();
|
|
1776
1806
|
Array.from(this.plugins.values()).sort((a, b) => (a.renderOrder ?? 0) - (b.renderOrder ?? 0)).forEach((plugin) => {
|
|
1777
1807
|
if (plugin.render) {
|
|
1778
|
-
plugin.render?.(
|
|
1808
|
+
plugin.render?.(renderer);
|
|
1779
1809
|
} else if (plugin.pathSet) {
|
|
1780
|
-
const style = this.computedStyle;
|
|
1781
1810
|
plugin.pathSet.paths.forEach((path) => {
|
|
1782
|
-
drawPath(
|
|
1783
|
-
ctx,
|
|
1784
|
-
path,
|
|
1785
|
-
fontSize: style.fontSize
|
|
1786
|
-
});
|
|
1811
|
+
renderer.drawPath(path);
|
|
1787
1812
|
});
|
|
1788
1813
|
}
|
|
1789
1814
|
});
|
|
@@ -1819,4 +1844,4 @@ __decorateClass([
|
|
|
1819
1844
|
property({ internal: true })
|
|
1820
1845
|
], Text.prototype, "fonts");
|
|
1821
1846
|
|
|
1822
|
-
export {
|
|
1847
|
+
export { Canvas2DRenderer as C, Fragment as F, Measurer as M, Paragraph as P, Text as T, Character as a, backgroundPlugin as b, getTransform2D as c, definePlugin as d, textDefaultStyle as e, createSvgLoader as f, getHighlightStyle as g, highlightPlugin as h, createSvgParser as i, parseColormap as j, isEqualObject as k, listStylePlugin as l, isEqualValue as m, hexToRgb as n, outlinePlugin as o, parseValueNumber as p, filterEmpty as q, renderPlugin as r, textDecorationPlugin as t };
|