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