@eternalheart/angular-file-preview 1.6.5
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/LICENSE +22 -0
- package/README.md +879 -0
- package/README.zh-CN.md +876 -0
- package/lib/LICENSE +22 -0
- package/lib/README.md +879 -0
- package/lib/components/preview/file-preview-toolbar.d.ts +19 -0
- package/lib/components/preview/nav-arrows.d.ts +25 -0
- package/lib/components/preview/renderer-outlet.d.ts +23 -0
- package/lib/components/preview/toolbar-button.d.ts +12 -0
- package/lib/components/resizable-split.d.ts +32 -0
- package/lib/di/locale.service.d.ts +12 -0
- package/lib/di/request.service.d.ts +20 -0
- package/lib/di/theme-mode.d.ts +6 -0
- package/lib/di/theme.service.d.ts +9 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-avifLoader-BP3fgcMm-CZsJ9svm.mjs +55 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-avifLoader-BP3fgcMm-CZsJ9svm.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-RendererError-DtNihCIX-DtNihCIX.mjs +58 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-RendererError-DtNihCIX-DtNihCIX.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-UobTf36G.mjs +5835 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-UobTf36G.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-base.types-D5x7QPey-D5x7QPey.mjs +17 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-base.types-D5x7QPey-D5x7QPey.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index--7d8Hgi0-D-sg24Qs.mjs +284 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index--7d8Hgi0-D-sg24Qs.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-6dZS_Cfs-B1itLV5R.mjs +703 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-6dZS_Cfs-B1itLV5R.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-B1ANUCTy-BRs7TMLn.mjs +231 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-B1ANUCTy-BRs7TMLn.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-BEaqpRV8-BidVIVlO.mjs +552 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-BEaqpRV8-BidVIVlO.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-BGqTRZbm-CAOLRw20.mjs +688 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-BGqTRZbm-CAOLRw20.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-Bv3JRXKn-B4Wewc-4.mjs +273 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-Bv3JRXKn-B4Wewc-4.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-C0McUoqT-DJ35bhIz.mjs +288 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-C0McUoqT-DJ35bhIz.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-C518mdUd-B5SCzrzU.mjs +550 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-C518mdUd-B5SCzrzU.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CDjKPqyW-CmX5sdkL.mjs +102 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CDjKPqyW-CmX5sdkL.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CHi9tOe0-NOeQYAnM.mjs +516 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CHi9tOe0-NOeQYAnM.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CQwhffym-DAGw4Xy_.mjs +823 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CQwhffym-DAGw4Xy_.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CSCTj7ft-BfqruUyY.mjs +164 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-CSCTj7ft-BfqruUyY.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-Cb1RLXeO-Bj9gjS1Z.mjs +655 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-Cb1RLXeO-Bj9gjS1Z.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-Cw90Kdyg-BzrW_cyx.mjs +207 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-Cw90Kdyg-BzrW_cyx.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-D35x1nwM-CugEEXjg.mjs +199 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-D35x1nwM-CugEEXjg.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-D9jJNzeM-mWX59Aj2.mjs +194 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-D9jJNzeM-mWX59Aj2.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-DbmuvdvN-C29uLyt2.mjs +94 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-DbmuvdvN-C29uLyt2.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-DsNNZ59Q-C8MaSME6.mjs +468 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-DsNNZ59Q-C8MaSME6.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-DufW2Fuc-CTosCut6.mjs +193 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-DufW2Fuc-CTosCut6.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-TSTa_Q7E-DBhkL6pV.mjs +184 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-TSTa_Q7E-DBhkL6pV.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-pG0Ko5mI-DthQJg-X.mjs +492 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-pG0Ko5mI-DthQJg-X.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-shiki-highlight-CL9cG481-BKfwdOpN.mjs +68 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-eternalheart-angular-file-preview-shiki-highlight-CL9cG481-BKfwdOpN.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-heicLoader-CH_raQNn-BSXHd_oi.mjs +36 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-heicLoader-CH_raQNn-BSXHd_oi.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-jp2Loader-ldvCSsvm-DJEhfimG.mjs +121 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-jp2Loader-ldvCSsvm-DJEhfimG.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-psdLoader-D5CkupyY-D5Gegcdg.mjs +78 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-psdLoader-D5CkupyY-D5Gegcdg.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-rawLoader-0mLvxCNp-CCXn9Rdp.mjs +81 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-rawLoader-0mLvxCNp-CCXn9Rdp.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-tiffLoader-CmUAD1vO-0JqIws9t.mjs +59 -0
- package/lib/fesm2022/eternalheart-angular-file-preview-tiffLoader-CmUAD1vO-0JqIws9t.mjs.map +1 -0
- package/lib/fesm2022/eternalheart-angular-file-preview.mjs +2 -0
- package/lib/fesm2022/eternalheart-angular-file-preview.mjs.map +1 -0
- package/lib/file-preview-content.d.ts +65 -0
- package/lib/file-preview-embed.d.ts +30 -0
- package/lib/file-preview-modal.d.ts +34 -0
- package/lib/fp-core.d.ts +1 -0
- package/lib/index.css +2119 -0
- package/lib/index.d.ts +11 -0
- package/lib/renderers/Audio/index.d.ts +74 -0
- package/lib/renderers/Cad/index.d.ts +45 -0
- package/lib/renderers/Cad/toolbar.d.ts +15 -0
- package/lib/renderers/Csv/index.d.ts +26 -0
- package/lib/renderers/Doc/index.d.ts +19 -0
- package/lib/renderers/Docx/index.d.ts +42 -0
- package/lib/renderers/Epub/index.d.ts +57 -0
- package/lib/renderers/Font/font-preview-line.d.ts +26 -0
- package/lib/renderers/Font/index.d.ts +52 -0
- package/lib/renderers/Image/index.d.ts +79 -0
- package/lib/renderers/Json/index.d.ts +61 -0
- package/lib/renderers/Markdown/index.d.ts +35 -0
- package/lib/renderers/Mobi/index.d.ts +51 -0
- package/lib/renderers/Msg/index.d.ts +47 -0
- package/lib/renderers/Pdf/index.d.ts +55 -0
- package/lib/renderers/Ppt/index.d.ts +19 -0
- package/lib/renderers/Pptx/index.d.ts +29 -0
- package/lib/renderers/RendererError.d.ts +9 -0
- package/lib/renderers/RendererLoading.d.ts +7 -0
- package/lib/renderers/Subtitle/index.d.ts +25 -0
- package/lib/renderers/Text/index.d.ts +29 -0
- package/lib/renderers/Unsupported/index.d.ts +15 -0
- package/lib/renderers/Video/index.d.ts +28 -0
- package/lib/renderers/Xlsx/index.d.ts +25 -0
- package/lib/renderers/Xml/index.d.ts +26 -0
- package/lib/renderers/Zip/index.d.ts +58 -0
- package/lib/renderers/Zip/tree-item.d.ts +29 -0
- package/lib/renderers/base.types.d.ts +10 -0
- package/lib/renderers/lazy.d.ts +23 -0
- package/lib/renderers/registry.d.ts +13 -0
- package/lib/renderers/toolbar.types.d.ts +19 -0
- package/lib/types.d.ts +26 -0
- package/lib/utils/audio-player.d.ts +20 -0
- package/lib/utils/shiki-highlight.d.ts +7 -0
- package/package.json +119 -0
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, inject, signal, computed, effect, untracked, DestroyRef, viewChild, afterNextRender, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { parse } from 'opentype.js';
|
|
4
|
+
import { L as LocaleService, R as RequestService, T as ThemeService, g as getFallbackTranslator } from './eternalheart-angular-file-preview-eternalheart-angular-file-preview-UobTf36G.mjs';
|
|
5
|
+
import { R as RendererError } from './eternalheart-angular-file-preview-eternalheart-angular-file-preview-RendererError-DtNihCIX-DtNihCIX.mjs';
|
|
6
|
+
|
|
7
|
+
class FontPreviewLine {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.font = input(null);
|
|
10
|
+
this.text = input.required();
|
|
11
|
+
this.fontSize = input.required();
|
|
12
|
+
this.renderMode = input.required();
|
|
13
|
+
this.theme = input.required();
|
|
14
|
+
this.wrapper = viewChild('wrapperRef');
|
|
15
|
+
this.canvas = viewChild('canvasRef');
|
|
16
|
+
this.resizeObserver = null;
|
|
17
|
+
afterNextRender(() => {
|
|
18
|
+
if (this.renderMode() === 'canvas') {
|
|
19
|
+
this.drawCanvas();
|
|
20
|
+
this.setupObserver();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
effect(() => {
|
|
24
|
+
this.text();
|
|
25
|
+
this.fontSize();
|
|
26
|
+
this.renderMode();
|
|
27
|
+
this.theme();
|
|
28
|
+
this.font();
|
|
29
|
+
if (this.renderMode() === 'canvas') {
|
|
30
|
+
requestAnimationFrame(() => {
|
|
31
|
+
this.drawCanvas();
|
|
32
|
+
this.setupObserver();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
inject(DestroyRef).onDestroy(() => this.teardownObserver());
|
|
37
|
+
}
|
|
38
|
+
teardownObserver() {
|
|
39
|
+
if (this.resizeObserver) {
|
|
40
|
+
this.resizeObserver.disconnect();
|
|
41
|
+
this.resizeObserver = null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
drawCanvas() {
|
|
45
|
+
const wrapper = this.wrapper()?.nativeElement;
|
|
46
|
+
const canvas = this.canvas()?.nativeElement;
|
|
47
|
+
const font = this.font();
|
|
48
|
+
if (!wrapper || !canvas || this.renderMode() !== 'canvas' || !font)
|
|
49
|
+
return;
|
|
50
|
+
const containerWidth = wrapper.clientWidth || 600;
|
|
51
|
+
const dpr = window.devicePixelRatio || 1;
|
|
52
|
+
const fontSize = this.fontSize();
|
|
53
|
+
const lineHeight = fontSize * 1.4;
|
|
54
|
+
const fillColor = this.theme() === 'light' ? '#1f2937' : '#f3f4f6';
|
|
55
|
+
const wrapLine = (line) => {
|
|
56
|
+
if (!line)
|
|
57
|
+
return [''];
|
|
58
|
+
const result = [];
|
|
59
|
+
let buf = '';
|
|
60
|
+
for (const ch of Array.from(line)) {
|
|
61
|
+
const next = buf + ch;
|
|
62
|
+
const w = font.getAdvanceWidth(next, fontSize);
|
|
63
|
+
if (w > containerWidth && buf) {
|
|
64
|
+
result.push(buf);
|
|
65
|
+
buf = ch;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
buf = next;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (buf)
|
|
72
|
+
result.push(buf);
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
75
|
+
const wrappedLines = [];
|
|
76
|
+
this.text().split('\n').forEach((seg) => {
|
|
77
|
+
wrapLine(seg).forEach((l) => wrappedLines.push(l));
|
|
78
|
+
});
|
|
79
|
+
const width = containerWidth;
|
|
80
|
+
const height = lineHeight * wrappedLines.length + 4;
|
|
81
|
+
canvas.width = Math.max(1, Math.floor(width * dpr));
|
|
82
|
+
canvas.height = Math.max(1, Math.floor(height * dpr));
|
|
83
|
+
canvas.style.width = `${width}px`;
|
|
84
|
+
canvas.style.height = `${height}px`;
|
|
85
|
+
const ctx = canvas.getContext('2d');
|
|
86
|
+
if (!ctx)
|
|
87
|
+
return;
|
|
88
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
89
|
+
ctx.clearRect(0, 0, width, height);
|
|
90
|
+
wrappedLines.forEach((line, idx) => {
|
|
91
|
+
const path = font.getPath(line, 0, fontSize + idx * lineHeight, fontSize);
|
|
92
|
+
path.fill = fillColor;
|
|
93
|
+
path.draw(ctx);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
setupObserver() {
|
|
97
|
+
this.teardownObserver();
|
|
98
|
+
if (this.renderMode() !== 'canvas')
|
|
99
|
+
return;
|
|
100
|
+
if (typeof ResizeObserver === 'undefined')
|
|
101
|
+
return;
|
|
102
|
+
const wrapper = this.wrapper()?.nativeElement;
|
|
103
|
+
if (!wrapper)
|
|
104
|
+
return;
|
|
105
|
+
this.resizeObserver = new ResizeObserver(() => this.drawCanvas());
|
|
106
|
+
this.resizeObserver.observe(wrapper);
|
|
107
|
+
}
|
|
108
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: FontPreviewLine, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
109
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: FontPreviewLine, isStandalone: true, selector: "afp-font-preview-line", inputs: { font: { classPropertyName: "font", publicName: "font", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, fontSize: { classPropertyName: "fontSize", publicName: "fontSize", isSignal: true, isRequired: true, transformFunction: null }, renderMode: { classPropertyName: "renderMode", publicName: "renderMode", isSignal: true, isRequired: true, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "wrapper", first: true, predicate: ["wrapperRef"], descendants: true, isSignal: true }, { propertyName: "canvas", first: true, predicate: ["canvasRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
110
|
+
<div #wrapperRef class="afp-w-full">
|
|
111
|
+
@if (renderMode() === 'canvas') {
|
|
112
|
+
<canvas #canvasRef class="afp-block"></canvas>
|
|
113
|
+
} @else {
|
|
114
|
+
<div
|
|
115
|
+
class="afp-w-full afp-text-fg-primary afp-whitespace-pre-wrap afp-break-words"
|
|
116
|
+
[style.fontFamily]="'PreviewFont, sans-serif'"
|
|
117
|
+
[style.fontSize]="fontSize() + 'px'"
|
|
118
|
+
[style.lineHeight]="1.4"
|
|
119
|
+
>{{ text() }}</div>
|
|
120
|
+
}
|
|
121
|
+
</div>
|
|
122
|
+
`, isInline: true, styles: [":host{display:block;width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
123
|
+
}
|
|
124
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: FontPreviewLine, decorators: [{
|
|
125
|
+
type: Component,
|
|
126
|
+
args: [{ selector: 'afp-font-preview-line', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
127
|
+
<div #wrapperRef class="afp-w-full">
|
|
128
|
+
@if (renderMode() === 'canvas') {
|
|
129
|
+
<canvas #canvasRef class="afp-block"></canvas>
|
|
130
|
+
} @else {
|
|
131
|
+
<div
|
|
132
|
+
class="afp-w-full afp-text-fg-primary afp-whitespace-pre-wrap afp-break-words"
|
|
133
|
+
[style.fontFamily]="'PreviewFont, sans-serif'"
|
|
134
|
+
[style.fontSize]="fontSize() + 'px'"
|
|
135
|
+
[style.lineHeight]="1.4"
|
|
136
|
+
>{{ text() }}</div>
|
|
137
|
+
}
|
|
138
|
+
</div>
|
|
139
|
+
`, styles: [":host{display:block;width:100%}\n"] }]
|
|
140
|
+
}], ctorParameters: () => [] });
|
|
141
|
+
|
|
142
|
+
const MAGIC_WOFF2 = 0x774f4632;
|
|
143
|
+
const MAGIC_WOFF = 0x774f4646;
|
|
144
|
+
const MAGIC_OTTO = 0x4f54544f;
|
|
145
|
+
const MAGIC_TTF1 = 0x00010000;
|
|
146
|
+
const MAGIC_TRUE = 0x74727565;
|
|
147
|
+
const detectMagic = (buf) => {
|
|
148
|
+
if (buf.byteLength < 4)
|
|
149
|
+
return 'unknown';
|
|
150
|
+
const m = new DataView(buf).getUint32(0);
|
|
151
|
+
if (m === MAGIC_WOFF2)
|
|
152
|
+
return 'woff2';
|
|
153
|
+
if (m === MAGIC_WOFF)
|
|
154
|
+
return 'woff';
|
|
155
|
+
if (m === MAGIC_OTTO)
|
|
156
|
+
return 'otf';
|
|
157
|
+
if (m === MAGIC_TTF1 || m === MAGIC_TRUE)
|
|
158
|
+
return 'ttf';
|
|
159
|
+
return 'unknown';
|
|
160
|
+
};
|
|
161
|
+
const DEFAULT_SAMPLES = {
|
|
162
|
+
latin: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz\n0123456789 .,;:!?@#$%&*()[]{}',
|
|
163
|
+
chinese: '春夏秋冬东南西北天地人和风雨雷电山水日月',
|
|
164
|
+
mixed: 'The Quick Brown Fox Jumps Over The Lazy Dog\n敏捷的棕色狐狸跳过了懒狗',
|
|
165
|
+
};
|
|
166
|
+
const SIZES = [72, 48, 36, 24, 18];
|
|
167
|
+
class FontRenderer {
|
|
168
|
+
constructor() {
|
|
169
|
+
this.url = input.required();
|
|
170
|
+
this.locale = inject(LocaleService, { optional: true });
|
|
171
|
+
this.request = inject(RequestService, { optional: true });
|
|
172
|
+
this.theme = inject(ThemeService, { optional: true });
|
|
173
|
+
this.t = this.locale?.t() ?? getFallbackTranslator();
|
|
174
|
+
this.sizes = SIZES;
|
|
175
|
+
this.samples = DEFAULT_SAMPLES;
|
|
176
|
+
this.font = signal(null);
|
|
177
|
+
this.metadata = signal(null);
|
|
178
|
+
this.metadataStatus = signal('loading');
|
|
179
|
+
this.loading = signal(true);
|
|
180
|
+
this.error = signal(null);
|
|
181
|
+
this.customText = signal('');
|
|
182
|
+
this.renderMode = signal('fontface');
|
|
183
|
+
this.displayText = computed(() => this.customText() || DEFAULT_SAMPLES.mixed);
|
|
184
|
+
this.showMetaPlaceholder = computed(() => this.metadataStatus() !== 'ready');
|
|
185
|
+
this.metaPlaceholder = computed(() => this.metadataStatus() === 'loading' ? this.t('font.metadata_loading') : this.t('font.metadata_unavailable'));
|
|
186
|
+
this.effectiveRenderMode = computed(() => (this.renderMode() === 'canvas' && this.font() ? 'canvas' : 'fontface'));
|
|
187
|
+
this.resolvedTheme = computed(() => this.theme?.theme() ?? 'dark');
|
|
188
|
+
this.fontFace = null;
|
|
189
|
+
this.getToolbarGroups = () => [];
|
|
190
|
+
effect(() => {
|
|
191
|
+
const url = this.url();
|
|
192
|
+
if (!url)
|
|
193
|
+
return;
|
|
194
|
+
untracked(() => { void this.loadFont(); });
|
|
195
|
+
});
|
|
196
|
+
inject(DestroyRef).onDestroy(() => this.releaseFontFace());
|
|
197
|
+
}
|
|
198
|
+
onCustomInput(ev) {
|
|
199
|
+
this.customText.set(ev.target.value);
|
|
200
|
+
}
|
|
201
|
+
releaseFontFace() {
|
|
202
|
+
if (this.fontFace) {
|
|
203
|
+
document.fonts.delete(this.fontFace);
|
|
204
|
+
this.fontFace = null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
detectFormat(url) {
|
|
208
|
+
const ext = url.split('.').pop()?.toLowerCase().split('?')[0] || '';
|
|
209
|
+
const formatMap = {
|
|
210
|
+
ttf: 'TrueType (TTF)',
|
|
211
|
+
otf: 'OpenType (OTF)',
|
|
212
|
+
woff: 'Web Open Font Format (WOFF)',
|
|
213
|
+
woff2: 'Web Open Font Format 2 (WOFF2)',
|
|
214
|
+
};
|
|
215
|
+
return formatMap[ext] || 'TTF';
|
|
216
|
+
}
|
|
217
|
+
formatLabel(magic, url) {
|
|
218
|
+
const labels = {
|
|
219
|
+
woff2: 'Web Open Font Format 2 (WOFF2)',
|
|
220
|
+
woff: 'Web Open Font Format (WOFF)',
|
|
221
|
+
otf: 'OpenType (OTF)',
|
|
222
|
+
ttf: 'TrueType (TTF)',
|
|
223
|
+
unknown: null,
|
|
224
|
+
};
|
|
225
|
+
return labels[magic] ?? this.detectFormat(url);
|
|
226
|
+
}
|
|
227
|
+
async loadFontFace(faceBuffer) {
|
|
228
|
+
try {
|
|
229
|
+
this.fontFace = new FontFace('PreviewFont', faceBuffer);
|
|
230
|
+
await this.fontFace.load();
|
|
231
|
+
document.fonts.add(this.fontFace);
|
|
232
|
+
this.renderMode.set('fontface');
|
|
233
|
+
}
|
|
234
|
+
catch (faceErr) {
|
|
235
|
+
console.warn('[FontRenderer] FontFace API rejected, fallback to Canvas:', faceErr);
|
|
236
|
+
this.renderMode.set('canvas');
|
|
237
|
+
throw faceErr;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async loadMetadata(arrayBuffer, magic) {
|
|
241
|
+
if (magic === 'woff2') {
|
|
242
|
+
throw new Error('WOFF2 metadata parsing intentionally skipped');
|
|
243
|
+
}
|
|
244
|
+
const fontData = parse(arrayBuffer);
|
|
245
|
+
if (!fontData) {
|
|
246
|
+
throw new Error('Font data is invalid');
|
|
247
|
+
}
|
|
248
|
+
const rawNames = (fontData.names || {});
|
|
249
|
+
const platformTables = ['windows', 'macintosh', 'unicode']
|
|
250
|
+
.map((k) => rawNames[k])
|
|
251
|
+
.filter((t) => !!t && typeof t === 'object');
|
|
252
|
+
const pickName = (key) => {
|
|
253
|
+
for (const table of platformTables) {
|
|
254
|
+
const entry = table[key];
|
|
255
|
+
const val = entry?.en || entry?.['zh-Hans'];
|
|
256
|
+
if (val)
|
|
257
|
+
return val;
|
|
258
|
+
}
|
|
259
|
+
const flat = rawNames[key];
|
|
260
|
+
return flat?.en || flat?.['zh-Hans'] || '';
|
|
261
|
+
};
|
|
262
|
+
const meta = {
|
|
263
|
+
family: pickName('fontFamily') || pickName('postScriptName') || 'Unknown',
|
|
264
|
+
subfamily: pickName('fontSubfamily'),
|
|
265
|
+
version: pickName('version'),
|
|
266
|
+
designer: pickName('designer'),
|
|
267
|
+
glyphCount: fontData.numGlyphs || 0,
|
|
268
|
+
format: this.formatLabel(magic, this.url()),
|
|
269
|
+
};
|
|
270
|
+
this.font.set(fontData);
|
|
271
|
+
this.metadata.set(meta);
|
|
272
|
+
this.metadataStatus.set('ready');
|
|
273
|
+
}
|
|
274
|
+
async loadFont() {
|
|
275
|
+
this.releaseFontFace();
|
|
276
|
+
this.font.set(null);
|
|
277
|
+
try {
|
|
278
|
+
this.loading.set(true);
|
|
279
|
+
this.error.set(null);
|
|
280
|
+
this.metadataStatus.set('loading');
|
|
281
|
+
const fetcher = this.request?.fetcher() ?? ((u, init) => fetch(u, init));
|
|
282
|
+
const response = await fetcher(this.url());
|
|
283
|
+
if (!response.ok) {
|
|
284
|
+
throw new Error('Failed to load font file');
|
|
285
|
+
}
|
|
286
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
287
|
+
const faceBuffer = arrayBuffer.slice(0);
|
|
288
|
+
const magic = detectMagic(arrayBuffer);
|
|
289
|
+
const facePromise = this.loadFontFace(faceBuffer);
|
|
290
|
+
const metadataPromise = this.loadMetadata(arrayBuffer, magic);
|
|
291
|
+
await facePromise.catch(() => {
|
|
292
|
+
// FontFace 失败由 metadata 兜底
|
|
293
|
+
});
|
|
294
|
+
this.loading.set(false);
|
|
295
|
+
try {
|
|
296
|
+
await metadataPromise;
|
|
297
|
+
}
|
|
298
|
+
catch (metaErr) {
|
|
299
|
+
if (magic !== 'woff2') {
|
|
300
|
+
console.warn('[FontRenderer] Metadata parse failed, font is still rendered via FontFace:', metaErr instanceof Error ? metaErr.message : String(metaErr));
|
|
301
|
+
}
|
|
302
|
+
this.metadataStatus.set('unavailable');
|
|
303
|
+
this.metadata.set({
|
|
304
|
+
family: 'Unknown',
|
|
305
|
+
subfamily: '',
|
|
306
|
+
version: '',
|
|
307
|
+
designer: '',
|
|
308
|
+
glyphCount: 0,
|
|
309
|
+
format: this.formatLabel(magic, this.url()),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
console.warn('[FontRenderer] Failed to load font:', err instanceof Error ? err.message : String(err));
|
|
315
|
+
this.error.set(this.t('font.load_failed'));
|
|
316
|
+
this.loading.set(false);
|
|
317
|
+
this.metadataStatus.set('unavailable');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: FontRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
321
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: FontRenderer, isStandalone: true, selector: "afp-font-renderer", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "afp-block afp-w-full afp-h-full" }, ngImport: i0, template: `
|
|
322
|
+
<div class="afp-flex afp-flex-col afp-w-full afp-h-full afp-overflow-hidden">
|
|
323
|
+
@if (loading()) {
|
|
324
|
+
<div class="afp-flex afp-items-center afp-justify-center afp-w-full afp-h-full">
|
|
325
|
+
<div class="afp-text-fg-secondary">{{ t('font.loading') }}</div>
|
|
326
|
+
</div>
|
|
327
|
+
} @else if (error() || !metadata()) {
|
|
328
|
+
<afp-renderer-error [message]="error() || t('font.parse_failed')" />
|
|
329
|
+
} @else {
|
|
330
|
+
<div class="afp-flex-shrink-0 afp-px-6 afp-py-4 afp-bg-surface-1 afp-border-b afp-border-line-weak afp-min-w-0">
|
|
331
|
+
<div class="afp-grid afp-grid-cols-2 afp-gap-x-6 afp-gap-y-2 afp-text-sm afp-min-w-0">
|
|
332
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
333
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.family') }}:</span>
|
|
334
|
+
<span class="afp-text-fg-primary afp-font-semibold afp-truncate">
|
|
335
|
+
{{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.family }}
|
|
336
|
+
</span>
|
|
337
|
+
</div>
|
|
338
|
+
@if (metadata()!.subfamily) {
|
|
339
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
340
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.subfamily') }}:</span>
|
|
341
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.subfamily }}</span>
|
|
342
|
+
</div>
|
|
343
|
+
}
|
|
344
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
345
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.format') }}:</span>
|
|
346
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.format }}</span>
|
|
347
|
+
</div>
|
|
348
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
349
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.glyphs') }}:</span>
|
|
350
|
+
<span class="afp-text-fg-primary afp-truncate">
|
|
351
|
+
{{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.glyphCount }}
|
|
352
|
+
</span>
|
|
353
|
+
</div>
|
|
354
|
+
@if (metadata()!.designer) {
|
|
355
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
356
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.designer') }}:</span>
|
|
357
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.designer }}</span>
|
|
358
|
+
</div>
|
|
359
|
+
}
|
|
360
|
+
@if (metadata()!.version) {
|
|
361
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
362
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.version') }}:</span>
|
|
363
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.version }}</span>
|
|
364
|
+
</div>
|
|
365
|
+
}
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<div class="afp-flex-1 afp-overflow-auto afp-min-w-0">
|
|
370
|
+
<div class="afp-px-6 afp-py-6 afp-space-y-8 afp-min-w-0">
|
|
371
|
+
<div class="afp-min-w-0">
|
|
372
|
+
<label class="afp-block afp-text-xs afp-text-fg-tertiary afp-mb-2">
|
|
373
|
+
{{ t('font.sample_text_placeholder') }}
|
|
374
|
+
</label>
|
|
375
|
+
<textarea
|
|
376
|
+
[value]="customText()"
|
|
377
|
+
class="afp-block afp-w-full afp-box-border afp-px-3 afp-py-2.5 afp-bg-surface-2 afp-text-fg-primary afp-text-sm afp-leading-relaxed afp-border afp-border-line afp-rounded-md afp-resize-y focus:afp-outline-none focus:afp-border-line-strong"
|
|
378
|
+
rows="2"
|
|
379
|
+
[placeholder]="t('font.sample_text_placeholder')"
|
|
380
|
+
[style.minHeight]="'64px'"
|
|
381
|
+
[style.maxHeight]="'160px'"
|
|
382
|
+
(input)="onCustomInput($event)"
|
|
383
|
+
></textarea>
|
|
384
|
+
</div>
|
|
385
|
+
|
|
386
|
+
<div class="afp-space-y-6 afp-min-w-0">
|
|
387
|
+
@for (size of sizes; track size) {
|
|
388
|
+
<div class="afp-space-y-2 afp-min-w-0">
|
|
389
|
+
<div class="afp-text-xs afp-text-fg-tertiary">{{ size }}px</div>
|
|
390
|
+
<afp-font-preview-line
|
|
391
|
+
[font]="font()"
|
|
392
|
+
[text]="displayText()"
|
|
393
|
+
[fontSize]="size"
|
|
394
|
+
[renderMode]="effectiveRenderMode()"
|
|
395
|
+
[theme]="resolvedTheme()"
|
|
396
|
+
/>
|
|
397
|
+
</div>
|
|
398
|
+
}
|
|
399
|
+
</div>
|
|
400
|
+
|
|
401
|
+
<div class="afp-space-y-6 afp-pt-6 afp-border-t afp-border-line-weak afp-min-w-0">
|
|
402
|
+
<div class="afp-min-w-0">
|
|
403
|
+
<div class="afp-text-sm afp-text-fg-tertiary afp-mb-3">Latin Alphabet</div>
|
|
404
|
+
<afp-font-preview-line
|
|
405
|
+
[font]="font()"
|
|
406
|
+
[text]="samples.latin"
|
|
407
|
+
[fontSize]="24"
|
|
408
|
+
[renderMode]="effectiveRenderMode()"
|
|
409
|
+
[theme]="resolvedTheme()"
|
|
410
|
+
/>
|
|
411
|
+
</div>
|
|
412
|
+
|
|
413
|
+
<div class="afp-min-w-0">
|
|
414
|
+
<div class="afp-text-sm afp-text-fg-tertiary afp-mb-3">Chinese Characters</div>
|
|
415
|
+
<afp-font-preview-line
|
|
416
|
+
[font]="font()"
|
|
417
|
+
[text]="samples.chinese"
|
|
418
|
+
[fontSize]="24"
|
|
419
|
+
[renderMode]="effectiveRenderMode()"
|
|
420
|
+
[theme]="resolvedTheme()"
|
|
421
|
+
/>
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
}
|
|
427
|
+
</div>
|
|
428
|
+
`, isInline: true, dependencies: [{ kind: "component", type: RendererError, selector: "afp-renderer-error", inputs: ["message", "detail", "showIcon"] }, { kind: "component", type: FontPreviewLine, selector: "afp-font-preview-line", inputs: ["font", "text", "fontSize", "renderMode", "theme"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
429
|
+
}
|
|
430
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: FontRenderer, decorators: [{
|
|
431
|
+
type: Component,
|
|
432
|
+
args: [{
|
|
433
|
+
selector: 'afp-font-renderer',
|
|
434
|
+
standalone: true,
|
|
435
|
+
imports: [RendererError, FontPreviewLine],
|
|
436
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
437
|
+
host: { class: 'afp-block afp-w-full afp-h-full' },
|
|
438
|
+
template: `
|
|
439
|
+
<div class="afp-flex afp-flex-col afp-w-full afp-h-full afp-overflow-hidden">
|
|
440
|
+
@if (loading()) {
|
|
441
|
+
<div class="afp-flex afp-items-center afp-justify-center afp-w-full afp-h-full">
|
|
442
|
+
<div class="afp-text-fg-secondary">{{ t('font.loading') }}</div>
|
|
443
|
+
</div>
|
|
444
|
+
} @else if (error() || !metadata()) {
|
|
445
|
+
<afp-renderer-error [message]="error() || t('font.parse_failed')" />
|
|
446
|
+
} @else {
|
|
447
|
+
<div class="afp-flex-shrink-0 afp-px-6 afp-py-4 afp-bg-surface-1 afp-border-b afp-border-line-weak afp-min-w-0">
|
|
448
|
+
<div class="afp-grid afp-grid-cols-2 afp-gap-x-6 afp-gap-y-2 afp-text-sm afp-min-w-0">
|
|
449
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
450
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.family') }}:</span>
|
|
451
|
+
<span class="afp-text-fg-primary afp-font-semibold afp-truncate">
|
|
452
|
+
{{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.family }}
|
|
453
|
+
</span>
|
|
454
|
+
</div>
|
|
455
|
+
@if (metadata()!.subfamily) {
|
|
456
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
457
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.subfamily') }}:</span>
|
|
458
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.subfamily }}</span>
|
|
459
|
+
</div>
|
|
460
|
+
}
|
|
461
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
462
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.format') }}:</span>
|
|
463
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.format }}</span>
|
|
464
|
+
</div>
|
|
465
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
466
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.glyphs') }}:</span>
|
|
467
|
+
<span class="afp-text-fg-primary afp-truncate">
|
|
468
|
+
{{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.glyphCount }}
|
|
469
|
+
</span>
|
|
470
|
+
</div>
|
|
471
|
+
@if (metadata()!.designer) {
|
|
472
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
473
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.designer') }}:</span>
|
|
474
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.designer }}</span>
|
|
475
|
+
</div>
|
|
476
|
+
}
|
|
477
|
+
@if (metadata()!.version) {
|
|
478
|
+
<div class="afp-flex afp-items-center afp-gap-2 afp-min-w-0">
|
|
479
|
+
<span class="afp-text-fg-tertiary afp-flex-shrink-0">{{ t('font.meta.version') }}:</span>
|
|
480
|
+
<span class="afp-text-fg-primary afp-truncate">{{ metadata()!.version }}</span>
|
|
481
|
+
</div>
|
|
482
|
+
}
|
|
483
|
+
</div>
|
|
484
|
+
</div>
|
|
485
|
+
|
|
486
|
+
<div class="afp-flex-1 afp-overflow-auto afp-min-w-0">
|
|
487
|
+
<div class="afp-px-6 afp-py-6 afp-space-y-8 afp-min-w-0">
|
|
488
|
+
<div class="afp-min-w-0">
|
|
489
|
+
<label class="afp-block afp-text-xs afp-text-fg-tertiary afp-mb-2">
|
|
490
|
+
{{ t('font.sample_text_placeholder') }}
|
|
491
|
+
</label>
|
|
492
|
+
<textarea
|
|
493
|
+
[value]="customText()"
|
|
494
|
+
class="afp-block afp-w-full afp-box-border afp-px-3 afp-py-2.5 afp-bg-surface-2 afp-text-fg-primary afp-text-sm afp-leading-relaxed afp-border afp-border-line afp-rounded-md afp-resize-y focus:afp-outline-none focus:afp-border-line-strong"
|
|
495
|
+
rows="2"
|
|
496
|
+
[placeholder]="t('font.sample_text_placeholder')"
|
|
497
|
+
[style.minHeight]="'64px'"
|
|
498
|
+
[style.maxHeight]="'160px'"
|
|
499
|
+
(input)="onCustomInput($event)"
|
|
500
|
+
></textarea>
|
|
501
|
+
</div>
|
|
502
|
+
|
|
503
|
+
<div class="afp-space-y-6 afp-min-w-0">
|
|
504
|
+
@for (size of sizes; track size) {
|
|
505
|
+
<div class="afp-space-y-2 afp-min-w-0">
|
|
506
|
+
<div class="afp-text-xs afp-text-fg-tertiary">{{ size }}px</div>
|
|
507
|
+
<afp-font-preview-line
|
|
508
|
+
[font]="font()"
|
|
509
|
+
[text]="displayText()"
|
|
510
|
+
[fontSize]="size"
|
|
511
|
+
[renderMode]="effectiveRenderMode()"
|
|
512
|
+
[theme]="resolvedTheme()"
|
|
513
|
+
/>
|
|
514
|
+
</div>
|
|
515
|
+
}
|
|
516
|
+
</div>
|
|
517
|
+
|
|
518
|
+
<div class="afp-space-y-6 afp-pt-6 afp-border-t afp-border-line-weak afp-min-w-0">
|
|
519
|
+
<div class="afp-min-w-0">
|
|
520
|
+
<div class="afp-text-sm afp-text-fg-tertiary afp-mb-3">Latin Alphabet</div>
|
|
521
|
+
<afp-font-preview-line
|
|
522
|
+
[font]="font()"
|
|
523
|
+
[text]="samples.latin"
|
|
524
|
+
[fontSize]="24"
|
|
525
|
+
[renderMode]="effectiveRenderMode()"
|
|
526
|
+
[theme]="resolvedTheme()"
|
|
527
|
+
/>
|
|
528
|
+
</div>
|
|
529
|
+
|
|
530
|
+
<div class="afp-min-w-0">
|
|
531
|
+
<div class="afp-text-sm afp-text-fg-tertiary afp-mb-3">Chinese Characters</div>
|
|
532
|
+
<afp-font-preview-line
|
|
533
|
+
[font]="font()"
|
|
534
|
+
[text]="samples.chinese"
|
|
535
|
+
[fontSize]="24"
|
|
536
|
+
[renderMode]="effectiveRenderMode()"
|
|
537
|
+
[theme]="resolvedTheme()"
|
|
538
|
+
/>
|
|
539
|
+
</div>
|
|
540
|
+
</div>
|
|
541
|
+
</div>
|
|
542
|
+
</div>
|
|
543
|
+
}
|
|
544
|
+
</div>
|
|
545
|
+
`,
|
|
546
|
+
}]
|
|
547
|
+
}], ctorParameters: () => [] });
|
|
548
|
+
|
|
549
|
+
export { FontRenderer };
|
|
550
|
+
//# sourceMappingURL=eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-C518mdUd-B5SCzrzU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eternalheart-angular-file-preview-eternalheart-angular-file-preview-index-C518mdUd-B5SCzrzU.mjs","sources":["../fesm2022/eternalheart-angular-file-preview-index-C518mdUd.mjs"],"sourcesContent":["import * as i0 from '@angular/core';\nimport { input, viewChild, afterNextRender, effect, inject, DestroyRef, ChangeDetectionStrategy, Component, signal, computed, untracked } from '@angular/core';\nimport { parse } from 'opentype.js';\nimport { L as LocaleService, R as RequestService, T as ThemeService, g as getFallbackTranslator } from './eternalheart-angular-file-preview-eternalheart-angular-file-preview-DXwNhxAB.mjs';\nimport { R as RendererError } from './eternalheart-angular-file-preview-RendererError-DtNihCIX.mjs';\n\nclass FontPreviewLine {\n constructor() {\n this.font = input(null);\n this.text = input.required();\n this.fontSize = input.required();\n this.renderMode = input.required();\n this.theme = input.required();\n this.wrapper = viewChild('wrapperRef');\n this.canvas = viewChild('canvasRef');\n this.resizeObserver = null;\n afterNextRender(() => {\n if (this.renderMode() === 'canvas') {\n this.drawCanvas();\n this.setupObserver();\n }\n });\n effect(() => {\n this.text();\n this.fontSize();\n this.renderMode();\n this.theme();\n this.font();\n if (this.renderMode() === 'canvas') {\n requestAnimationFrame(() => {\n this.drawCanvas();\n this.setupObserver();\n });\n }\n });\n inject(DestroyRef).onDestroy(() => this.teardownObserver());\n }\n teardownObserver() {\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n }\n drawCanvas() {\n const wrapper = this.wrapper()?.nativeElement;\n const canvas = this.canvas()?.nativeElement;\n const font = this.font();\n if (!wrapper || !canvas || this.renderMode() !== 'canvas' || !font)\n return;\n const containerWidth = wrapper.clientWidth || 600;\n const dpr = window.devicePixelRatio || 1;\n const fontSize = this.fontSize();\n const lineHeight = fontSize * 1.4;\n const fillColor = this.theme() === 'light' ? '#1f2937' : '#f3f4f6';\n const wrapLine = (line) => {\n if (!line)\n return [''];\n const result = [];\n let buf = '';\n for (const ch of Array.from(line)) {\n const next = buf + ch;\n const w = font.getAdvanceWidth(next, fontSize);\n if (w > containerWidth && buf) {\n result.push(buf);\n buf = ch;\n }\n else {\n buf = next;\n }\n }\n if (buf)\n result.push(buf);\n return result;\n };\n const wrappedLines = [];\n this.text().split('\\n').forEach((seg) => {\n wrapLine(seg).forEach((l) => wrappedLines.push(l));\n });\n const width = containerWidth;\n const height = lineHeight * wrappedLines.length + 4;\n canvas.width = Math.max(1, Math.floor(width * dpr));\n canvas.height = Math.max(1, Math.floor(height * dpr));\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n const ctx = canvas.getContext('2d');\n if (!ctx)\n return;\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, width, height);\n wrappedLines.forEach((line, idx) => {\n const path = font.getPath(line, 0, fontSize + idx * lineHeight, fontSize);\n path.fill = fillColor;\n path.draw(ctx);\n });\n }\n setupObserver() {\n this.teardownObserver();\n if (this.renderMode() !== 'canvas')\n return;\n if (typeof ResizeObserver === 'undefined')\n return;\n const wrapper = this.wrapper()?.nativeElement;\n if (!wrapper)\n return;\n this.resizeObserver = new ResizeObserver(() => this.drawCanvas());\n this.resizeObserver.observe(wrapper);\n }\n static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"19.2.25\", ngImport: i0, type: FontPreviewLine, deps: [], target: i0.ɵɵFactoryTarget.Component }); }\n static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: \"17.0.0\", version: \"19.2.25\", type: FontPreviewLine, isStandalone: true, selector: \"afp-font-preview-line\", inputs: { font: { classPropertyName: \"font\", publicName: \"font\", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: \"text\", publicName: \"text\", isSignal: true, isRequired: true, transformFunction: null }, fontSize: { classPropertyName: \"fontSize\", publicName: \"fontSize\", isSignal: true, isRequired: true, transformFunction: null }, renderMode: { classPropertyName: \"renderMode\", publicName: \"renderMode\", isSignal: true, isRequired: true, transformFunction: null }, theme: { classPropertyName: \"theme\", publicName: \"theme\", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: \"wrapper\", first: true, predicate: [\"wrapperRef\"], descendants: true, isSignal: true }, { propertyName: \"canvas\", first: true, predicate: [\"canvasRef\"], descendants: true, isSignal: true }], ngImport: i0, template: `\n <div #wrapperRef class=\"afp-w-full\">\n @if (renderMode() === 'canvas') {\n <canvas #canvasRef class=\"afp-block\"></canvas>\n } @else {\n <div\n class=\"afp-w-full afp-text-fg-primary afp-whitespace-pre-wrap afp-break-words\"\n [style.fontFamily]=\"'PreviewFont, sans-serif'\"\n [style.fontSize]=\"fontSize() + 'px'\"\n [style.lineHeight]=\"1.4\"\n >{{ text() }}</div>\n }\n </div>\n `, isInline: true, styles: [\":host{display:block;width:100%}\\n\"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"19.2.25\", ngImport: i0, type: FontPreviewLine, decorators: [{\n type: Component,\n args: [{ selector: 'afp-font-preview-line', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `\n <div #wrapperRef class=\"afp-w-full\">\n @if (renderMode() === 'canvas') {\n <canvas #canvasRef class=\"afp-block\"></canvas>\n } @else {\n <div\n class=\"afp-w-full afp-text-fg-primary afp-whitespace-pre-wrap afp-break-words\"\n [style.fontFamily]=\"'PreviewFont, sans-serif'\"\n [style.fontSize]=\"fontSize() + 'px'\"\n [style.lineHeight]=\"1.4\"\n >{{ text() }}</div>\n }\n </div>\n `, styles: [\":host{display:block;width:100%}\\n\"] }]\n }], ctorParameters: () => [] });\n\nconst MAGIC_WOFF2 = 0x774f4632;\nconst MAGIC_WOFF = 0x774f4646;\nconst MAGIC_OTTO = 0x4f54544f;\nconst MAGIC_TTF1 = 0x00010000;\nconst MAGIC_TRUE = 0x74727565;\nconst detectMagic = (buf) => {\n if (buf.byteLength < 4)\n return 'unknown';\n const m = new DataView(buf).getUint32(0);\n if (m === MAGIC_WOFF2)\n return 'woff2';\n if (m === MAGIC_WOFF)\n return 'woff';\n if (m === MAGIC_OTTO)\n return 'otf';\n if (m === MAGIC_TTF1 || m === MAGIC_TRUE)\n return 'ttf';\n return 'unknown';\n};\nconst DEFAULT_SAMPLES = {\n latin: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ\\nabcdefghijklmnopqrstuvwxyz\\n0123456789 .,;:!?@#$%&*()[]{}',\n chinese: '春夏秋冬东南西北天地人和风雨雷电山水日月',\n mixed: 'The Quick Brown Fox Jumps Over The Lazy Dog\\n敏捷的棕色狐狸跳过了懒狗',\n};\nconst SIZES = [72, 48, 36, 24, 18];\nclass FontRenderer {\n constructor() {\n this.url = input.required();\n this.locale = inject(LocaleService, { optional: true });\n this.request = inject(RequestService, { optional: true });\n this.theme = inject(ThemeService, { optional: true });\n this.t = this.locale?.t() ?? getFallbackTranslator();\n this.sizes = SIZES;\n this.samples = DEFAULT_SAMPLES;\n this.font = signal(null);\n this.metadata = signal(null);\n this.metadataStatus = signal('loading');\n this.loading = signal(true);\n this.error = signal(null);\n this.customText = signal('');\n this.renderMode = signal('fontface');\n this.displayText = computed(() => this.customText() || DEFAULT_SAMPLES.mixed);\n this.showMetaPlaceholder = computed(() => this.metadataStatus() !== 'ready');\n this.metaPlaceholder = computed(() => this.metadataStatus() === 'loading' ? this.t('font.metadata_loading') : this.t('font.metadata_unavailable'));\n this.effectiveRenderMode = computed(() => (this.renderMode() === 'canvas' && this.font() ? 'canvas' : 'fontface'));\n this.resolvedTheme = computed(() => this.theme?.theme() ?? 'dark');\n this.fontFace = null;\n this.getToolbarGroups = () => [];\n effect(() => {\n const url = this.url();\n if (!url)\n return;\n untracked(() => { void this.loadFont(); });\n });\n inject(DestroyRef).onDestroy(() => this.releaseFontFace());\n }\n onCustomInput(ev) {\n this.customText.set(ev.target.value);\n }\n releaseFontFace() {\n if (this.fontFace) {\n document.fonts.delete(this.fontFace);\n this.fontFace = null;\n }\n }\n detectFormat(url) {\n const ext = url.split('.').pop()?.toLowerCase().split('?')[0] || '';\n const formatMap = {\n ttf: 'TrueType (TTF)',\n otf: 'OpenType (OTF)',\n woff: 'Web Open Font Format (WOFF)',\n woff2: 'Web Open Font Format 2 (WOFF2)',\n };\n return formatMap[ext] || 'TTF';\n }\n formatLabel(magic, url) {\n const labels = {\n woff2: 'Web Open Font Format 2 (WOFF2)',\n woff: 'Web Open Font Format (WOFF)',\n otf: 'OpenType (OTF)',\n ttf: 'TrueType (TTF)',\n unknown: null,\n };\n return labels[magic] ?? this.detectFormat(url);\n }\n async loadFontFace(faceBuffer) {\n try {\n this.fontFace = new FontFace('PreviewFont', faceBuffer);\n await this.fontFace.load();\n document.fonts.add(this.fontFace);\n this.renderMode.set('fontface');\n }\n catch (faceErr) {\n console.warn('[FontRenderer] FontFace API rejected, fallback to Canvas:', faceErr);\n this.renderMode.set('canvas');\n throw faceErr;\n }\n }\n async loadMetadata(arrayBuffer, magic) {\n if (magic === 'woff2') {\n throw new Error('WOFF2 metadata parsing intentionally skipped');\n }\n const fontData = parse(arrayBuffer);\n if (!fontData) {\n throw new Error('Font data is invalid');\n }\n const rawNames = (fontData.names || {});\n const platformTables = ['windows', 'macintosh', 'unicode']\n .map((k) => rawNames[k])\n .filter((t) => !!t && typeof t === 'object');\n const pickName = (key) => {\n for (const table of platformTables) {\n const entry = table[key];\n const val = entry?.en || entry?.['zh-Hans'];\n if (val)\n return val;\n }\n const flat = rawNames[key];\n return flat?.en || flat?.['zh-Hans'] || '';\n };\n const meta = {\n family: pickName('fontFamily') || pickName('postScriptName') || 'Unknown',\n subfamily: pickName('fontSubfamily'),\n version: pickName('version'),\n designer: pickName('designer'),\n glyphCount: fontData.numGlyphs || 0,\n format: this.formatLabel(magic, this.url()),\n };\n this.font.set(fontData);\n this.metadata.set(meta);\n this.metadataStatus.set('ready');\n }\n async loadFont() {\n this.releaseFontFace();\n this.font.set(null);\n try {\n this.loading.set(true);\n this.error.set(null);\n this.metadataStatus.set('loading');\n const fetcher = this.request?.fetcher() ?? ((u, init) => fetch(u, init));\n const response = await fetcher(this.url());\n if (!response.ok) {\n throw new Error('Failed to load font file');\n }\n const arrayBuffer = await response.arrayBuffer();\n const faceBuffer = arrayBuffer.slice(0);\n const magic = detectMagic(arrayBuffer);\n const facePromise = this.loadFontFace(faceBuffer);\n const metadataPromise = this.loadMetadata(arrayBuffer, magic);\n await facePromise.catch(() => {\n // FontFace 失败由 metadata 兜底\n });\n this.loading.set(false);\n try {\n await metadataPromise;\n }\n catch (metaErr) {\n if (magic !== 'woff2') {\n console.warn('[FontRenderer] Metadata parse failed, font is still rendered via FontFace:', metaErr instanceof Error ? metaErr.message : String(metaErr));\n }\n this.metadataStatus.set('unavailable');\n this.metadata.set({\n family: 'Unknown',\n subfamily: '',\n version: '',\n designer: '',\n glyphCount: 0,\n format: this.formatLabel(magic, this.url()),\n });\n }\n }\n catch (err) {\n console.warn('[FontRenderer] Failed to load font:', err instanceof Error ? err.message : String(err));\n this.error.set(this.t('font.load_failed'));\n this.loading.set(false);\n this.metadataStatus.set('unavailable');\n }\n }\n static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"19.2.25\", ngImport: i0, type: FontRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component }); }\n static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: \"17.0.0\", version: \"19.2.25\", type: FontRenderer, isStandalone: true, selector: \"afp-font-renderer\", inputs: { url: { classPropertyName: \"url\", publicName: \"url\", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: \"afp-block afp-w-full afp-h-full\" }, ngImport: i0, template: `\n <div class=\"afp-flex afp-flex-col afp-w-full afp-h-full afp-overflow-hidden\">\n @if (loading()) {\n <div class=\"afp-flex afp-items-center afp-justify-center afp-w-full afp-h-full\">\n <div class=\"afp-text-fg-secondary\">{{ t('font.loading') }}</div>\n </div>\n } @else if (error() || !metadata()) {\n <afp-renderer-error [message]=\"error() || t('font.parse_failed')\" />\n } @else {\n <div class=\"afp-flex-shrink-0 afp-px-6 afp-py-4 afp-bg-surface-1 afp-border-b afp-border-line-weak afp-min-w-0\">\n <div class=\"afp-grid afp-grid-cols-2 afp-gap-x-6 afp-gap-y-2 afp-text-sm afp-min-w-0\">\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.family') }}:</span>\n <span class=\"afp-text-fg-primary afp-font-semibold afp-truncate\">\n {{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.family }}\n </span>\n </div>\n @if (metadata()!.subfamily) {\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.subfamily') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.subfamily }}</span>\n </div>\n }\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.format') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.format }}</span>\n </div>\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.glyphs') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">\n {{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.glyphCount }}\n </span>\n </div>\n @if (metadata()!.designer) {\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.designer') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.designer }}</span>\n </div>\n }\n @if (metadata()!.version) {\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.version') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.version }}</span>\n </div>\n }\n </div>\n </div>\n\n <div class=\"afp-flex-1 afp-overflow-auto afp-min-w-0\">\n <div class=\"afp-px-6 afp-py-6 afp-space-y-8 afp-min-w-0\">\n <div class=\"afp-min-w-0\">\n <label class=\"afp-block afp-text-xs afp-text-fg-tertiary afp-mb-2\">\n {{ t('font.sample_text_placeholder') }}\n </label>\n <textarea\n [value]=\"customText()\"\n class=\"afp-block afp-w-full afp-box-border afp-px-3 afp-py-2.5 afp-bg-surface-2 afp-text-fg-primary afp-text-sm afp-leading-relaxed afp-border afp-border-line afp-rounded-md afp-resize-y focus:afp-outline-none focus:afp-border-line-strong\"\n rows=\"2\"\n [placeholder]=\"t('font.sample_text_placeholder')\"\n [style.minHeight]=\"'64px'\"\n [style.maxHeight]=\"'160px'\"\n (input)=\"onCustomInput($event)\"\n ></textarea>\n </div>\n\n <div class=\"afp-space-y-6 afp-min-w-0\">\n @for (size of sizes; track size) {\n <div class=\"afp-space-y-2 afp-min-w-0\">\n <div class=\"afp-text-xs afp-text-fg-tertiary\">{{ size }}px</div>\n <afp-font-preview-line\n [font]=\"font()\"\n [text]=\"displayText()\"\n [fontSize]=\"size\"\n [renderMode]=\"effectiveRenderMode()\"\n [theme]=\"resolvedTheme()\"\n />\n </div>\n }\n </div>\n\n <div class=\"afp-space-y-6 afp-pt-6 afp-border-t afp-border-line-weak afp-min-w-0\">\n <div class=\"afp-min-w-0\">\n <div class=\"afp-text-sm afp-text-fg-tertiary afp-mb-3\">Latin Alphabet</div>\n <afp-font-preview-line\n [font]=\"font()\"\n [text]=\"samples.latin\"\n [fontSize]=\"24\"\n [renderMode]=\"effectiveRenderMode()\"\n [theme]=\"resolvedTheme()\"\n />\n </div>\n\n <div class=\"afp-min-w-0\">\n <div class=\"afp-text-sm afp-text-fg-tertiary afp-mb-3\">Chinese Characters</div>\n <afp-font-preview-line\n [font]=\"font()\"\n [text]=\"samples.chinese\"\n [fontSize]=\"24\"\n [renderMode]=\"effectiveRenderMode()\"\n [theme]=\"resolvedTheme()\"\n />\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n `, isInline: true, dependencies: [{ kind: \"component\", type: RendererError, selector: \"afp-renderer-error\", inputs: [\"message\", \"detail\", \"showIcon\"] }, { kind: \"component\", type: FontPreviewLine, selector: \"afp-font-preview-line\", inputs: [\"font\", \"text\", \"fontSize\", \"renderMode\", \"theme\"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"19.2.25\", ngImport: i0, type: FontRenderer, decorators: [{\n type: Component,\n args: [{\n selector: 'afp-font-renderer',\n standalone: true,\n imports: [RendererError, FontPreviewLine],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'afp-block afp-w-full afp-h-full' },\n template: `\n <div class=\"afp-flex afp-flex-col afp-w-full afp-h-full afp-overflow-hidden\">\n @if (loading()) {\n <div class=\"afp-flex afp-items-center afp-justify-center afp-w-full afp-h-full\">\n <div class=\"afp-text-fg-secondary\">{{ t('font.loading') }}</div>\n </div>\n } @else if (error() || !metadata()) {\n <afp-renderer-error [message]=\"error() || t('font.parse_failed')\" />\n } @else {\n <div class=\"afp-flex-shrink-0 afp-px-6 afp-py-4 afp-bg-surface-1 afp-border-b afp-border-line-weak afp-min-w-0\">\n <div class=\"afp-grid afp-grid-cols-2 afp-gap-x-6 afp-gap-y-2 afp-text-sm afp-min-w-0\">\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.family') }}:</span>\n <span class=\"afp-text-fg-primary afp-font-semibold afp-truncate\">\n {{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.family }}\n </span>\n </div>\n @if (metadata()!.subfamily) {\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.subfamily') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.subfamily }}</span>\n </div>\n }\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.format') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.format }}</span>\n </div>\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.glyphs') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">\n {{ showMetaPlaceholder() ? metaPlaceholder() : metadata()!.glyphCount }}\n </span>\n </div>\n @if (metadata()!.designer) {\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.designer') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.designer }}</span>\n </div>\n }\n @if (metadata()!.version) {\n <div class=\"afp-flex afp-items-center afp-gap-2 afp-min-w-0\">\n <span class=\"afp-text-fg-tertiary afp-flex-shrink-0\">{{ t('font.meta.version') }}:</span>\n <span class=\"afp-text-fg-primary afp-truncate\">{{ metadata()!.version }}</span>\n </div>\n }\n </div>\n </div>\n\n <div class=\"afp-flex-1 afp-overflow-auto afp-min-w-0\">\n <div class=\"afp-px-6 afp-py-6 afp-space-y-8 afp-min-w-0\">\n <div class=\"afp-min-w-0\">\n <label class=\"afp-block afp-text-xs afp-text-fg-tertiary afp-mb-2\">\n {{ t('font.sample_text_placeholder') }}\n </label>\n <textarea\n [value]=\"customText()\"\n class=\"afp-block afp-w-full afp-box-border afp-px-3 afp-py-2.5 afp-bg-surface-2 afp-text-fg-primary afp-text-sm afp-leading-relaxed afp-border afp-border-line afp-rounded-md afp-resize-y focus:afp-outline-none focus:afp-border-line-strong\"\n rows=\"2\"\n [placeholder]=\"t('font.sample_text_placeholder')\"\n [style.minHeight]=\"'64px'\"\n [style.maxHeight]=\"'160px'\"\n (input)=\"onCustomInput($event)\"\n ></textarea>\n </div>\n\n <div class=\"afp-space-y-6 afp-min-w-0\">\n @for (size of sizes; track size) {\n <div class=\"afp-space-y-2 afp-min-w-0\">\n <div class=\"afp-text-xs afp-text-fg-tertiary\">{{ size }}px</div>\n <afp-font-preview-line\n [font]=\"font()\"\n [text]=\"displayText()\"\n [fontSize]=\"size\"\n [renderMode]=\"effectiveRenderMode()\"\n [theme]=\"resolvedTheme()\"\n />\n </div>\n }\n </div>\n\n <div class=\"afp-space-y-6 afp-pt-6 afp-border-t afp-border-line-weak afp-min-w-0\">\n <div class=\"afp-min-w-0\">\n <div class=\"afp-text-sm afp-text-fg-tertiary afp-mb-3\">Latin Alphabet</div>\n <afp-font-preview-line\n [font]=\"font()\"\n [text]=\"samples.latin\"\n [fontSize]=\"24\"\n [renderMode]=\"effectiveRenderMode()\"\n [theme]=\"resolvedTheme()\"\n />\n </div>\n\n <div class=\"afp-min-w-0\">\n <div class=\"afp-text-sm afp-text-fg-tertiary afp-mb-3\">Chinese Characters</div>\n <afp-font-preview-line\n [font]=\"font()\"\n [text]=\"samples.chinese\"\n [fontSize]=\"24\"\n [renderMode]=\"effectiveRenderMode()\"\n [theme]=\"resolvedTheme()\"\n />\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n `,\n }]\n }], ctorParameters: () => [] });\n\nexport { FontRenderer };\n//# sourceMappingURL=eternalheart-angular-file-preview-index-C518mdUd.mjs.map\n"],"names":[],"mappings":"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"}
|