@mlightcad/mtext-renderer 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,241 @@
1
+ # MText Renderer for Three.js
2
+
3
+ A flexible and extensible AutoCAD MText renderer implementation using Three.js. This package provides a modular architecture to render AutoCAD MText content with different rendering engines, with a primary focus on Three.js rendering.
4
+
5
+ ## Features
6
+
7
+ - Render AutoCAD MText content using Three.js
8
+ - Modular font loading system
9
+ - Font management and dynamic font loading
10
+ - Cache parsed fonts to improve rendering performance
11
+
12
+ ## Core Components
13
+
14
+ ### FontManager
15
+
16
+ The central manager for font operations. It's a singleton class that handles font loading, caching, and text rendering.
17
+
18
+ **Public Properties:**
19
+ - `unsupportedChars`: Record of characters not supported by any loaded font
20
+ - `missedFonts`: Record of fonts that were requested but not found
21
+ - `enableFontCache`: Flag to enable/disable font caching. If it is true, parsed fonts
22
+ will be stored in local IndexedDB to improve performance. Default value is true.
23
+ - `defaultFont`: Default font to use when a requested font is not found
24
+ - `events`: Event managers for font-related events
25
+ - `fontNotFound`: Triggered when a font cannot be found
26
+ - `fontLoaded`: Triggered when a font is successfully loaded
27
+
28
+ **Public Methods:**
29
+ - `loadFonts(urls)`: Loads fonts from URLs
30
+ - `getCharShape(char, fontName, size)`: Gets text shape for a character
31
+ - `getFontScaleFactor(fontName)`: Gets scale factor for a font
32
+ - `getNotFoundTextShape(size)`: Gets shape for not found indicator
33
+ - `getUnsupportedChar()`: Gets record of unsupported characters
34
+ - `release()`: Releases all loaded fonts
35
+
36
+ ### FontLoader & DefaultFontLoader
37
+
38
+ Interface for font loading operations. The default implementation [DefaultFontLoader](./src/font/defaultFontLoader.ts) uses a [CDN-based font repository](https://cdn.jsdelivr.net/gh/mlight-lee/cad-data/fonts/). It loads font metadata from a JSON file and provides access to available fonts. You can implement one font loader by your own if you want to use fonts hosted in your own server.
39
+
40
+ **Public Methods:**
41
+ - `load(fontNames)`: Loads specified fonts into the system
42
+ - `getAvaiableFonts()`: Retrieves information about available fonts
43
+
44
+ ### BaseFont
45
+
46
+ Abstract base class for font implementations. Provides common functionality for font handling.
47
+
48
+ **Public Properties:**
49
+ - `type`: Type of font ('shx' or 'mesh')
50
+ - `data`: Parsed font data
51
+ - `unsupportedChars`: Record of unsupported characters
52
+
53
+ **Public Methods:**
54
+ - `getCharShape(char, size)`: Gets shape for a character
55
+ - `getScaleFactor()`: Gets font scale factor
56
+ - `getNotFoundTextShape(size)`: Gets shape for not found indicator
57
+
58
+ ### BaseTextShape
59
+
60
+ Abstract base class for text shape implementations. Provides common functionality for text shape handling.
61
+
62
+ **Public Properties:**
63
+ - `char`: Character this shape represents
64
+ - `size`: Size of the text shape
65
+
66
+ **Public Methods:**
67
+ - `getWidth()`: Gets width of text shape
68
+ - `getHeight()`: Gets height of text shape
69
+ - `toGeometry()`: Converts shape to THREE.BufferGeometry
70
+
71
+ ### FontFactory
72
+
73
+ Singleton factory class for creating font instances. Handles creation of appropriate font objects based on type and data format.
74
+
75
+ **Public Methods:**
76
+ - `createFont(data)`: Creates font from font data
77
+ - `createFontFromBuffer(fileName, buffer)`: Creates font from file data
78
+
79
+ ### FontCacheManager
80
+ Manages font data caching using IndexedDB. Provides persistent storage for font data.
81
+
82
+ **Public Methods:**
83
+ - `get(fileName)`: Retrieves font data from cache
84
+ - `set(fileName, fontData)`: Stores font data in cache
85
+ - `getAll()`: Retrieves all cached font data
86
+ - `clear()`: Clears all cached font data
87
+
88
+ ### MText
89
+ Main class for rendering AutoCAD MText content. Extends THREE.Object3D to integrate with Three.js scene graph.
90
+
91
+ **Public Properties:**
92
+ - `content`: MText content configuration including text, height, width, and position
93
+ - `style`: Text style configuration including font, color, and text generation flags
94
+ - `fontManager`: Reference to FontManager instance for font operations
95
+ - `styleManager`: Reference to StyleManager instance for style operations
96
+
97
+ **Public Methods:**
98
+ - `update()`: Updates the text rendering based on current content and style
99
+ - `setContent(content)`: Updates the text content
100
+ - `setStyle(style)`: Updates the text style
101
+ - `dispose()`: Cleans up resources when the MText instance is no longer needed
102
+
103
+ ## Class Diagram
104
+
105
+ ```mermaid
106
+ classDiagram
107
+ class MText {
108
+ +content: MTextContent
109
+ +style: MTextStyle
110
+ +fontManager: FontManager
111
+ +styleManager: StyleManager
112
+ +update()
113
+ +setContent(content)
114
+ +setStyle(style)
115
+ +dispose()
116
+ }
117
+
118
+ class FontManager {
119
+ -_instance: FontManager
120
+ +unsupportedChars: Record
121
+ +missedFonts: Record
122
+ +enableFontCache: boolean
123
+ +defaultFont: string
124
+ +events: EventManagers
125
+ +loadFonts(urls)
126
+ +getCharShape(char, fontName, size)
127
+ +getFontScaleFactor(fontName)
128
+ +getNotFoundTextShape(size)
129
+ +getUnsupportedChar()
130
+ +release()
131
+ }
132
+
133
+ class FontLoader {
134
+ <<interface>>
135
+ +load(fontNames)
136
+ +getAvaiableFonts()
137
+ }
138
+
139
+ class DefaultFontLoader {
140
+ -_avaiableFonts: FontInfo[]
141
+ +load(fontNames)
142
+ +getAvaiableFonts()
143
+ }
144
+
145
+ class BaseFont {
146
+ <<abstract>>
147
+ +type: FontType
148
+ +data: unknown
149
+ +unsupportedChars: Record
150
+ +getCharShape(char, size)
151
+ +getScaleFactor()
152
+ +getNotFoundTextShape(size)
153
+ }
154
+
155
+ class BaseTextShape {
156
+ <<abstract>>
157
+ +char: string
158
+ +size: number
159
+ +getWidth()
160
+ +getHeight()
161
+ +toGeometry()
162
+ }
163
+
164
+ class FontFactory {
165
+ -_instance: FontFactory
166
+ +createFont(data)
167
+ +createFontFromBuffer(fileName, buffer)
168
+ }
169
+
170
+ class FontCacheManager {
171
+ -_instance: FontCacheManager
172
+ +get(fileName)
173
+ +set(fileName, fontData)
174
+ +getAll()
175
+ +clear()
176
+ }
177
+
178
+ MText --> FontManager
179
+ MText --> StyleManager
180
+ FontManager --> FontFactory
181
+ FontManager --> FontCacheManager
182
+ FontManager --> BaseFont
183
+ DefaultFontLoader ..|> FontLoader
184
+ BaseFont <|-- MeshFont
185
+ BaseFont <|-- ShxFont
186
+ BaseTextShape <|-- MeshTextShape
187
+ BaseTextShape <|-- ShxTextShape
188
+ ```
189
+
190
+ ## Usage
191
+
192
+ ```typescript
193
+ import * as THREE from 'three';
194
+ import { DefaultFontLoader, FontManager, MText, StyleManager } from '@mlightcad/mtext-renderer';
195
+
196
+ // Initialize core components
197
+ const fontManager = FontManager.instance;
198
+ const styleManager = new StyleManager();
199
+ const fontLoader = new DefaultFontLoader();
200
+
201
+ // Load fonts needed
202
+ await fontLoader.load(['simsun']);
203
+
204
+ // Create MText content
205
+ const mtextContent = {
206
+ text: '{\\fArial|b0|i0|c0|p34;Hello World}',
207
+ height: 0.1,
208
+ width: 0,
209
+ position: new THREE.Vector3(0, 0, 0)
210
+ };
211
+
212
+ // Create MText instance with style
213
+ const mtext = new MText(
214
+ mtextContent,
215
+ {
216
+ name: 'Standard',
217
+ standardFlag: 0,
218
+ fixedTextHeight: 0.1,
219
+ widthFactor: 1,
220
+ obliqueAngle: 0,
221
+ textGenerationFlag: 0,
222
+ lastHeight: 0.1,
223
+ font: 'Standard',
224
+ bigFont: '',
225
+ color: 0xffffff
226
+ },
227
+ styleManager,
228
+ fontManager
229
+ );
230
+
231
+ // Add to Three.js scene
232
+ scene.add(mtext);
233
+ ```
234
+
235
+ ## License
236
+
237
+ MIT
238
+
239
+ ## Contributing
240
+
241
+ Contributions are welcome! Please read our contributing guidelines for details.
@@ -0,0 +1,72 @@
1
+ import { FontData } from '../font';
2
+
3
+ /**
4
+ * A simple font cache interface that provides map-like operations for font data
5
+ */
6
+ export declare class FontCacheManager {
7
+ private static readonly DATABASE_NAME;
8
+ private static readonly DATABASE_VERSION;
9
+ private static _instance;
10
+ private db;
11
+ private isClosing;
12
+ private constructor();
13
+ /**
14
+ * Returns the singleton instance of the FontCacheManager
15
+ */
16
+ static get instance(): FontCacheManager;
17
+ /**
18
+ * Sets a font in the cache
19
+ * @param fileName The font file name (key)
20
+ * @param fontData The font data to store
21
+ */
22
+ set(fileName: string, fontData: FontData): Promise<void>;
23
+ /**
24
+ * Gets a font from the cache
25
+ * @param fileName The font file name (key)
26
+ * @returns The font data if found, undefined otherwise
27
+ */
28
+ get(fileName: string): Promise<FontData | undefined>;
29
+ /**
30
+ * Deletes a font from the cache
31
+ * @param fileName The font file name (key)
32
+ */
33
+ delete(fileName: string): Promise<void>;
34
+ /**
35
+ * Gets all fonts from the cache
36
+ * @returns An array of all font data in the cache
37
+ */
38
+ getAll(): Promise<FontData[]>;
39
+ /**
40
+ * Clears all fonts from the cache
41
+ */
42
+ clear(): Promise<void>;
43
+ /**
44
+ * Checks if a font exists in the cache
45
+ * @param fileName The font file name (key)
46
+ */
47
+ has(fileName: string): Promise<boolean>;
48
+ /**
49
+ * Closes the database connection and cleans up resources.
50
+ * After calling this, any further operations will require reopening the database.
51
+ */
52
+ close(): void;
53
+ /**
54
+ * Destroys the database instance and deletes all data.
55
+ * Use with caution as this operation cannot be undone.
56
+ */
57
+ destroy(): Promise<void>;
58
+ private getDatabase;
59
+ /**
60
+ * Applies all schema versions that are greater than the old version and less than or equal to the new version
61
+ * @param db The database instance
62
+ * @param oldVersion The old version of the database
63
+ * @param newVersion The new version of the database
64
+ */
65
+ private handleUpgrade;
66
+ /**
67
+ * Applies a single schema version's changes to the database
68
+ * @param db The database instance
69
+ * @param schema The schema version to apply
70
+ */
71
+ private applySchemaVersion;
72
+ }
@@ -0,0 +1 @@
1
+ export * from './fontCacheManager';
@@ -0,0 +1,28 @@
1
+ import { DBSchema } from 'idb';
2
+ import { FontData } from '../font/font';
3
+
4
+ /**
5
+ * Store name constant
6
+ */
7
+ export declare const DB_STORES: {
8
+ readonly fonts: "fonts";
9
+ };
10
+ /**
11
+ * Database schema interface for the font cache
12
+ */
13
+ export interface DbFontCacheSchema extends DBSchema {
14
+ [DB_STORES.fonts]: {
15
+ key: string;
16
+ value: FontData;
17
+ };
18
+ }
19
+ /**
20
+ * Database schema versions
21
+ */
22
+ export declare const dbSchema: {
23
+ version: number;
24
+ stores: {
25
+ name: "fonts";
26
+ keyPath: string;
27
+ }[];
28
+ }[];
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The class representing one event manager
3
+ */
4
+ export declare class EventManager<T = unknown> {
5
+ private listeners;
6
+ /**
7
+ * Add the event listener
8
+ * @param listener Input listener to be added
9
+ */
10
+ addEventListener(listener: (payload: T) => void): void;
11
+ /**
12
+ * Remove the listener
13
+ * @param listener Input listener to be removed
14
+ */
15
+ removeEventListener(listener: (payload: T) => void): void;
16
+ /**
17
+ * Remove all listeners bound to the target and add one new listener
18
+ * @param listener Input listener to be added
19
+ */
20
+ replaceEventListener(listener: (payload: T) => void): void;
21
+ /**
22
+ * Notify all listeners
23
+ * @param payload Input payload passed to listener
24
+ */
25
+ dispatch(payload?: T, ...args: unknown[]): void;
26
+ }
@@ -0,0 +1,2 @@
1
+ export * from './eventManager';
2
+ export * from './utils';
@@ -0,0 +1,11 @@
1
+ export declare const getExtension: (url: string) => string;
2
+ export declare const getFileName: (url: string) => string | undefined;
3
+ export declare const getFileNameWithoutExtension: (url: string) => string;
4
+ /**
5
+ * AutoCAD files sometimes use an indexed color value between 1 and 255 inclusive.
6
+ * Each value corresponds to a color. index 1 is red, that is 16711680 or 0xFF0000.
7
+ * index 0 and 256, while included in this array, are actually reserved for inheritance
8
+ * values in AutoCAD so they should not be used for index color lookups.
9
+ */
10
+ export declare const AUTOCAD_COLOR_INDEX: number[];
11
+ export declare const getColorByIndex: (index: number) => number;
@@ -0,0 +1,48 @@
1
+ import { BaseTextShape } from './baseTextShape';
2
+ import { FontType } from './font';
3
+
4
+ /**
5
+ * Abstract base class for font implementations.
6
+ * Provides common functionality and interface for font handling.
7
+ * This class defines the core interface that all font types must implement.
8
+ */
9
+ export declare abstract class BaseFont {
10
+ /** The type of font (shx or mesh) */
11
+ abstract readonly type: FontType;
12
+ /**
13
+ * The parsed font data. Different types of fonts have different data structures.
14
+ * This data is used to render characters and calculate metrics.
15
+ */
16
+ abstract readonly data: unknown;
17
+ /**
18
+ * Record of characters that are not supported by this font.
19
+ * Maps character strings to their occurrence count.
20
+ * Used for tracking and reporting unsupported characters.
21
+ */
22
+ unsupportedChars: Record<string, number>;
23
+ /**
24
+ * Gets the shape data for a specific character at a given size.
25
+ * @param char - The character to get the shape for
26
+ * @param size - The desired size of the character
27
+ * @returns The shape data for the character, or undefined if not found
28
+ */
29
+ abstract getCharShape(char: string, size: number): BaseTextShape | undefined;
30
+ /**
31
+ * Gets the scale factor for this font.
32
+ * This is used to adjust the size of characters when rendering.
33
+ * @returns The scale factor as a number
34
+ */
35
+ abstract getScaleFactor(): number;
36
+ /**
37
+ * Gets the shape to display when a character is not found in the font.
38
+ * @param size - The desired size of the not found shape
39
+ * @returns The shape data for the not found indicator, or undefined if not available
40
+ */
41
+ abstract getNotFoundTextShape(size: number): BaseTextShape | undefined;
42
+ /**
43
+ * Records an unsupported character in the font.
44
+ * Increments the count for the given character in unsupportedChars.
45
+ * @param char - The unsupported character to record
46
+ */
47
+ protected addUnsupportedChar(char: string): void;
48
+ }
@@ -0,0 +1,23 @@
1
+ import * as THREE from 'three';
2
+ /**
3
+ * Abstract base class for text shape implementations.
4
+ * Provides common functionality and interface for text shape handling.
5
+ * This class defines the core interface that all text shape types must implement.
6
+ */
7
+ export declare abstract class BaseTextShape extends THREE.Shape {
8
+ /** The character this shape represents */
9
+ readonly char: string;
10
+ /**
11
+ * Width used to render this character
12
+ */
13
+ width: number;
14
+ /**
15
+ * Creates a new instance of BaseTextShape
16
+ * @param char - The character this shape represents */
17
+ constructor(char: string);
18
+ /**
19
+ * Converts the text shape to a THREE.js geometry
20
+ * @returns A THREE.js BufferGeometry representing the text shape
21
+ */
22
+ abstract toGeometry(): THREE.BufferGeometry;
23
+ }
@@ -0,0 +1,34 @@
1
+ import { FontInfo, FontLoader } from './fontLoader';
2
+
3
+ /**
4
+ * Default implementation of the FontLoader interface.
5
+ * This class provides font loading functionality using a [CDN-based font repository](https://cdn.jsdelivr.net/gh/mlight-lee/cad-data/fonts/).
6
+ * It loads font metadata from a JSON file and provides access to available fonts.
7
+ */
8
+ export declare class DefaultFontLoader implements FontLoader {
9
+ /** List of available fonts in the system */
10
+ private _avaiableFonts;
11
+ /**
12
+ * Creates a new instance of DefaultFontLoader
13
+ */
14
+ constructor();
15
+ /**
16
+ * Gets the list of available fonts
17
+ * @returns Array of FontInfo objects describing available fonts
18
+ */
19
+ get avaiableFonts(): FontInfo[];
20
+ /**
21
+ * Retrieves information about all available fonts in the system.
22
+ * Loads font metadata from a CDN if not already loaded.
23
+ * @returns Promise that resolves to an array of FontInfo objects
24
+ * @throws {Error} If font metadata cannot be loaded from the CDN
25
+ */
26
+ getAvaiableFonts(): Promise<FontInfo[]>;
27
+ /**
28
+ * Loads the specified fonts into the system.
29
+ * If no font names are provided, loads all available fonts.
30
+ * @param fontNames - Array of font names to load
31
+ * @returns Promise that resolves to an array of FontLoadStatus objects
32
+ */
33
+ load(fontNames: string[]): Promise<import('./fontLoader').FontLoadStatus[]>;
34
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Represents the type of font supported by the system
3
+ * - 'shx': SHX font format commonly used in CAD systems
4
+ * - 'mesh': Mesh-based font format (e.g., TTF, OTF, WOFF)
5
+ */
6
+ export type FontType = 'shx' | 'mesh';
7
+ /**
8
+ * Represents font data stored in the cache database.
9
+ * This interface defines the structure of font data that is stored and retrieved from the cache.
10
+ */
11
+ export interface FontData {
12
+ /** The name of the font */
13
+ name: string;
14
+ /** The type of font (shx or mesh) */
15
+ type: FontType;
16
+ /** The parsed font data. Different types of fonts have different data structures. */
17
+ data: unknown;
18
+ }
@@ -0,0 +1,42 @@
1
+ import { BaseFont } from './baseFont';
2
+ import { FontData } from './font';
3
+
4
+ /**
5
+ * A singleton factory class for creating font instances.
6
+ * This factory can create both ShxFont and MeshFont instances based on the provided font data.
7
+ * It handles the creation of appropriate font objects based on the font type and data format.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const fontFactory = FontFactory.getInstance();
12
+ * const font = fontFactory.createFont(fontData);
13
+ * ```
14
+ */
15
+ export declare class FontFactory {
16
+ private static _instance;
17
+ private constructor();
18
+ /**
19
+ * Gets the singleton instance of the FontFactory
20
+ * @returns The FontFactory instance
21
+ */
22
+ static get instance(): FontFactory;
23
+ /**
24
+ * Creates a font instance based on the provided font data.
25
+ * The type of font created (ShxFont or MeshFont) is determined by the font type.
26
+ *
27
+ * @param data - The font data to create the font instance from
28
+ * @returns A new instance of either ShxFont or MeshFont
29
+ * @throws {Error} If the font data type is not supported
30
+ */
31
+ createFont(data: FontData): BaseFont;
32
+ /**
33
+ * Creates a font instance from a file name and its ArrayBuffer data.
34
+ * The type of font created is determined by the file extension.
35
+ *
36
+ * @param fileName - The name of the font file
37
+ * @param buffer - The ArrayBuffer containing the font data
38
+ * @returns A new instance of either ShxFont or MeshFont
39
+ * @throws {Error} If the file type is not supported
40
+ */
41
+ createFontFromBuffer(fileName: string, buffer: ArrayBuffer): BaseFont;
42
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Represents information about a font in the system
3
+ */
4
+ export interface FontInfo {
5
+ /** Array of font names/aliases */
6
+ name: string[];
7
+ /** Font file name */
8
+ file: string;
9
+ /** Type of the font - either mesh or shx format */
10
+ type: 'woff' | 'shx';
11
+ /** URL where the font can be accessed */
12
+ url: string;
13
+ }
14
+ /**
15
+ * Represents the status of a font loading operation
16
+ */
17
+ export interface FontLoadStatus {
18
+ /** Name of the font that was loaded */
19
+ fontName: string;
20
+ /** URL from which the font was loaded */
21
+ url: string;
22
+ /** Whether the font was successfully loaded */
23
+ status: boolean;
24
+ }
25
+ /**
26
+ * Interface that defines font loading functionality.
27
+ * Applications should implement this interface to provide font loading capabilities.
28
+ * This interface abstracts the font loading process, allowing different implementations
29
+ * for different font sources or loading strategies.
30
+ */
31
+ export interface FontLoader {
32
+ /**
33
+ * Loads the specified fonts into the system
34
+ * @param fontNames - Array of font names to load
35
+ * @returns Promise that resolves to an array of FontLoadStatus objects indicating the load status of each font
36
+ */
37
+ load(fontNames: string[]): Promise<FontLoadStatus[]>;
38
+ /**
39
+ * Retrieves information about all available fonts in the system
40
+ * @returns Promise that resolves to an array of FontInfo objects containing details about available fonts
41
+ */
42
+ getAvaiableFonts(): Promise<FontInfo[]>;
43
+ }