modern-text 0.2.2 → 0.2.4
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 +687 -629
- package/dist/index.d.cts +131 -72
- package/dist/index.d.mts +131 -72
- package/dist/index.d.ts +131 -72
- package/dist/index.js +2 -2
- package/dist/index.mjs +671 -631
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3,17 +3,6 @@
|
|
|
3
3
|
const modernPath2d = require('modern-path2d');
|
|
4
4
|
const modernFont = require('modern-font');
|
|
5
5
|
|
|
6
|
-
class Feature {
|
|
7
|
-
constructor(_text) {
|
|
8
|
-
this._text = _text;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
class Deformer extends Feature {
|
|
13
|
-
deform() {
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
6
|
function parseColor(ctx, source, box) {
|
|
18
7
|
if (typeof source === "string" && source.startsWith("linear-gradient")) {
|
|
19
8
|
const { x0, y0, x1, y1, stops } = parseCssLinearGradient(source, box.left, box.top, box.width, box.height);
|
|
@@ -95,43 +84,66 @@ function drawPaths(options) {
|
|
|
95
84
|
});
|
|
96
85
|
}
|
|
97
86
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
87
|
+
function filterEmpty(val) {
|
|
88
|
+
if (!val)
|
|
89
|
+
return val;
|
|
90
|
+
const res = {};
|
|
91
|
+
for (const key in val) {
|
|
92
|
+
if (val[key] !== "" && val[key] !== void 0) {
|
|
93
|
+
res[key] = val[key];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return res;
|
|
97
|
+
}
|
|
98
|
+
function getRotationPoint(point, rotation) {
|
|
99
|
+
const { x, y } = point;
|
|
100
|
+
const sin = Math.sin(rotation);
|
|
101
|
+
const cos = Math.cos(rotation);
|
|
102
|
+
return {
|
|
103
|
+
x: x * cos - y * sin,
|
|
104
|
+
y: x * sin + y * cos
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function getSkewPoint(point, startPoint, skewX, skewY) {
|
|
108
|
+
const dx = point.x - startPoint.x;
|
|
109
|
+
const dy = point.y - startPoint.y;
|
|
110
|
+
return {
|
|
111
|
+
x: startPoint.x + (dx + Math.tan(skewX) * dy),
|
|
112
|
+
y: startPoint.y + (dy + Math.tan(skewY) * dx)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function getScalePoint(point, startPoint, scaleX, scaleY) {
|
|
116
|
+
const x = scaleX < 0 ? startPoint.x - point.x + startPoint.x : point.x;
|
|
117
|
+
const y = scaleY < 0 ? startPoint.y - point.y + startPoint.y : point.y;
|
|
118
|
+
return {
|
|
119
|
+
x: x * Math.abs(scaleX),
|
|
120
|
+
y: y * Math.abs(scaleY)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function getPointPosition(point, startPoint, rotation = 0, skewX = 0, skewY = 0, scaleX = 1, scaleY = 1) {
|
|
124
|
+
let points = Array.isArray(point) ? point : [point];
|
|
125
|
+
const _rotation = -rotation / 180 * Math.PI;
|
|
126
|
+
const { x, y } = startPoint;
|
|
127
|
+
if (scaleX !== 1 || scaleY !== 1) {
|
|
128
|
+
points = points.map((point2) => {
|
|
129
|
+
return getScalePoint(point2, startPoint, scaleX, scaleY);
|
|
117
130
|
});
|
|
118
|
-
return modernPath2d.BoundingBox.from(...boxes);
|
|
119
131
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
effects.forEach((effect) => {
|
|
125
|
-
uploadColor(effect, boundingBox, ctx);
|
|
126
|
-
});
|
|
127
|
-
characters.forEach((character) => {
|
|
128
|
-
effects.forEach((effect) => {
|
|
129
|
-
character.drawTo(ctx, effect);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
return this;
|
|
132
|
+
if (skewX || skewY) {
|
|
133
|
+
points = points.map((point2) => {
|
|
134
|
+
return getSkewPoint(point2, startPoint, skewX, skewY);
|
|
135
|
+
});
|
|
134
136
|
}
|
|
137
|
+
points = points.map((d) => {
|
|
138
|
+
const h = d.x - x;
|
|
139
|
+
const f = -(d.y - y);
|
|
140
|
+
d = getRotationPoint({ x: h, y: f }, _rotation);
|
|
141
|
+
return {
|
|
142
|
+
x: x + d.x,
|
|
143
|
+
y: y - d.y
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
return points[0];
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
var __defProp$4 = Object.defineProperty;
|
|
@@ -140,448 +152,149 @@ var __publicField$4 = (obj, key, value) => {
|
|
|
140
152
|
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
141
153
|
return value;
|
|
142
154
|
};
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
155
|
+
const set1 = /* @__PURE__ */ new Set(["\xA9", "\xAE", "\xF7"]);
|
|
156
|
+
const set2 = /* @__PURE__ */ new Set([
|
|
157
|
+
"\u2014",
|
|
158
|
+
"\u2026",
|
|
159
|
+
"\u201C",
|
|
160
|
+
"\u201D",
|
|
161
|
+
"\uFE4F",
|
|
162
|
+
"\uFE4B",
|
|
163
|
+
"\uFE4C",
|
|
164
|
+
"\u2018",
|
|
165
|
+
"\u2019",
|
|
166
|
+
"\u02DC"
|
|
167
|
+
]);
|
|
168
|
+
class Character {
|
|
169
|
+
constructor(content, index, parent) {
|
|
170
|
+
this.content = content;
|
|
171
|
+
this.index = index;
|
|
172
|
+
this.parent = parent;
|
|
173
|
+
__publicField$4(this, "boundingBox", new modernPath2d.BoundingBox());
|
|
174
|
+
__publicField$4(this, "path", new modernPath2d.Path2D());
|
|
175
|
+
__publicField$4(this, "textWidth", 0);
|
|
176
|
+
__publicField$4(this, "textHeight", 0);
|
|
147
177
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
178
|
+
get computedStyle() {
|
|
179
|
+
return this.parent.computedStyle;
|
|
180
|
+
}
|
|
181
|
+
get isVertical() {
|
|
182
|
+
return this.computedStyle.writingMode.includes("vertical");
|
|
183
|
+
}
|
|
184
|
+
get fontSize() {
|
|
185
|
+
return this.computedStyle.fontSize;
|
|
186
|
+
}
|
|
187
|
+
_font() {
|
|
188
|
+
const font = modernFont.fonts.get(this.computedStyle.fontFamily)?.font;
|
|
189
|
+
if (font instanceof modernFont.Woff || font instanceof modernFont.Ttf) {
|
|
190
|
+
return font.sfnt;
|
|
151
191
|
}
|
|
152
|
-
|
|
153
|
-
const max = modernPath2d.Point2D.MIN;
|
|
154
|
-
this.paths.forEach((path) => path.getMinMax(min, max));
|
|
155
|
-
return new modernPath2d.BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
192
|
+
return void 0;
|
|
156
193
|
}
|
|
157
|
-
|
|
158
|
-
const {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
194
|
+
_updateGlyph(font) {
|
|
195
|
+
const { content, computedStyle, boundingBox, isVertical } = this;
|
|
196
|
+
const { left, top, height } = boundingBox;
|
|
197
|
+
const { fontSize } = computedStyle;
|
|
198
|
+
const { unitsPerEm, ascender, descender, os2, post } = font;
|
|
199
|
+
const rate = unitsPerEm / fontSize;
|
|
200
|
+
const glyphWidth = font.getAdvanceWidth(content, fontSize);
|
|
201
|
+
const glyphHeight = (ascender + Math.abs(descender)) / rate;
|
|
202
|
+
const baseline = ascender / rate;
|
|
203
|
+
const yStrikeoutPosition = (ascender - os2.yStrikeoutPosition) / rate;
|
|
204
|
+
const yStrikeoutSize = os2.yStrikeoutSize / rate;
|
|
205
|
+
const underlinePosition = (ascender - post.underlinePosition) / rate;
|
|
206
|
+
const underlineThickness = post.underlineThickness / rate;
|
|
207
|
+
this.glyphWidth = glyphWidth;
|
|
208
|
+
this.glyphHeight = glyphHeight;
|
|
209
|
+
this.underlinePosition = underlinePosition;
|
|
210
|
+
this.underlineThickness = underlineThickness;
|
|
211
|
+
this.yStrikeoutPosition = yStrikeoutPosition;
|
|
212
|
+
this.yStrikeoutSize = yStrikeoutSize;
|
|
213
|
+
this.baseline = baseline;
|
|
214
|
+
this.centerDiviation = 0.5 * height - baseline;
|
|
215
|
+
this.glyphBox = isVertical ? new modernPath2d.BoundingBox(left, top, glyphHeight, glyphWidth) : new modernPath2d.BoundingBox(left, top, glyphWidth, glyphHeight);
|
|
216
|
+
this.centerPoint = this.glyphBox.getCenterPoint();
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
_decoration() {
|
|
220
|
+
const { isVertical, underlinePosition, yStrikeoutPosition } = this;
|
|
221
|
+
const { textDecoration, fontSize } = this.computedStyle;
|
|
222
|
+
const { left, top, width, height } = this.boundingBox;
|
|
223
|
+
const lineWidth = 0.1 * fontSize;
|
|
224
|
+
let start;
|
|
225
|
+
switch (textDecoration) {
|
|
226
|
+
case "underline":
|
|
227
|
+
if (isVertical) {
|
|
228
|
+
start = left;
|
|
168
229
|
} else {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
230
|
+
start = top + underlinePosition;
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
case "line-through":
|
|
234
|
+
if (isVertical) {
|
|
235
|
+
start = left + width / 2;
|
|
236
|
+
} else {
|
|
237
|
+
start = top + yStrikeoutPosition;
|
|
172
238
|
}
|
|
239
|
+
break;
|
|
240
|
+
case "none":
|
|
241
|
+
default:
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
244
|
+
if (isVertical) {
|
|
245
|
+
return [
|
|
246
|
+
{ type: "M", x: start, y: top },
|
|
247
|
+
{ type: "L", x: start, y: top + height },
|
|
248
|
+
{ type: "L", x: start + lineWidth, y: top + height },
|
|
249
|
+
{ type: "L", x: start + lineWidth, y: top },
|
|
250
|
+
{ type: "Z" }
|
|
251
|
+
];
|
|
252
|
+
} else {
|
|
253
|
+
return [
|
|
254
|
+
{ type: "M", x: left, y: start },
|
|
255
|
+
{ type: "L", x: left + width, y: start },
|
|
256
|
+
{ type: "L", x: left + width, y: start + lineWidth },
|
|
257
|
+
{ type: "L", x: left, y: start + lineWidth },
|
|
258
|
+
{ type: "Z" }
|
|
259
|
+
];
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
_transform(commands, cb) {
|
|
263
|
+
return commands.map((rawCmd) => {
|
|
264
|
+
const cmd = { ...rawCmd };
|
|
265
|
+
switch (cmd.type) {
|
|
266
|
+
case "L":
|
|
267
|
+
case "M":
|
|
268
|
+
[cmd.x, cmd.y] = cb(cmd.x, cmd.y);
|
|
269
|
+
break;
|
|
270
|
+
case "Q":
|
|
271
|
+
[cmd.x1, cmd.y1] = cb(cmd.x1, cmd.y1);
|
|
272
|
+
[cmd.x, cmd.y] = cb(cmd.x, cmd.y);
|
|
273
|
+
break;
|
|
173
274
|
}
|
|
174
|
-
|
|
275
|
+
return cmd;
|
|
175
276
|
});
|
|
176
|
-
this.paths = groups.filter((characters2) => characters2.length).map((characters2) => {
|
|
177
|
-
return {
|
|
178
|
-
url: characters2[0].parent.highlight.url,
|
|
179
|
-
box: modernPath2d.BoundingBox.from(...characters2.map((c) => c.glyphBox)),
|
|
180
|
-
baseline: Math.max(...characters2.map((c) => c.baseline))
|
|
181
|
-
};
|
|
182
|
-
}).map((group2) => this._parseGroup(group2, fontSize)).flat();
|
|
183
277
|
}
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const { x, y, width, height } = new modernPath2d.BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
191
|
-
const viewBox = svg.getAttribute("viewBox").split(" ").map(Number);
|
|
192
|
-
return {
|
|
193
|
-
paths,
|
|
194
|
-
box: new modernPath2d.BoundingBox(x, y, width, height),
|
|
195
|
-
viewBox: new modernPath2d.BoundingBox(...viewBox)
|
|
278
|
+
_italic(commands, startPoint) {
|
|
279
|
+
const { baseline, glyphWidth } = this;
|
|
280
|
+
const { left, top } = this.boundingBox;
|
|
281
|
+
const _startPoint = startPoint || {
|
|
282
|
+
y: top + baseline,
|
|
283
|
+
x: left + glyphWidth / 2
|
|
196
284
|
};
|
|
285
|
+
return this._transform(commands, (x, y) => {
|
|
286
|
+
const p = getSkewPoint({ x, y }, _startPoint, -0.24, 0);
|
|
287
|
+
return [p.x, p.y];
|
|
288
|
+
});
|
|
197
289
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (type === 0) {
|
|
204
|
-
const offset = {
|
|
205
|
-
x: groupBox.left - fontSize * 0.2,
|
|
206
|
-
y: groupBox.top
|
|
207
|
-
};
|
|
208
|
-
const scaleX = (groupBox.width + fontSize * 0.2 * 2) / box.width;
|
|
209
|
-
const scaleY = groupBox.height / box.height;
|
|
210
|
-
const m = new modernPath2d.Matrix3().translate(-box.x, -box.y).scale(scaleX, scaleY).translate(offset.x, offset.y);
|
|
211
|
-
paths.forEach((original) => {
|
|
212
|
-
result.push(original.clone().transform(m));
|
|
213
|
-
});
|
|
214
|
-
} else if (type === 1) {
|
|
215
|
-
const scale = fontSize / box.width * 2;
|
|
216
|
-
const width = box.width * scale;
|
|
217
|
-
const length = Math.ceil(groupBox.width / width);
|
|
218
|
-
const totalWidth = width * length;
|
|
219
|
-
const offset = {
|
|
220
|
-
x: groupBox.left + (groupBox.width - totalWidth) / 2 + fontSize * 0.1,
|
|
221
|
-
y: groupBox.top + baseline + fontSize * 0.1
|
|
222
|
-
};
|
|
223
|
-
const m = new modernPath2d.Matrix3().translate(-box.x, -box.y).scale(scale, scale).translate(offset.x, offset.y);
|
|
224
|
-
for (let i = 0; i < length; i++) {
|
|
225
|
-
const _m = m.clone().translate(i * width, 0);
|
|
226
|
-
paths.forEach((original) => {
|
|
227
|
-
result.push(original.clone().transform(_m));
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return result;
|
|
232
|
-
}
|
|
233
|
-
draw({ ctx }) {
|
|
234
|
-
drawPaths({
|
|
235
|
-
ctx,
|
|
236
|
-
paths: this.paths,
|
|
237
|
-
fontSize: this._text.computedStyle.fontSize,
|
|
238
|
-
fill: false
|
|
239
|
-
});
|
|
240
|
-
return this;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
class Measurer extends Feature {
|
|
245
|
-
_styleToDomStyle(style) {
|
|
246
|
-
const _style = { ...style };
|
|
247
|
-
for (const key in style) {
|
|
248
|
-
if ([
|
|
249
|
-
"width",
|
|
250
|
-
"height",
|
|
251
|
-
"fontSize",
|
|
252
|
-
"letterSpacing",
|
|
253
|
-
"textStrokeWidth",
|
|
254
|
-
"shadowOffsetX",
|
|
255
|
-
"shadowOffsetY",
|
|
256
|
-
"shadowBlur"
|
|
257
|
-
].includes(key)) {
|
|
258
|
-
_style[key] = `${style[key]}px`;
|
|
259
|
-
} else {
|
|
260
|
-
_style[key] = style[key];
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return _style;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* <div style="...">
|
|
267
|
-
* <ul>
|
|
268
|
-
* <li style="...">
|
|
269
|
-
* <div>
|
|
270
|
-
* <span style="...">...</span>
|
|
271
|
-
* <span>...</span>
|
|
272
|
-
* </div>
|
|
273
|
-
* </li>
|
|
274
|
-
* </ul>
|
|
275
|
-
* </div>
|
|
276
|
-
*/
|
|
277
|
-
createDom() {
|
|
278
|
-
const { paragraphs, computedStyle: style } = this._text;
|
|
279
|
-
const documentFragment = document.createDocumentFragment();
|
|
280
|
-
const dom = document.createElement("div");
|
|
281
|
-
Object.assign(dom.style, this._styleToDomStyle(style));
|
|
282
|
-
dom.style.position = "absolute";
|
|
283
|
-
dom.style.visibility = "hidden";
|
|
284
|
-
const ul = document.createElement("ul");
|
|
285
|
-
ul.style.listStyle = "none";
|
|
286
|
-
ul.style.padding = "0";
|
|
287
|
-
ul.style.margin = "0";
|
|
288
|
-
paragraphs.forEach((paragraph) => {
|
|
289
|
-
const li = document.createElement("li");
|
|
290
|
-
const div = document.createElement("div");
|
|
291
|
-
Object.assign(li.style, this._styleToDomStyle(paragraph.style));
|
|
292
|
-
paragraph.fragments.forEach((fragment) => {
|
|
293
|
-
const span = document.createElement("span");
|
|
294
|
-
Object.assign(span.style, this._styleToDomStyle(fragment.style));
|
|
295
|
-
span.appendChild(document.createTextNode(fragment.content));
|
|
296
|
-
div.appendChild(span);
|
|
297
|
-
});
|
|
298
|
-
ul.appendChild(li);
|
|
299
|
-
li.appendChild(div);
|
|
300
|
-
});
|
|
301
|
-
dom.appendChild(ul);
|
|
302
|
-
documentFragment.appendChild(dom);
|
|
303
|
-
document.body.appendChild(documentFragment);
|
|
304
|
-
return {
|
|
305
|
-
dom,
|
|
306
|
-
destory: () => dom.parentNode?.removeChild(dom)
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
_measureDom(dom) {
|
|
310
|
-
const paragraphs = [];
|
|
311
|
-
const fragments = [];
|
|
312
|
-
const characters = [];
|
|
313
|
-
dom.querySelectorAll("li").forEach((li, paragraphIndex) => {
|
|
314
|
-
const pBox = li.getBoundingClientRect();
|
|
315
|
-
paragraphs.push({
|
|
316
|
-
paragraphIndex,
|
|
317
|
-
left: pBox.left,
|
|
318
|
-
top: pBox.top,
|
|
319
|
-
width: pBox.width,
|
|
320
|
-
height: pBox.height
|
|
321
|
-
});
|
|
322
|
-
li.querySelectorAll("span").forEach((span, fragmentIndex) => {
|
|
323
|
-
const fBox = li.getBoundingClientRect();
|
|
324
|
-
fragments.push({
|
|
325
|
-
paragraphIndex,
|
|
326
|
-
fragmentIndex,
|
|
327
|
-
left: fBox.left,
|
|
328
|
-
top: fBox.top,
|
|
329
|
-
width: fBox.width,
|
|
330
|
-
height: fBox.height
|
|
331
|
-
});
|
|
332
|
-
const text = span.firstChild;
|
|
333
|
-
if (text instanceof window.Text) {
|
|
334
|
-
const range = document.createRange();
|
|
335
|
-
range.selectNodeContents(text);
|
|
336
|
-
const len = text.data ? text.data.length : 0;
|
|
337
|
-
let i = 0;
|
|
338
|
-
for (; i <= len; ) {
|
|
339
|
-
range.setStart(text, Math.max(i - 1, 0));
|
|
340
|
-
range.setEnd(text, i);
|
|
341
|
-
const rects = range.getClientRects?.() ?? [range.getBoundingClientRect()];
|
|
342
|
-
let rect = rects[rects.length - 1];
|
|
343
|
-
if (rects.length > 1 && rect.width < 2) {
|
|
344
|
-
rect = rects[rects.length - 2];
|
|
345
|
-
}
|
|
346
|
-
const content = range.toString();
|
|
347
|
-
if (content !== "" && rect && rect.width + rect.height !== 0) {
|
|
348
|
-
characters.push({
|
|
349
|
-
content,
|
|
350
|
-
newParagraphIndex: -1,
|
|
351
|
-
paragraphIndex,
|
|
352
|
-
fragmentIndex,
|
|
353
|
-
characterIndex: i - 1,
|
|
354
|
-
top: rect.top,
|
|
355
|
-
left: rect.left,
|
|
356
|
-
height: rect.height,
|
|
357
|
-
width: rect.width,
|
|
358
|
-
textWidth: -1,
|
|
359
|
-
textHeight: -1
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
i++;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
return {
|
|
368
|
-
paragraphs,
|
|
369
|
-
fragments,
|
|
370
|
-
characters
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
measureDom(dom) {
|
|
374
|
-
const { paragraphs } = this._text;
|
|
375
|
-
const rect = dom.getBoundingClientRect();
|
|
376
|
-
const innerEl = dom.querySelector("ul");
|
|
377
|
-
const isVertical = window.getComputedStyle(dom).writingMode.includes("vertical");
|
|
378
|
-
const oldLineHeight = innerEl.style.lineHeight;
|
|
379
|
-
innerEl.style.lineHeight = "4000px";
|
|
380
|
-
const _paragraphs = [[]];
|
|
381
|
-
let fragments = _paragraphs[0];
|
|
382
|
-
const { characters: oldCharacters } = this._measureDom(dom);
|
|
383
|
-
if (oldCharacters.length > 0) {
|
|
384
|
-
fragments.push(oldCharacters[0]);
|
|
385
|
-
oldCharacters.reduce((prev, current) => {
|
|
386
|
-
const attr = isVertical ? "left" : "top";
|
|
387
|
-
if (Math.abs(current[attr] - prev[attr]) > 4e3 / 2) {
|
|
388
|
-
fragments = [];
|
|
389
|
-
_paragraphs.push(fragments);
|
|
390
|
-
}
|
|
391
|
-
fragments.push(current);
|
|
392
|
-
return current;
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
innerEl.style.lineHeight = oldLineHeight;
|
|
396
|
-
const measured = this._measureDom(dom);
|
|
397
|
-
measured.paragraphs.forEach((p) => {
|
|
398
|
-
const _p = paragraphs[p.paragraphIndex];
|
|
399
|
-
_p.boundingBox.left = p.left;
|
|
400
|
-
_p.boundingBox.top = p.top;
|
|
401
|
-
_p.boundingBox.width = p.width;
|
|
402
|
-
_p.boundingBox.height = p.height;
|
|
403
|
-
});
|
|
404
|
-
measured.fragments.forEach((f) => {
|
|
405
|
-
const _f = paragraphs[f.paragraphIndex].fragments[f.fragmentIndex];
|
|
406
|
-
_f.boundingBox.left = f.left;
|
|
407
|
-
_f.boundingBox.top = f.top;
|
|
408
|
-
_f.boundingBox.width = f.width;
|
|
409
|
-
_f.boundingBox.height = f.height;
|
|
410
|
-
});
|
|
411
|
-
const results = [];
|
|
412
|
-
let i = 0;
|
|
413
|
-
_paragraphs.forEach((oldCharacters2) => {
|
|
414
|
-
oldCharacters2.forEach((oldCharacter) => {
|
|
415
|
-
const character = measured.characters[i];
|
|
416
|
-
const { paragraphIndex, fragmentIndex, characterIndex } = character;
|
|
417
|
-
results.push({
|
|
418
|
-
...character,
|
|
419
|
-
newParagraphIndex: paragraphIndex,
|
|
420
|
-
textWidth: oldCharacter.width,
|
|
421
|
-
textHeight: oldCharacter.height,
|
|
422
|
-
left: character.left - rect.left,
|
|
423
|
-
top: character.top - rect.top
|
|
424
|
-
});
|
|
425
|
-
const item = paragraphs[paragraphIndex].fragments[fragmentIndex].characters[characterIndex];
|
|
426
|
-
item.boundingBox.left = results[i].left;
|
|
427
|
-
item.boundingBox.top = results[i].top;
|
|
428
|
-
item.boundingBox.width = results[i].width;
|
|
429
|
-
item.boundingBox.height = results[i].height;
|
|
430
|
-
item.textWidth = results[i].textWidth;
|
|
431
|
-
item.textHeight = results[i].textHeight;
|
|
432
|
-
i++;
|
|
433
|
-
});
|
|
434
|
-
});
|
|
435
|
-
return {
|
|
436
|
-
paragraphs,
|
|
437
|
-
boundingBox: new modernPath2d.BoundingBox(0, 0, rect.width, rect.height)
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
measure(dom) {
|
|
441
|
-
let destory;
|
|
442
|
-
if (!dom) {
|
|
443
|
-
({ dom, destory } = this.createDom());
|
|
444
|
-
}
|
|
445
|
-
const result = this.measureDom(dom);
|
|
446
|
-
destory?.();
|
|
447
|
-
return result;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
function filterEmpty(val) {
|
|
452
|
-
if (!val)
|
|
453
|
-
return val;
|
|
454
|
-
const res = {};
|
|
455
|
-
for (const key in val) {
|
|
456
|
-
if (val[key] !== "" && val[key] !== void 0) {
|
|
457
|
-
res[key] = val[key];
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
return res;
|
|
461
|
-
}
|
|
462
|
-
function getRotationPoint(point, rotation) {
|
|
463
|
-
const { x, y } = point;
|
|
464
|
-
const sin = Math.sin(rotation);
|
|
465
|
-
const cos = Math.cos(rotation);
|
|
466
|
-
return {
|
|
467
|
-
x: x * cos - y * sin,
|
|
468
|
-
y: x * sin + y * cos
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
function getSkewPoint(point, startPoint, skewX, skewY) {
|
|
472
|
-
const dx = point.x - startPoint.x;
|
|
473
|
-
const dy = point.y - startPoint.y;
|
|
474
|
-
return {
|
|
475
|
-
x: startPoint.x + (dx + Math.tan(skewX) * dy),
|
|
476
|
-
y: startPoint.y + (dy + Math.tan(skewY) * dx)
|
|
477
|
-
};
|
|
478
|
-
}
|
|
479
|
-
function getScalePoint(point, startPoint, scaleX, scaleY) {
|
|
480
|
-
const x = scaleX < 0 ? startPoint.x - point.x + startPoint.x : point.x;
|
|
481
|
-
const y = scaleY < 0 ? startPoint.y - point.y + startPoint.y : point.y;
|
|
482
|
-
return {
|
|
483
|
-
x: x * Math.abs(scaleX),
|
|
484
|
-
y: y * Math.abs(scaleY)
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
function getPointPosition(point, startPoint, rotation = 0, skewX = 0, skewY = 0, scaleX = 1, scaleY = 1) {
|
|
488
|
-
let points = Array.isArray(point) ? point : [point];
|
|
489
|
-
const _rotation = -rotation / 180 * Math.PI;
|
|
490
|
-
const { x, y } = startPoint;
|
|
491
|
-
if (scaleX !== 1 || scaleY !== 1) {
|
|
492
|
-
points = points.map((point2) => {
|
|
493
|
-
return getScalePoint(point2, startPoint, scaleX, scaleY);
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
if (skewX || skewY) {
|
|
497
|
-
points = points.map((point2) => {
|
|
498
|
-
return getSkewPoint(point2, startPoint, skewX, skewY);
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
points = points.map((d) => {
|
|
502
|
-
const h = d.x - x;
|
|
503
|
-
const f = -(d.y - y);
|
|
504
|
-
d = getRotationPoint({ x: h, y: f }, _rotation);
|
|
505
|
-
return {
|
|
506
|
-
x: x + d.x,
|
|
507
|
-
y: y - d.y
|
|
508
|
-
};
|
|
509
|
-
});
|
|
510
|
-
return points[0];
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
var __defProp$3 = Object.defineProperty;
|
|
514
|
-
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
515
|
-
var __publicField$3 = (obj, key, value) => {
|
|
516
|
-
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
517
|
-
return value;
|
|
518
|
-
};
|
|
519
|
-
const set1 = /* @__PURE__ */ new Set(["\xA9", "\xAE", "\xF7"]);
|
|
520
|
-
const set2 = /* @__PURE__ */ new Set([
|
|
521
|
-
"\u2014",
|
|
522
|
-
"\u2026",
|
|
523
|
-
"\u201C",
|
|
524
|
-
"\u201D",
|
|
525
|
-
"\uFE4F",
|
|
526
|
-
"\uFE4B",
|
|
527
|
-
"\uFE4C",
|
|
528
|
-
"\u2018",
|
|
529
|
-
"\u2019",
|
|
530
|
-
"\u02DC"
|
|
531
|
-
]);
|
|
532
|
-
class Character {
|
|
533
|
-
constructor(content, index, parent) {
|
|
534
|
-
this.content = content;
|
|
535
|
-
this.index = index;
|
|
536
|
-
this.parent = parent;
|
|
537
|
-
__publicField$3(this, "boundingBox", new modernPath2d.BoundingBox());
|
|
538
|
-
__publicField$3(this, "path", new modernPath2d.Path2D());
|
|
539
|
-
__publicField$3(this, "textWidth", 0);
|
|
540
|
-
__publicField$3(this, "textHeight", 0);
|
|
541
|
-
}
|
|
542
|
-
get computedStyle() {
|
|
543
|
-
return this.parent.computedStyle;
|
|
544
|
-
}
|
|
545
|
-
get isVertical() {
|
|
546
|
-
return this.computedStyle.writingMode.includes("vertical");
|
|
547
|
-
}
|
|
548
|
-
get fontSize() {
|
|
549
|
-
return this.computedStyle.fontSize;
|
|
550
|
-
}
|
|
551
|
-
_updateFont() {
|
|
552
|
-
const font = modernFont.fonts.get(this.computedStyle.fontFamily)?.font;
|
|
553
|
-
if (font instanceof modernFont.Woff || font instanceof modernFont.Ttf) {
|
|
554
|
-
this.font = font.sfnt;
|
|
555
|
-
}
|
|
556
|
-
return this;
|
|
557
|
-
}
|
|
558
|
-
_updateGlyph(font) {
|
|
559
|
-
const { content, computedStyle, boundingBox, isVertical } = this;
|
|
560
|
-
const { left, top, height } = boundingBox;
|
|
561
|
-
const { fontSize } = computedStyle;
|
|
562
|
-
const { unitsPerEm, ascender, descender, os2, post } = font;
|
|
563
|
-
const rate = unitsPerEm / fontSize;
|
|
564
|
-
const glyphWidth = font.getAdvanceWidth(content, fontSize);
|
|
565
|
-
const glyphHeight = (ascender + Math.abs(descender)) / rate;
|
|
566
|
-
const baseline = ascender / rate;
|
|
567
|
-
const yStrikeoutPosition = (ascender - os2.yStrikeoutPosition) / rate;
|
|
568
|
-
const yStrikeoutSize = os2.yStrikeoutSize / rate;
|
|
569
|
-
const underlinePosition = (ascender - post.underlinePosition) / rate;
|
|
570
|
-
const underlineThickness = post.underlineThickness / rate;
|
|
571
|
-
this.glyphWidth = glyphWidth;
|
|
572
|
-
this.glyphHeight = glyphHeight;
|
|
573
|
-
this.underlinePosition = underlinePosition;
|
|
574
|
-
this.underlineThickness = underlineThickness;
|
|
575
|
-
this.yStrikeoutPosition = yStrikeoutPosition;
|
|
576
|
-
this.yStrikeoutSize = yStrikeoutSize;
|
|
577
|
-
this.baseline = baseline;
|
|
578
|
-
this.centerDiviation = 0.5 * height - baseline;
|
|
579
|
-
this.glyphBox = isVertical ? new modernPath2d.BoundingBox(left, top, glyphHeight, glyphWidth) : new modernPath2d.BoundingBox(left, top, glyphWidth, glyphHeight);
|
|
580
|
-
this.centerPoint = this.glyphBox.getCenterPoint();
|
|
581
|
-
return this;
|
|
290
|
+
_rotation90(commands, point) {
|
|
291
|
+
return this._transform(commands, (x, y) => {
|
|
292
|
+
const p = getPointPosition({ x, y }, point, 90);
|
|
293
|
+
return [p.x, p.y];
|
|
294
|
+
});
|
|
582
295
|
}
|
|
583
296
|
updatePath() {
|
|
584
|
-
const font = this.
|
|
297
|
+
const font = this._font();
|
|
585
298
|
if (!font) {
|
|
586
299
|
return this;
|
|
587
300
|
}
|
|
@@ -594,16 +307,14 @@ class Character {
|
|
|
594
307
|
computedStyle,
|
|
595
308
|
baseline,
|
|
596
309
|
glyphHeight,
|
|
597
|
-
glyphWidth
|
|
598
|
-
yStrikeoutPosition,
|
|
599
|
-
underlinePosition
|
|
310
|
+
glyphWidth
|
|
600
311
|
} = this._updateGlyph(font);
|
|
601
312
|
const { os2, ascender, descender } = font;
|
|
602
313
|
const usWinAscent = ascender;
|
|
603
314
|
const usWinDescent = descender;
|
|
604
315
|
const typoAscender = os2.sTypoAscender;
|
|
605
|
-
const { left, top
|
|
606
|
-
const { fontSize, fontStyle
|
|
316
|
+
const { left, top } = boundingBox;
|
|
317
|
+
const { fontSize, fontStyle } = computedStyle;
|
|
607
318
|
let x = left;
|
|
608
319
|
let y = top + baseline;
|
|
609
320
|
let glyphIndex;
|
|
@@ -622,192 +333,512 @@ class Character {
|
|
|
622
333
|
x: x + glyphWidth / 2
|
|
623
334
|
};
|
|
624
335
|
if (fontStyle === "italic") {
|
|
625
|
-
|
|
336
|
+
commands = this._italic(
|
|
626
337
|
commands,
|
|
627
338
|
isVertical ? {
|
|
628
339
|
x: point.x,
|
|
629
340
|
y: top - (glyphHeight - glyphWidth) / 2 + baseline
|
|
630
|
-
} :
|
|
341
|
+
} : void 0
|
|
631
342
|
);
|
|
632
343
|
}
|
|
633
|
-
|
|
344
|
+
commands = this._rotation90(commands, point);
|
|
634
345
|
} else {
|
|
635
346
|
if (glyphIndex !== void 0) {
|
|
636
347
|
commands = font.glyf.glyphs.get(glyphIndex).getPathCommands(x, y, fontSize);
|
|
637
348
|
if (fontStyle === "italic") {
|
|
638
|
-
|
|
349
|
+
commands = this._italic(
|
|
639
350
|
commands,
|
|
640
351
|
isVertical ? {
|
|
641
352
|
x: x + glyphWidth / 2,
|
|
642
353
|
y: top + typoAscender / (usWinAscent + Math.abs(usWinDescent)) * glyphHeight
|
|
643
|
-
} :
|
|
354
|
+
} : void 0
|
|
644
355
|
);
|
|
645
356
|
}
|
|
646
357
|
} else {
|
|
647
358
|
commands = font.getPathCommands(content, x, y, fontSize) ?? [];
|
|
648
359
|
if (fontStyle === "italic") {
|
|
649
|
-
|
|
360
|
+
commands = this._italic(
|
|
650
361
|
commands,
|
|
651
|
-
isVertical ? { x: x + glyphHeight / 2, y } :
|
|
362
|
+
isVertical ? { x: x + glyphHeight / 2, y } : void 0
|
|
652
363
|
);
|
|
653
364
|
}
|
|
654
365
|
}
|
|
655
366
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
case "
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
{ type: "L", x: left + width, y: start },
|
|
677
|
-
{ type: "L", x: left + width, y: start + len },
|
|
678
|
-
{ type: "L", x: left, y: start + len },
|
|
679
|
-
{ type: "Z" }
|
|
680
|
-
];
|
|
681
|
-
switch (textDecoration) {
|
|
682
|
-
case "underline":
|
|
683
|
-
commands.push(...create(top + underlinePosition, lineWidth));
|
|
367
|
+
commands.push(...this._decoration());
|
|
368
|
+
this.commands = commands;
|
|
369
|
+
this.path = new modernPath2d.Path2D(commands);
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
372
|
+
update() {
|
|
373
|
+
this.updatePath();
|
|
374
|
+
return this;
|
|
375
|
+
}
|
|
376
|
+
getMinMax(min = modernPath2d.Point2D.MAX, max = modernPath2d.Point2D.MIN) {
|
|
377
|
+
let last = { x: 0, y: 0 };
|
|
378
|
+
this.commands.forEach((cmd) => {
|
|
379
|
+
switch (cmd.type) {
|
|
380
|
+
case "L":
|
|
381
|
+
case "M":
|
|
382
|
+
min.x = Math.min(min.x, cmd.x);
|
|
383
|
+
min.y = Math.min(min.y, cmd.y);
|
|
384
|
+
max.x = Math.max(max.x, cmd.x);
|
|
385
|
+
max.y = Math.max(max.y, cmd.y);
|
|
386
|
+
last = { x: cmd.x, y: cmd.y };
|
|
684
387
|
break;
|
|
685
|
-
case "
|
|
686
|
-
|
|
388
|
+
case "Q": {
|
|
389
|
+
const x1 = 0.5 * (last.x + cmd.x1);
|
|
390
|
+
const y1 = 0.5 * (last.y + cmd.y1);
|
|
391
|
+
const x2 = 0.5 * (last.x + cmd.x);
|
|
392
|
+
const y2 = 0.5 * (last.y + cmd.y);
|
|
393
|
+
min.x = Math.min(min.x, last.x, cmd.x, x1, x2);
|
|
394
|
+
min.y = Math.min(min.y, last.y, cmd.y, y1, y2);
|
|
395
|
+
max.x = Math.max(max.x, last.x, cmd.x, x1, x2);
|
|
396
|
+
max.y = Math.max(max.y, last.y, cmd.y, y1, y2);
|
|
397
|
+
last = { x: cmd.x, y: cmd.y };
|
|
687
398
|
break;
|
|
399
|
+
}
|
|
688
400
|
}
|
|
401
|
+
});
|
|
402
|
+
return { min, max };
|
|
403
|
+
}
|
|
404
|
+
drawTo(ctx, config = {}) {
|
|
405
|
+
drawPaths({
|
|
406
|
+
ctx,
|
|
407
|
+
paths: [this.path],
|
|
408
|
+
fontSize: this.computedStyle.fontSize,
|
|
409
|
+
color: this.computedStyle.color,
|
|
410
|
+
...config
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
var __defProp$3 = Object.defineProperty;
|
|
416
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
417
|
+
var __publicField$3 = (obj, key, value) => {
|
|
418
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
419
|
+
return value;
|
|
420
|
+
};
|
|
421
|
+
class Fragment {
|
|
422
|
+
constructor(content, style = {}, parent) {
|
|
423
|
+
this.content = content;
|
|
424
|
+
this.style = style;
|
|
425
|
+
this.parent = parent;
|
|
426
|
+
__publicField$3(this, "boundingBox", new modernPath2d.BoundingBox());
|
|
427
|
+
__publicField$3(this, "highlight");
|
|
428
|
+
this.updateComputedStyle().initCharacters();
|
|
429
|
+
}
|
|
430
|
+
get computedContent() {
|
|
431
|
+
const style = this.computedStyle;
|
|
432
|
+
return style.textTransform === "uppercase" ? this.content.toUpperCase() : style.textTransform === "lowercase" ? this.content.toLowerCase() : this.content;
|
|
433
|
+
}
|
|
434
|
+
updateComputedStyle() {
|
|
435
|
+
this.computedStyle = {
|
|
436
|
+
...this.parent.computedStyle,
|
|
437
|
+
...filterEmpty(this.style)
|
|
438
|
+
};
|
|
439
|
+
return this;
|
|
440
|
+
}
|
|
441
|
+
initCharacters() {
|
|
442
|
+
const characters = [];
|
|
443
|
+
let index = 0;
|
|
444
|
+
for (const c of this.computedContent) {
|
|
445
|
+
characters.push(new Character(c, index++, this));
|
|
689
446
|
}
|
|
690
|
-
this.
|
|
447
|
+
this.characters = characters;
|
|
691
448
|
return this;
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
var __defProp$2 = Object.defineProperty;
|
|
453
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
454
|
+
var __publicField$2 = (obj, key, value) => {
|
|
455
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
456
|
+
return value;
|
|
457
|
+
};
|
|
458
|
+
class Paragraph {
|
|
459
|
+
constructor(style, parentStyle) {
|
|
460
|
+
this.style = style;
|
|
461
|
+
this.parentStyle = parentStyle;
|
|
462
|
+
__publicField$2(this, "boundingBox", new modernPath2d.BoundingBox());
|
|
463
|
+
__publicField$2(this, "fragments", []);
|
|
464
|
+
this.updateComputedStyle();
|
|
465
|
+
}
|
|
466
|
+
updateComputedStyle() {
|
|
467
|
+
this.computedStyle = {
|
|
468
|
+
...filterEmpty(this.parentStyle),
|
|
469
|
+
...filterEmpty(this.style)
|
|
470
|
+
};
|
|
471
|
+
return this;
|
|
472
|
+
}
|
|
473
|
+
addFragment(content, style) {
|
|
474
|
+
const fragment = new Fragment(content, style, this);
|
|
475
|
+
this.fragments.push(fragment);
|
|
476
|
+
return fragment;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
class Feature {
|
|
481
|
+
constructor(_text) {
|
|
482
|
+
this._text = _text;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
class Deformer extends Feature {
|
|
487
|
+
deform() {
|
|
488
|
+
this._text.deformation?.();
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
class Effector extends Feature {
|
|
493
|
+
getBoundingBox() {
|
|
494
|
+
const { characters, effects } = this._text;
|
|
495
|
+
const boxes = [];
|
|
496
|
+
characters.forEach((character) => {
|
|
497
|
+
const fontSize = character.computedStyle.fontSize;
|
|
498
|
+
effects?.forEach((effect) => {
|
|
499
|
+
const offsetX = (effect.offsetX ?? 0) * fontSize;
|
|
500
|
+
const offsetY = (effect.offsetY ?? 0) * fontSize;
|
|
501
|
+
const shadowOffsetX = (effect.shadowOffsetX ?? 0) * fontSize;
|
|
502
|
+
const shadowOffsetY = (effect.shadowOffsetY ?? 0) * fontSize;
|
|
503
|
+
const textStrokeWidth = Math.max(0.1, effect.textStrokeWidth ?? 0) * fontSize;
|
|
504
|
+
const aabb = character.boundingBox.clone();
|
|
505
|
+
aabb.left += offsetX + shadowOffsetX - textStrokeWidth;
|
|
506
|
+
aabb.top += offsetY + shadowOffsetY - textStrokeWidth;
|
|
507
|
+
aabb.width += textStrokeWidth * 2;
|
|
508
|
+
aabb.height += textStrokeWidth * 2;
|
|
509
|
+
boxes.push(aabb);
|
|
713
510
|
});
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
command[`x${arg}`] = pos.x;
|
|
728
|
-
command[`y${arg}`] = pos.y;
|
|
729
|
-
}
|
|
511
|
+
});
|
|
512
|
+
return modernPath2d.BoundingBox.from(...boxes);
|
|
513
|
+
}
|
|
514
|
+
draw(options) {
|
|
515
|
+
const { ctx } = options;
|
|
516
|
+
const { effects, characters, boundingBox } = this._text;
|
|
517
|
+
if (effects) {
|
|
518
|
+
effects.forEach((effect) => {
|
|
519
|
+
uploadColor(effect, boundingBox, ctx);
|
|
520
|
+
});
|
|
521
|
+
characters.forEach((character) => {
|
|
522
|
+
effects.forEach((effect) => {
|
|
523
|
+
character.drawTo(ctx, effect);
|
|
730
524
|
});
|
|
731
525
|
});
|
|
732
526
|
}
|
|
733
|
-
}
|
|
734
|
-
update() {
|
|
735
|
-
this.updatePath();
|
|
736
527
|
return this;
|
|
737
528
|
}
|
|
738
|
-
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
var __defProp$1 = Object.defineProperty;
|
|
532
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
533
|
+
var __publicField$1 = (obj, key, value) => {
|
|
534
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
535
|
+
return value;
|
|
536
|
+
};
|
|
537
|
+
class Highlighter extends Feature {
|
|
538
|
+
constructor() {
|
|
539
|
+
super(...arguments);
|
|
540
|
+
__publicField$1(this, "paths", []);
|
|
541
|
+
}
|
|
542
|
+
getBoundingBox() {
|
|
543
|
+
if (!this.paths.length) {
|
|
544
|
+
return new modernPath2d.BoundingBox();
|
|
545
|
+
}
|
|
546
|
+
const min = modernPath2d.Point2D.MAX;
|
|
547
|
+
const max = modernPath2d.Point2D.MIN;
|
|
548
|
+
this.paths.forEach((path) => path.getMinMax(min, max));
|
|
549
|
+
return new modernPath2d.BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
550
|
+
}
|
|
551
|
+
highlight() {
|
|
552
|
+
const { characters, computedStyle: style } = this._text;
|
|
553
|
+
const fontSize = style.fontSize;
|
|
554
|
+
let group;
|
|
555
|
+
const groups = [];
|
|
556
|
+
let prevHighlight;
|
|
557
|
+
characters.forEach((character) => {
|
|
558
|
+
const highlight = character.parent.highlight;
|
|
559
|
+
if (highlight?.url) {
|
|
560
|
+
if (prevHighlight?.url === highlight.url) {
|
|
561
|
+
group.push(character);
|
|
562
|
+
} else {
|
|
563
|
+
group = [];
|
|
564
|
+
group.push(character);
|
|
565
|
+
groups.push(group);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
prevHighlight = highlight;
|
|
569
|
+
});
|
|
570
|
+
this.paths = groups.filter((characters2) => characters2.length).map((characters2) => {
|
|
571
|
+
return {
|
|
572
|
+
url: characters2[0].parent.highlight.url,
|
|
573
|
+
box: modernPath2d.BoundingBox.from(...characters2.map((c) => c.glyphBox)),
|
|
574
|
+
baseline: Math.max(...characters2.map((c) => c.baseline))
|
|
575
|
+
};
|
|
576
|
+
}).map((group2) => this._parseGroup(group2, fontSize)).flat();
|
|
577
|
+
}
|
|
578
|
+
_parseSvg(url) {
|
|
579
|
+
const svg = modernPath2d.parseSvgToDom(url);
|
|
580
|
+
const paths = modernPath2d.parseSvg(svg);
|
|
581
|
+
const min = modernPath2d.Point2D.MAX;
|
|
582
|
+
const max = modernPath2d.Point2D.MIN;
|
|
583
|
+
paths.forEach((path) => path.getMinMax(min, max));
|
|
584
|
+
const { x, y, width, height } = new modernPath2d.BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
585
|
+
const viewBox = svg.getAttribute("viewBox").split(" ").map(Number);
|
|
586
|
+
return {
|
|
587
|
+
paths,
|
|
588
|
+
box: new modernPath2d.BoundingBox(x, y, width, height),
|
|
589
|
+
viewBox: new modernPath2d.BoundingBox(...viewBox)
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
_parseGroup(group, fontSize) {
|
|
593
|
+
const { url, box: groupBox, baseline } = group;
|
|
594
|
+
const { box, viewBox, paths } = this._parseSvg(url);
|
|
595
|
+
const result = [];
|
|
596
|
+
const type = box.height / viewBox.height > 0.3 ? 0 : 1;
|
|
597
|
+
if (type === 0) {
|
|
598
|
+
const offset = {
|
|
599
|
+
x: groupBox.left - fontSize * 0.2,
|
|
600
|
+
y: groupBox.top
|
|
601
|
+
};
|
|
602
|
+
const scaleX = (groupBox.width + fontSize * 0.2 * 2) / box.width;
|
|
603
|
+
const scaleY = groupBox.height / box.height;
|
|
604
|
+
const m = new modernPath2d.Matrix3().translate(-box.x, -box.y).scale(scaleX, scaleY).translate(offset.x, offset.y);
|
|
605
|
+
paths.forEach((original) => {
|
|
606
|
+
result.push(original.clone().transform(m));
|
|
607
|
+
});
|
|
608
|
+
} else if (type === 1) {
|
|
609
|
+
const scale = fontSize / box.width * 2;
|
|
610
|
+
const width = box.width * scale;
|
|
611
|
+
const length = Math.ceil(groupBox.width / width);
|
|
612
|
+
const totalWidth = width * length;
|
|
613
|
+
const offset = {
|
|
614
|
+
x: groupBox.left + (groupBox.width - totalWidth) / 2 + fontSize * 0.1,
|
|
615
|
+
y: groupBox.top + baseline + fontSize * 0.1
|
|
616
|
+
};
|
|
617
|
+
const m = new modernPath2d.Matrix3().translate(-box.x, -box.y).scale(scale, scale).translate(offset.x, offset.y);
|
|
618
|
+
for (let i = 0; i < length; i++) {
|
|
619
|
+
const _m = m.clone().translate(i * width, 0);
|
|
620
|
+
paths.forEach((original) => {
|
|
621
|
+
result.push(original.clone().transform(_m));
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return result;
|
|
626
|
+
}
|
|
627
|
+
draw({ ctx }) {
|
|
739
628
|
drawPaths({
|
|
740
629
|
ctx,
|
|
741
|
-
paths:
|
|
742
|
-
fontSize: this.computedStyle.fontSize,
|
|
743
|
-
|
|
744
|
-
...config
|
|
630
|
+
paths: this.paths,
|
|
631
|
+
fontSize: this._text.computedStyle.fontSize,
|
|
632
|
+
fill: false
|
|
745
633
|
});
|
|
634
|
+
return this;
|
|
746
635
|
}
|
|
747
636
|
}
|
|
748
637
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
638
|
+
class Measurer extends Feature {
|
|
639
|
+
_styleToDomStyle(style) {
|
|
640
|
+
const _style = { ...style };
|
|
641
|
+
for (const key in style) {
|
|
642
|
+
if ([
|
|
643
|
+
"width",
|
|
644
|
+
"height",
|
|
645
|
+
"fontSize",
|
|
646
|
+
"letterSpacing",
|
|
647
|
+
"textStrokeWidth",
|
|
648
|
+
"shadowOffsetX",
|
|
649
|
+
"shadowOffsetY",
|
|
650
|
+
"shadowBlur"
|
|
651
|
+
].includes(key)) {
|
|
652
|
+
_style[key] = `${style[key]}px`;
|
|
653
|
+
} else {
|
|
654
|
+
_style[key] = style[key];
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return _style;
|
|
767
658
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
659
|
+
/**
|
|
660
|
+
* <section style="...">
|
|
661
|
+
* <ul>
|
|
662
|
+
* <li style="...">
|
|
663
|
+
* <span style="...">...</span>
|
|
664
|
+
* <span>...</span>
|
|
665
|
+
* </li>
|
|
666
|
+
* </ul>
|
|
667
|
+
* </section>
|
|
668
|
+
*/
|
|
669
|
+
createDom() {
|
|
670
|
+
const { paragraphs, computedStyle } = this._text;
|
|
671
|
+
const documentFragment = document.createDocumentFragment();
|
|
672
|
+
const dom = document.createElement("section");
|
|
673
|
+
Object.assign(dom.style, {
|
|
674
|
+
...this._styleToDomStyle(computedStyle),
|
|
675
|
+
position: "absolute",
|
|
676
|
+
visibility: "hidden"
|
|
677
|
+
});
|
|
678
|
+
const ul = document.createElement("ul");
|
|
679
|
+
Object.assign(ul.style, {
|
|
680
|
+
listStyle: "none",
|
|
681
|
+
padding: "0",
|
|
682
|
+
margin: "0"
|
|
683
|
+
});
|
|
684
|
+
paragraphs.forEach((paragraph) => {
|
|
685
|
+
const li = document.createElement("li");
|
|
686
|
+
Object.assign(li.style, this._styleToDomStyle(paragraph.style));
|
|
687
|
+
paragraph.fragments.forEach((fragment) => {
|
|
688
|
+
const span = document.createElement("span");
|
|
689
|
+
Object.assign(span.style, this._styleToDomStyle(fragment.style));
|
|
690
|
+
span.appendChild(document.createTextNode(fragment.content));
|
|
691
|
+
li.appendChild(span);
|
|
692
|
+
});
|
|
693
|
+
ul.appendChild(li);
|
|
694
|
+
});
|
|
695
|
+
dom.appendChild(ul);
|
|
696
|
+
documentFragment.appendChild(dom);
|
|
697
|
+
document.body.appendChild(documentFragment);
|
|
698
|
+
return {
|
|
699
|
+
dom,
|
|
700
|
+
destory: () => dom.parentNode?.removeChild(dom)
|
|
772
701
|
};
|
|
773
|
-
return this;
|
|
774
702
|
}
|
|
775
|
-
|
|
703
|
+
_measureDom(dom) {
|
|
704
|
+
const paragraphs = [];
|
|
705
|
+
const fragments = [];
|
|
776
706
|
const characters = [];
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
707
|
+
dom.querySelectorAll("li").forEach((li, paragraphIndex) => {
|
|
708
|
+
const pBox = li.getBoundingClientRect();
|
|
709
|
+
paragraphs.push({
|
|
710
|
+
paragraphIndex,
|
|
711
|
+
left: pBox.left,
|
|
712
|
+
top: pBox.top,
|
|
713
|
+
width: pBox.width,
|
|
714
|
+
height: pBox.height
|
|
715
|
+
});
|
|
716
|
+
li.querySelectorAll("span").forEach((span, fragmentIndex) => {
|
|
717
|
+
const fBox = li.getBoundingClientRect();
|
|
718
|
+
fragments.push({
|
|
719
|
+
paragraphIndex,
|
|
720
|
+
fragmentIndex,
|
|
721
|
+
left: fBox.left,
|
|
722
|
+
top: fBox.top,
|
|
723
|
+
width: fBox.width,
|
|
724
|
+
height: fBox.height
|
|
725
|
+
});
|
|
726
|
+
const text = span.firstChild;
|
|
727
|
+
if (text instanceof window.Text) {
|
|
728
|
+
const range = document.createRange();
|
|
729
|
+
range.selectNodeContents(text);
|
|
730
|
+
const len = text.data ? text.data.length : 0;
|
|
731
|
+
let i = 0;
|
|
732
|
+
for (; i <= len; ) {
|
|
733
|
+
range.setStart(text, Math.max(i - 1, 0));
|
|
734
|
+
range.setEnd(text, i);
|
|
735
|
+
const rects = range.getClientRects?.() ?? [range.getBoundingClientRect()];
|
|
736
|
+
let rect = rects[rects.length - 1];
|
|
737
|
+
if (rects.length > 1 && rect.width < 2) {
|
|
738
|
+
rect = rects[rects.length - 2];
|
|
739
|
+
}
|
|
740
|
+
const content = range.toString();
|
|
741
|
+
if (content !== "" && rect && rect.width + rect.height !== 0) {
|
|
742
|
+
characters.push({
|
|
743
|
+
content,
|
|
744
|
+
newParagraphIndex: -1,
|
|
745
|
+
paragraphIndex,
|
|
746
|
+
fragmentIndex,
|
|
747
|
+
characterIndex: i - 1,
|
|
748
|
+
top: rect.top,
|
|
749
|
+
left: rect.left,
|
|
750
|
+
height: rect.height,
|
|
751
|
+
width: rect.width,
|
|
752
|
+
textWidth: -1,
|
|
753
|
+
textHeight: -1
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
i++;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
});
|
|
761
|
+
return {
|
|
762
|
+
paragraphs,
|
|
763
|
+
fragments,
|
|
764
|
+
characters
|
|
765
|
+
};
|
|
799
766
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
767
|
+
measureDom(dom) {
|
|
768
|
+
const { paragraphs } = this._text;
|
|
769
|
+
const rect = dom.getBoundingClientRect();
|
|
770
|
+
const innerEl = dom.querySelector("ul");
|
|
771
|
+
const isVertical = window.getComputedStyle(dom).writingMode.includes("vertical");
|
|
772
|
+
const oldLineHeight = innerEl.style.lineHeight;
|
|
773
|
+
innerEl.style.lineHeight = "4000px";
|
|
774
|
+
const _paragraphs = [[]];
|
|
775
|
+
let fragments = _paragraphs[0];
|
|
776
|
+
const { characters: oldCharacters } = this._measureDom(dom);
|
|
777
|
+
if (oldCharacters.length > 0) {
|
|
778
|
+
fragments.push(oldCharacters[0]);
|
|
779
|
+
oldCharacters.reduce((prev, current) => {
|
|
780
|
+
const attr = isVertical ? "left" : "top";
|
|
781
|
+
if (Math.abs(current[attr] - prev[attr]) > 4e3 / 2) {
|
|
782
|
+
fragments = [];
|
|
783
|
+
_paragraphs.push(fragments);
|
|
784
|
+
}
|
|
785
|
+
fragments.push(current);
|
|
786
|
+
return current;
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
innerEl.style.lineHeight = oldLineHeight;
|
|
790
|
+
const measured = this._measureDom(dom);
|
|
791
|
+
measured.paragraphs.forEach((p) => {
|
|
792
|
+
const _p = paragraphs[p.paragraphIndex];
|
|
793
|
+
_p.boundingBox.left = p.left;
|
|
794
|
+
_p.boundingBox.top = p.top;
|
|
795
|
+
_p.boundingBox.width = p.width;
|
|
796
|
+
_p.boundingBox.height = p.height;
|
|
797
|
+
});
|
|
798
|
+
measured.fragments.forEach((f) => {
|
|
799
|
+
const _f = paragraphs[f.paragraphIndex].fragments[f.fragmentIndex];
|
|
800
|
+
_f.boundingBox.left = f.left;
|
|
801
|
+
_f.boundingBox.top = f.top;
|
|
802
|
+
_f.boundingBox.width = f.width;
|
|
803
|
+
_f.boundingBox.height = f.height;
|
|
804
|
+
});
|
|
805
|
+
const results = [];
|
|
806
|
+
let i = 0;
|
|
807
|
+
_paragraphs.forEach((oldCharacters2) => {
|
|
808
|
+
oldCharacters2.forEach((oldCharacter) => {
|
|
809
|
+
const character = measured.characters[i];
|
|
810
|
+
const { paragraphIndex, fragmentIndex, characterIndex } = character;
|
|
811
|
+
results.push({
|
|
812
|
+
...character,
|
|
813
|
+
newParagraphIndex: paragraphIndex,
|
|
814
|
+
textWidth: oldCharacter.width,
|
|
815
|
+
textHeight: oldCharacter.height,
|
|
816
|
+
left: character.left - rect.left,
|
|
817
|
+
top: character.top - rect.top
|
|
818
|
+
});
|
|
819
|
+
const item = paragraphs[paragraphIndex].fragments[fragmentIndex].characters[characterIndex];
|
|
820
|
+
item.boundingBox.left = results[i].left;
|
|
821
|
+
item.boundingBox.top = results[i].top;
|
|
822
|
+
item.boundingBox.width = results[i].width;
|
|
823
|
+
item.boundingBox.height = results[i].height;
|
|
824
|
+
item.textWidth = results[i].textWidth;
|
|
825
|
+
item.textHeight = results[i].textHeight;
|
|
826
|
+
i++;
|
|
827
|
+
});
|
|
828
|
+
});
|
|
829
|
+
return {
|
|
830
|
+
paragraphs,
|
|
831
|
+
boundingBox: new modernPath2d.BoundingBox(0, 0, rect.width, rect.height)
|
|
804
832
|
};
|
|
805
|
-
return this;
|
|
806
833
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
834
|
+
measure(dom) {
|
|
835
|
+
let destory;
|
|
836
|
+
if (!dom) {
|
|
837
|
+
({ dom, destory } = this.createDom());
|
|
838
|
+
}
|
|
839
|
+
const result = this.measureDom(dom);
|
|
840
|
+
destory?.();
|
|
841
|
+
return result;
|
|
811
842
|
}
|
|
812
843
|
}
|
|
813
844
|
|
|
@@ -866,6 +897,10 @@ class Parser extends Feature {
|
|
|
866
897
|
}
|
|
867
898
|
}
|
|
868
899
|
|
|
900
|
+
class Reflector extends Feature {
|
|
901
|
+
// TODO
|
|
902
|
+
}
|
|
903
|
+
|
|
869
904
|
class Renderer2D extends Feature {
|
|
870
905
|
setupView(options) {
|
|
871
906
|
const { ctx, pixelRatio } = options;
|
|
@@ -966,6 +1001,7 @@ class Text {
|
|
|
966
1001
|
__publicField(this, "style");
|
|
967
1002
|
__publicField(this, "effects");
|
|
968
1003
|
__publicField(this, "deformation");
|
|
1004
|
+
__publicField(this, "measureDom");
|
|
969
1005
|
__publicField(this, "needsUpdate", true);
|
|
970
1006
|
__publicField(this, "computedStyle", { ...defaultTextStyles });
|
|
971
1007
|
__publicField(this, "paragraphs", []);
|
|
@@ -977,19 +1013,23 @@ class Text {
|
|
|
977
1013
|
__publicField(this, "_effector", new Effector(this));
|
|
978
1014
|
__publicField(this, "_highlighter", new Highlighter(this));
|
|
979
1015
|
__publicField(this, "_renderer2D", new Renderer2D(this));
|
|
980
|
-
const { content = "", style = {}, effects, deformation } = options;
|
|
1016
|
+
const { content = "", style = {}, effects, deformation, measureDom } = options;
|
|
981
1017
|
this.content = content;
|
|
982
1018
|
this.style = style;
|
|
983
1019
|
this.effects = effects;
|
|
984
1020
|
this.deformation = deformation;
|
|
1021
|
+
this.measureDom = measureDom;
|
|
985
1022
|
}
|
|
986
1023
|
get characters() {
|
|
987
1024
|
return this.paragraphs.flatMap((p) => p.fragments.flatMap((f) => f.characters));
|
|
988
1025
|
}
|
|
989
|
-
measure(dom) {
|
|
1026
|
+
measure(dom = this.measureDom) {
|
|
990
1027
|
this.computedStyle = { ...defaultTextStyles, ...this.style };
|
|
1028
|
+
const old = this.paragraphs;
|
|
991
1029
|
this.paragraphs = this._parser.parse();
|
|
992
|
-
|
|
1030
|
+
const result = this._measurer.measure(dom);
|
|
1031
|
+
this.paragraphs = old;
|
|
1032
|
+
return result;
|
|
993
1033
|
}
|
|
994
1034
|
requestUpdate() {
|
|
995
1035
|
this.needsUpdate = true;
|
|
@@ -1006,7 +1046,7 @@ class Text {
|
|
|
1006
1046
|
this._highlighter.highlight();
|
|
1007
1047
|
const min = modernPath2d.Point2D.MAX;
|
|
1008
1048
|
const max = modernPath2d.Point2D.MIN;
|
|
1009
|
-
this.characters.forEach((c) => c.
|
|
1049
|
+
this.characters.forEach((c) => c.getMinMax(min, max));
|
|
1010
1050
|
this.renderBoundingBox = new modernPath2d.BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
1011
1051
|
return this;
|
|
1012
1052
|
}
|
|
@@ -1026,27 +1066,45 @@ class Text {
|
|
|
1026
1066
|
this._effector.getBoundingBox(),
|
|
1027
1067
|
this._highlighter.getBoundingBox()
|
|
1028
1068
|
);
|
|
1029
|
-
this._renderer2D.setupView({ pixelRatio, ctx });
|
|
1030
|
-
this._renderer2D.uploadColors({ ctx });
|
|
1031
|
-
this._highlighter.draw({ ctx });
|
|
1032
|
-
this._effector.draw({ ctx });
|
|
1033
1069
|
} else {
|
|
1034
1070
|
this.renderBoundingBox = modernPath2d.BoundingBox.from(
|
|
1035
1071
|
this.boundingBox,
|
|
1036
1072
|
this.renderBoundingBox,
|
|
1037
1073
|
this._highlighter.getBoundingBox()
|
|
1038
1074
|
);
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1075
|
+
}
|
|
1076
|
+
this._renderer2D.setupView({ pixelRatio, ctx });
|
|
1077
|
+
this._renderer2D.uploadColors({ ctx });
|
|
1078
|
+
this._highlighter.draw({ ctx });
|
|
1079
|
+
if (this.effects?.length) {
|
|
1080
|
+
this._effector.draw({ ctx });
|
|
1081
|
+
} else {
|
|
1042
1082
|
this._renderer2D.draw({ ctx });
|
|
1043
1083
|
}
|
|
1044
1084
|
return this;
|
|
1045
1085
|
}
|
|
1046
1086
|
}
|
|
1047
1087
|
|
|
1088
|
+
exports.Character = Character;
|
|
1089
|
+
exports.Deformer = Deformer;
|
|
1090
|
+
exports.Effector = Effector;
|
|
1091
|
+
exports.Fragment = Fragment;
|
|
1092
|
+
exports.Highlighter = Highlighter;
|
|
1093
|
+
exports.Measurer = Measurer;
|
|
1094
|
+
exports.Paragraph = Paragraph;
|
|
1095
|
+
exports.Parser = Parser;
|
|
1096
|
+
exports.Reflector = Reflector;
|
|
1097
|
+
exports.Renderer2D = Renderer2D;
|
|
1048
1098
|
exports.Text = Text;
|
|
1049
1099
|
exports.defaultTextStyles = defaultTextStyles;
|
|
1100
|
+
exports.drawPaths = drawPaths;
|
|
1101
|
+
exports.filterEmpty = filterEmpty;
|
|
1102
|
+
exports.getPointPosition = getPointPosition;
|
|
1103
|
+
exports.getRotationPoint = getRotationPoint;
|
|
1104
|
+
exports.getScalePoint = getScalePoint;
|
|
1105
|
+
exports.getSkewPoint = getSkewPoint;
|
|
1106
|
+
exports.parseColor = parseColor;
|
|
1107
|
+
exports.uploadColor = uploadColor;
|
|
1050
1108
|
Object.keys(modernFont).forEach(function (k) {
|
|
1051
1109
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = modernFont[k];
|
|
1052
1110
|
});
|