@mlightcad/mtext-renderer 0.10.16 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { FontInfo, FontLoader, FontLoadStatus } from './fontLoader';
2
2
  /**
3
3
  * Default implementation of the FontLoader interface.
4
- * This class provides font loading functionality using [this font repository](https://mlightcad.gitlab.io/cad-data/fonts/).
4
+ * This class provides font loading functionality using [this font repository](https://cdn.jsdelivr.net/gh/mlightcad/cad-data/fonts/).
5
5
  * It loads font metadata from a JSON file and provides access to available fonts.
6
6
  */
7
7
  export declare class DefaultFontLoader implements FontLoader {
@@ -42,7 +42,7 @@ export declare class DefaultFontLoader implements FontLoader {
42
42
  * @param fontNames - Array of font names to load
43
43
  * @returns Promise that resolves to an array of FontLoadStatus objects
44
44
  */
45
- load(fontNames: string[]): Promise<FontLoadStatus[]>;
45
+ load(fontNames: readonly string[]): Promise<FontLoadStatus[]>;
46
46
  /**
47
47
  * Build one font map. The key is font name. The value is font info.
48
48
  */
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Preset names for common AutoCAD-era default font fallback chains.
3
+ *
4
+ * Third-party DWG viewers often mirror fonts that were widely bundled or
5
+ * referenced during the AutoCAD R12/R14 era, then simplified in later releases.
6
+ */
7
+ export type DefaultFontsPreset =
8
+ /** SHX symbol fonts plus mesh CJK fallback (library default). */
9
+ 'minimal'
10
+ /** Classic R12/R14 stack: SHX basics, GB big font, then mesh CJK and AMGDT. */
11
+ | 'r12r14'
12
+ /** Later-era stack: hztxt big font with simsun and AMGDT symbols. */
13
+ | 'modern'
14
+ /** Western SHX fonts plus simsun and AMGDT; no CJK-specific SHX big fonts. */
15
+ | 'international'
16
+ /** Broad CJK coverage: both GB big-font SHX files plus common mesh fallbacks. */
17
+ | 'cjk';
18
+ /**
19
+ * Predefined text-font fallback chains (primary / big-font substitutes and CJK
20
+ * mesh fallbacks). Symbol fonts such as `amgdt` are configured separately via
21
+ * {@link SYMBOL_FONTS_PRESETS}.
22
+ */
23
+ export declare const DEFAULT_FONTS_PRESETS: Record<DefaultFontsPreset, readonly string[]>;
24
+ /**
25
+ * GDT / SHX symbol-font chains used for AutoCAD control codes (`%%c`, `%%d`,
26
+ * `%%p`, `%%130`, etc.). Earlier entries are tried first.
27
+ */
28
+ export declare const SYMBOL_FONTS_PRESETS: Record<DefaultFontsPreset, readonly string[]>;
29
+ export declare function isDefaultFontsPreset(value: string): value is DefaultFontsPreset;
@@ -44,7 +44,7 @@ export interface FontLoader {
44
44
  * @param fontNames - Array of font names to load
45
45
  * @returns Promise that resolves to an array of FontLoadStatus objects indicating the load status of each font
46
46
  */
47
- load(fontNames: string[]): Promise<FontLoadStatus[]>;
47
+ load(fontNames: readonly string[]): Promise<FontLoadStatus[]>;
48
48
  /**
49
49
  * Retrieves information about all available fonts in the system
50
50
  * @returns Promise that resolves to an array of FontInfo objects containing details about available fonts
@@ -1,6 +1,7 @@
1
1
  import { EventManager } from '../common';
2
2
  import { BaseFont } from './baseFont';
3
3
  import { BaseTextShape } from './baseTextShape';
4
+ import { DefaultFontsPreset } from './defaultFontsPresets';
4
5
  import { FontType } from './font';
5
6
  import { FontInfo, FontLoader, FontLoadStatus } from './fontLoader';
6
7
  /**
@@ -45,8 +46,17 @@ export declare class FontManager {
45
46
  missedFonts: Record<string, number>;
46
47
  /** Flag to enable/disable font caching */
47
48
  enableFontCache: boolean;
48
- /** Default font to use when a requested font is not found */
49
- defaultFont: string;
49
+ /**
50
+ * Default fonts to use when a requested font is not found or lacks a glyph.
51
+ * Insertion order is preserved; earlier entries are tried first.
52
+ */
53
+ defaultFonts: Set<string>;
54
+ /**
55
+ * GDT / SHX symbol fonts for AutoCAD control-code glyphs (`%%c`, `%%d`, `%%p`,
56
+ * `%%nnn`, etc.). Separate from {@link defaultFonts} so text fallbacks are not
57
+ * polluted by symbol-font code-point matches.
58
+ */
59
+ symbolFonts: Set<string>;
50
60
  /** Event managers for font-related events */
51
61
  readonly events: {
52
62
  /** Event triggered when a font cannot be found */
@@ -70,6 +80,47 @@ export declare class FontManager {
70
80
  * @param mapping - The font mapping to set
71
81
  */
72
82
  setFontMapping(mapping: FontMapping): void;
83
+ /**
84
+ * Sets the default font fallback chain.
85
+ *
86
+ * Pass a {@link DefaultFontsPreset} name to apply a predefined AutoCAD-era
87
+ * fallback stack, or pass one or more font names to define a custom chain.
88
+ * Earlier entries are tried first when a glyph is missing.
89
+ *
90
+ * @param fonts - A preset name, a single font name, or an ordered list of font names
91
+ * @example
92
+ * ```ts
93
+ * FontManager.instance.setDefaultFonts('r12r14')
94
+ * FontManager.instance.setDefaultFonts(['hztxt', 'simsun', 'gdt'])
95
+ * FontManager.instance.setDefaultFonts('simkai')
96
+ * ```
97
+ */
98
+ setDefaultFonts(fonts: DefaultFontsPreset): void;
99
+ setDefaultFonts(fonts: string | readonly string[]): void;
100
+ /**
101
+ * Sets the symbol-font fallback chain for AutoCAD control-code glyphs.
102
+ *
103
+ * Pass a {@link DefaultFontsPreset} name to apply a predefined symbol stack,
104
+ * or pass one or more font names to define a custom chain.
105
+ *
106
+ * @param fonts - A preset name, a single font name, or an ordered list of font names
107
+ */
108
+ setSymbolFonts(fonts: DefaultFontsPreset): void;
109
+ setSymbolFonts(fonts: string | readonly string[]): void;
110
+ /**
111
+ * Returns the font names for a predefined default-font preset.
112
+ * @param preset - The preset to look up
113
+ */
114
+ getDefaultFontsPreset(preset: DefaultFontsPreset): readonly string[];
115
+ /**
116
+ * Returns the symbol-font names for a predefined preset.
117
+ * @param preset - The preset to look up
118
+ */
119
+ getSymbolFontsPreset(preset: DefaultFontsPreset): readonly string[];
120
+ /**
121
+ * Font names that should be loaded for the active default and symbol chains.
122
+ */
123
+ getFontsToLoad(): readonly string[];
73
124
  /**
74
125
  * Sets the font loader
75
126
  * @param fontLoader - The font loader to set
@@ -83,12 +134,12 @@ export declare class FontManager {
83
134
  */
84
135
  getAvailableFonts(): Promise<FontInfo[]>;
85
136
  /**
86
- * Return true if the default font was loaded.
87
- * @returns True if the default font was loaded. False otherwise.
137
+ * Return true if all default fonts were loaded.
138
+ * @returns True if every font in `defaultFonts` is loaded. False otherwise.
88
139
  */
89
140
  isDefaultFontLoaded(): boolean;
90
141
  /**
91
- * Loads the default font
142
+ * Loads all default and symbol fonts
92
143
  * @returns Promise that resolves to the font load statuses
93
144
  */
94
145
  loadDefaultFont(): Promise<FontLoadStatus[]>;
@@ -97,7 +148,7 @@ export declare class FontManager {
97
148
  * @param names - Font names to load.
98
149
  * @returns Promise that resolves to an array of font load statuses
99
150
  */
100
- loadFontsByNames(names: string | string[]): Promise<FontLoadStatus[]>;
151
+ loadFontsByNames(names: string | readonly string[]): Promise<FontLoadStatus[]>;
101
152
  /**
102
153
  * Loads the specified fonts from URLs
103
154
  * @param urls - URLs of font files to load.
@@ -125,13 +176,24 @@ export declare class FontManager {
125
176
  */
126
177
  getFontByChar(char: string): BaseFont | undefined;
127
178
  /**
128
- * Gets the text shape for a specific character with the specified font and size
179
+ * Gets the text shape for a specific character in the named font only.
180
+ * Does not fall back to bigFont, default fonts, or other loaded fonts.
129
181
  * @param char - The character to get the shape for
130
182
  * @param fontName - The name of the font to use
131
183
  * @param size - The size of the character
132
184
  * @returns The text shape for the character, or undefined if not found
133
185
  */
134
186
  getCharShape(char: string, fontName: string, size: number): BaseTextShape | undefined;
187
+ /**
188
+ * Gets the text shape from the first loaded default font that contains the character.
189
+ * Used after primary and optional bigFont lookups per AutoCAD text-style semantics.
190
+ */
191
+ getCharShapeFromDefaults(char: string, size: number): BaseTextShape | undefined;
192
+ /**
193
+ * Gets the text shape from configured GDT / symbol fonts (e.g. `amgdt.shx`).
194
+ * Used for AutoCAD percent codes and other symbol-font code points.
195
+ */
196
+ getCharShapeFromSymbolFonts(char: string, size: number): BaseTextShape | undefined;
135
197
  /**
136
198
  * Gets the scale factor for a specific font
137
199
  * @param fontName - The name of the font
@@ -171,6 +233,10 @@ export declare class FontManager {
171
233
  * Loads all fonts from the cache
172
234
  */
173
235
  getAllFontsFromCache(): Promise<void>;
236
+ /**
237
+ * Registers a loaded font under its primary name and all aliases.
238
+ */
239
+ private registerFontInMap;
174
240
  /**
175
241
  * Gets a record of all unsupported characters across all loaded fonts
176
242
  * @returns A record mapping unsupported characters to their occurrence count
@@ -1,6 +1,7 @@
1
1
  export * from './baseFont';
2
2
  export * from './baseTextShape';
3
3
  export * from './defaultFontLoader';
4
+ export * from './defaultFontsPresets';
4
5
  export * from './font';
5
6
  export * from './fontFactory';
6
7
  export * from './fontLoader';
@@ -82,6 +82,15 @@ export declare class MeshFont extends BaseFont {
82
82
  * @returns An object containing the opentype font and parsed metadata
83
83
  */
84
84
  private parseMeshFont;
85
+ /**
86
+ * Whether opentype maps the character to a real glyph (not .notdef at index 0).
87
+ *
88
+ * opentype.js ≤1.3.4: {@link OpenTypeFont.hasChar} used `charToGlyphIndex(c) !== null`,
89
+ * but CmapEncoding returns 0 for missing code points — see
90
+ * https://github.com/opentypejs/opentype.js/issues/330 (fixed in 2.0.0).
91
+ * We keep `index > 0` here so hasChar stays aligned with {@link _loadGlyphIfNeeded}.
92
+ */
93
+ private opentypeHasGlyph;
85
94
  /**
86
95
  * Return true if this font contains glyph of the specified character. Otherwise, return false.
87
96
  * @param char - The character to check
@@ -55,6 +55,8 @@ export declare class ShxFont extends BaseFont {
55
55
  * @returns The shape data for the character code, or undefined if not found
56
56
  */
57
57
  getCodeShape(code: number, size: number): ShxTextShape | undefined;
58
+ /** True when the SHX glyph has drawable strokes or a non-zero pen advance. */
59
+ private static hasRenderableStrokes;
58
60
  /**
59
61
  * For an unsupported char, use "?" as a replacement.
60
62
  */
@@ -305,6 +305,7 @@ export declare class MTextProcessor {
305
305
  * @param char Input one character
306
306
  * @returns Return the text shape of the specified character
307
307
  */
308
+ private shapeHasStrokeGeometry;
308
309
  private getCharShape;
309
310
  private advanceToNextLine;
310
311
  private captureCurrentLineAdvance;
@@ -323,6 +324,12 @@ export declare class MTextProcessor {
323
324
  * a rough fallback when the font has no space definition.
324
325
  */
325
326
  private calculateBlankWidthForFont;
327
+ /**
328
+ * Merges line-based geometries for LineSegments. SHX glyphs use indexed
329
+ * BufferGeometry while fraction/divider decorations omit an index; normalize
330
+ * to non-indexed form so mergeGeometries accepts the batch.
331
+ */
332
+ private mergeLineGeometries;
326
333
  /**
327
334
  * Convert the text shape geometries to three.js object
328
335
  * @param geometries Input text shape geometries
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Expands AutoCAD `%%` stroke control codes into `\K`/`\k`, `\O`/`\o`, and `\L`/`\l`
3
+ * inline formatting commands understood by {@link @mlightcad/mtext-parser}.
4
+ */
5
+ export declare function expandPercentControlCodes(text: string): string;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * AutoCAD percent-sign symbol codes (`%%c`, `%%d`, `%%p`) and their SHX
3
+ * symbol-font code points.
4
+ *
5
+ * Named percent codes are expanded by {@link @mlightcad/mtext-parser} into Unicode
6
+ * before rendering. AutoCAD itself does not rely on those Unicode code points in
7
+ * the primary text font; it resolves the symbols through GDT / symbol SHX fonts
8
+ * such as `amgdt.shx` using legacy control-code code points.
9
+ *
10
+ * References:
11
+ * - AutoCAD "Text Symbols and Special Characters"
12
+ * - AutoCAD "Control Codes and Special Characters" (`%%nnn`)
13
+ * - Legacy SHX convention: 127 = degree, 128 = plus/minus, 129 = diameter
14
+ * - Modern `amgdt.shx`: degree at 126/176, ± at 177, diameter at U+2205 (∅);
15
+ * code 130 = angle (∠). Legacy bytes 127–128 must not be used when CJK mesh
16
+ * fonts in the fallback chain expose unrelated glyphs at those code points.
17
+ */
18
+ export type AutoCadPercentSymbolCode = 'c' | 'd' | 'p';
19
+ /**
20
+ * Ordered SHX byte-code candidates for each named AutoCAD percent symbol.
21
+ * Earlier entries are preferred when present in the symbol-font fallback chain
22
+ * Earlier entries are preferred when present in {@link FontManager.symbolFonts}.
23
+ */
24
+ export declare const AUTOCAD_PERCENT_SYMBOL_CONTROL_CODES: Readonly<Record<AutoCadPercentSymbolCode, readonly number[]>>;
25
+ /**
26
+ * Returns whether a character originated from an AutoCAD named percent symbol.
27
+ */
28
+ export declare function isAutoCadPercentSymbolChar(char: string): boolean;
29
+ /**
30
+ * Returns whether a character likely came from an AutoCAD numeric percent code
31
+ * (`%%ddd`) expanded by mtext-parser into {@link String.fromCharCode}.
32
+ *
33
+ * AutoCAD resolves these byte-oriented SHX code points from GDT / symbol fonts
34
+ * (e.g. `amgdt.shx`), not from the primary text font—even when the text font
35
+ * defines a glyph at the same code (as with `txt.shx` at code 132).
36
+ */
37
+ export declare function isAutoCadNumericPercentControlCodeChar(char: string): boolean;
38
+ /**
39
+ * Returns ordered SHX control-code characters to try in symbol-font fallbacks
40
+ * for an AutoCAD percent-symbol Unicode expansion.
41
+ */
42
+ export declare function getShxControlCodeCandidates(char: string): readonly string[];
43
+ /**
44
+ * @deprecated Use {@link getShxControlCodeCandidates} instead.
45
+ */
46
+ export declare function getShxControlCodeChar(char: string): string | undefined;
@@ -63,7 +63,7 @@ export interface MTextBaseRenderer {
63
63
  * @param fonts Font names to load (without extension for built-ins).
64
64
  * @returns A Promise with the list of fonts that were processed.
65
65
  */
66
- loadFonts(fonts: string[]): Promise<{
66
+ loadFonts(fonts: readonly string[]): Promise<{
67
67
  loaded: string[];
68
68
  }>;
69
69
  /**
@@ -33,7 +33,7 @@ export declare class MainThreadRenderer implements MTextBaseRenderer {
33
33
  /**
34
34
  * Load fonts in the main thread
35
35
  */
36
- loadFonts(fonts: string[]): Promise<{
36
+ loadFonts(fonts: readonly string[]): Promise<{
37
37
  loaded: string[];
38
38
  }>;
39
39
  /**
@@ -1,3 +1,4 @@
1
+ import { DefaultFontsPreset } from '../font';
1
2
  import { StyleManager } from '../renderer';
2
3
  import { ColorSettings, MTextData, TextStyle } from '../renderer/types';
3
4
  import { MTextObject } from './baseRenderer';
@@ -56,10 +57,22 @@ export declare class UnifiedRenderer {
56
57
  * @param colorSettings - Optional color context (ByLayer, ByBlock colors).
57
58
  */
58
59
  syncRenderMText(mtextContent: MTextData, textStyle: TextStyle, colorSettings?: ColorSettings): MTextObject;
60
+ /**
61
+ * Sets the default font fallback chain on the active renderer and workers.
62
+ */
63
+ setDefaultFonts(fonts: DefaultFontsPreset | string | readonly string[]): Promise<void>;
64
+ /**
65
+ * Returns font names for a predefined default-font preset.
66
+ */
67
+ getDefaultFontsPreset(preset: DefaultFontsPreset): readonly string[];
68
+ /**
69
+ * Returns symbol-font names for a predefined preset.
70
+ */
71
+ getSymbolFontsPreset(preset: DefaultFontsPreset): readonly string[];
59
72
  /**
60
73
  * Load fonts using the current mode
61
74
  */
62
- loadFonts(fonts: string[]): Promise<{
75
+ loadFonts(fonts: readonly string[]): Promise<{
63
76
  loaded: string[];
64
77
  }>;
65
78
  /**
@@ -158,6 +158,10 @@ export declare class WebWorkerRenderer implements MTextBaseRenderer {
158
158
  * @param value - URL to load fonts
159
159
  */
160
160
  setFontUrl(value: string): Promise<void>;
161
+ /**
162
+ * Syncs the default font fallback chain to all workers.
163
+ */
164
+ setDefaultFonts(fonts: readonly string[], symbolFonts: readonly string[]): Promise<void>;
161
165
  /**
162
166
  * Render MText in one worker and return serialized data asynchronously.
163
167
  */
@@ -167,7 +171,7 @@ export declare class WebWorkerRenderer implements MTextBaseRenderer {
167
171
  * Notes: It isn't supported yet.
168
172
  */
169
173
  syncRenderMText(_mtextContent: MTextData, _textStyle: TextStyle, _colorSettings?: ColorSettings): MTextObject;
170
- loadFonts(fonts: string[]): Promise<{
174
+ loadFonts(fonts: readonly string[]): Promise<{
171
175
  loaded: string[];
172
176
  }>;
173
177
  getAvailableFonts(): Promise<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mlightcad/mtext-renderer",
3
- "version": "0.10.16",
3
+ "version": "0.11.0",
4
4
  "description": "AutoCAD MText renderer based on Three.js",
5
5
  "license": "MIT",
6
6
  "author": "MLight Lee <mlight.lee@outlook.com>",
@@ -34,13 +34,13 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "@mlightcad/mtext-parser": "^1.4.1",
37
- "@mlightcad/shx-parser": "^1.3.2",
37
+ "@mlightcad/shx-parser": "^1.3.4",
38
38
  "iconv-lite": "^0.7.0",
39
39
  "idb": "^8.0.3",
40
- "opentype.js": "^1.3.4"
40
+ "opentype.js": "^2.0.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@types/opentype.js": "^1.3.8",
43
+ "@types/opentype.js": "^1.3.10",
44
44
  "@types/three": "^0.172.0",
45
45
  "vitest": "^3.2.4"
46
46
  },