|
| 1 | +/** |
| 2 | + * Per-call options for {@link SVGLoader.load}. All fields optional; |
| 3 | + * caller-supplied values override the defaults in |
| 4 | + * {@link DEFAULT_SVG_LOAD_OPTIONS}. |
| 5 | + */ |
| 6 | +export interface SVGLoadOptions { |
| 7 | + |
| 8 | + /** |
| 9 | + * Multiplier from SVG user-space units (1 unit = the value of the |
| 10 | + * `width`/`height`/`viewBox` attributes) into the SceneModel's |
| 11 | + * coordinate system. Default `1` — leaves coordinates in SVG |
| 12 | + * native units. For a drawing meant to sit in a millimetre scene |
| 13 | + * with SVG authored at 1 unit = 1 mm, leave at `1`; for SVG |
| 14 | + * authored at 1 unit = 1 inch, use `25.4`. |
| 15 | + */ |
| 16 | + scale?: number; |
| 17 | + |
| 18 | + /** |
| 19 | + * When `true` (default), Y coordinates are negated so the SVG |
| 20 | + * (which uses +Y-down) renders the right way up in a scene with |
| 21 | + * +Y-up. Pass `false` if the host scene is +Y-down, or if you |
| 22 | + * want the SVG to appear mirrored vertically for some other |
| 23 | + * reason. |
| 24 | + */ |
| 25 | + flipY?: boolean; |
| 26 | + |
| 27 | + /** |
| 28 | + * Optional override for stroke colour. When set to an `[r, g, b]` |
| 29 | + * triplet (channels in `[0, 1]`), every emitted line mesh uses |
| 30 | + * this colour regardless of the SVG's own `stroke` attribute — |
| 31 | + * useful for "ink one colour" presentations. |
| 32 | + * |
| 33 | + * When **omitted** (the default), the loader honours per-element |
| 34 | + * stroke colours from the SVG `stroke` attribute, bucketing |
| 35 | + * emitted segments by colour. |
| 36 | + */ |
| 37 | + color?: [number, number, number]; |
| 38 | + |
| 39 | + /** |
| 40 | + * Optional override for fill colour. When set to an `[r, g, b]` |
| 41 | + * triplet, every emitted fill mesh uses this colour regardless |
| 42 | + * of the SVG's `fill` attribute. |
| 43 | + */ |
| 44 | + fillColor?: [number, number, number]; |
| 45 | + |
| 46 | + /** |
| 47 | + * Floor on the pixel width of emitted line meshes. Sub-pixel SVG |
| 48 | + * strokes would otherwise vanish under GPU rasterisation. Default |
| 49 | + * `1.0`. |
| 50 | + */ |
| 51 | + minLineWidth?: number; |
| 52 | + |
| 53 | + /** |
| 54 | + * Multiplier from SVG `stroke-width` (user-space units) into the |
| 55 | + * pixel widths consumed by `SceneMaterialParams.lineWidth`. |
| 56 | + * Default `1.0`. SVGs that author hairlines at 0.25 user-units |
| 57 | + * benefit from raising this to ~3 so they meet {@link minLineWidth} |
| 58 | + * naturally rather than being clamped. |
| 59 | + */ |
| 60 | + lineWidthScale?: number; |
| 61 | + |
| 62 | + /** |
| 63 | + * Steps used to tessellate each cubic / quadratic bezier segment |
| 64 | + * into line pieces. Higher = smoother curves, more line indices. |
| 65 | + * `16` is a reasonable default for hand-drawn / CAD-export SVGs; |
| 66 | + * raise to `32` for logos and icon sets dominated by curves. |
| 67 | + * Default `16`. |
| 68 | + */ |
| 69 | + bezierSteps?: number; |
| 70 | + |
| 71 | + /** |
| 72 | + * Steps used to tessellate `<circle>` and `<ellipse>` elements, |
| 73 | + * and the elliptical-arc commands (`A`/`a`) in paths. `36` = 10° |
| 74 | + * facets, indistinguishable from smooth at typical zoom. Default |
| 75 | + * `36`. |
| 76 | + */ |
| 77 | + circleSteps?: number; |
| 78 | + |
| 79 | + /** |
| 80 | + * When `true` (default), `<path>`, `<rect>`, `<circle>`, |
| 81 | + * `<ellipse>`, and `<polygon>` elements with a non-`none` `fill` |
| 82 | + * attribute are tessellated to triangles via earcut and emitted |
| 83 | + * as `TrianglesPrimitive` meshes. Pass `false` to skip fill |
| 84 | + * emission (strokes only). |
| 85 | + */ |
| 86 | + renderFills?: boolean; |
| 87 | + |
| 88 | + /** |
| 89 | + * Z-offset applied to filled triangle meshes so they sit *behind* |
| 90 | + * stroked line meshes from the same drawing. Without this, the |
| 91 | + * filled region's depth-buffer write swallows stroke fragments |
| 92 | + * along the shared boundary (z-fighting). Default `-0.05` (in |
| 93 | + * scene units post-{@link scale}). |
| 94 | + */ |
| 95 | + fillZOffset?: number; |
| 96 | + |
| 97 | + /** |
| 98 | + * How element ids on emitted SceneObjects are formed. |
| 99 | + * |
| 100 | + * - `"group"` (default) — one SceneObject per top-level `<g>`. |
| 101 | + * Elements outside any group go into a synthetic SceneObject |
| 102 | + * named `<sceneModelId>-root`. Best for hand-authored SVGs |
| 103 | + * where `<g id="walls">` etc. is the user's logical grouping. |
| 104 | + * - `"element"` — one SceneObject per geometric element. Best |
| 105 | + * for SVGs exported from CAD where individual entities should |
| 106 | + * be independently pickable and the file has no useful groups. |
| 107 | + */ |
| 108 | + objectIdStrategy?: "group" | "element"; |
| 109 | + |
| 110 | + /** |
| 111 | + * Default stroke colour applied when an element (and all its |
| 112 | + * ancestors) carry no `stroke` attribute. SVG itself defaults to |
| 113 | + * `none` for stroke — but the typical user expectation when |
| 114 | + * importing an SVG into a viewer is "show me the drawing", so |
| 115 | + * the loader defaults to black. Set to `null` to honour SVG's |
| 116 | + * own default (no stroke at all when unspecified). |
| 117 | + */ |
| 118 | + defaultStroke?: [number, number, number] | null; |
| 119 | + |
| 120 | + /** |
| 121 | + * Default fill colour applied when an element (and all its |
| 122 | + * ancestors) carry no `fill` attribute. SVG itself defaults |
| 123 | + * `fill` to black; the loader follows that to match browser |
| 124 | + * rendering. Set to `null` to suppress fills on un-styled |
| 125 | + * elements. |
| 126 | + */ |
| 127 | + defaultFill?: [number, number, number] | null; |
| 128 | + |
| 129 | + /** |
| 130 | + * Optional progress callback. Invoked once per top-level element |
| 131 | + * group after extraction with `(elementIndex, totalElements)`. |
| 132 | + */ |
| 133 | + onProgress?: (elementIndex: number, totalElements: number) => void; |
| 134 | + |
| 135 | + /** |
| 136 | + * When `true` (default), `<text>` elements are rasterised onto an |
| 137 | + * in-memory canvas per label and emitted as textured triangle |
| 138 | + * quads — room labels, dimensions, drawing-title text, etc. Pass |
| 139 | + * `false` to skip text emission entirely. |
| 140 | + * |
| 141 | + * Each `<text>` becomes one quad regardless of how many `<tspan>` |
| 142 | + * children it contains; per-tspan letter-spacing is lost but the |
| 143 | + * overall label reads correctly. Hosts that need per-tspan |
| 144 | + * kerning precision should pre-rasterise externally. |
| 145 | + */ |
| 146 | + renderText?: boolean; |
| 147 | + |
| 148 | + /** |
| 149 | + * Optional override for text fill colour. When set, every emitted |
| 150 | + * text quad rasterises with this colour regardless of the SVG's |
| 151 | + * own `fill` attribute / CSS class. |
| 152 | + */ |
| 153 | + textColor?: [number, number, number]; |
| 154 | + |
| 155 | + /** |
| 156 | + * Fallback fill colour when a `<text>` element resolves to no |
| 157 | + * `fill` (no attribute, no class declaration, parent style also |
| 158 | + * null). Default near-black `[0.05, 0.05, 0.05]`. |
| 159 | + */ |
| 160 | + textDefaultColor?: [number, number, number]; |
| 161 | + |
| 162 | + /** |
| 163 | + * Fallback CSS font face when a `<text>` element's class doesn't |
| 164 | + * specify `font-family`. Default |
| 165 | + * `"Arial, Helvetica, sans-serif"`. |
| 166 | + */ |
| 167 | + textFont?: string; |
| 168 | + |
| 169 | + /** |
| 170 | + * Fallback font size (SVG user-units) when a `<text>` element |
| 171 | + * carries no `font-size` attribute or class. Default `12`. |
| 172 | + */ |
| 173 | + textDefaultSize?: number; |
| 174 | + |
| 175 | + /** |
| 176 | + * Canvas pixels per SVG user-unit when rasterising text. Higher = |
| 177 | + * sharper text at the cost of texture memory. `4` reads cleanly |
| 178 | + * at typical drawing-zoom; raise to `8` for high-DPI displays, |
| 179 | + * drop to `2` for huge drawings with hundreds of labels. Default |
| 180 | + * `4`. |
| 181 | + */ |
| 182 | + textPxPerUnit?: number; |
| 183 | +} |
| 184 | + |
| 185 | + |
| 186 | +/** |
| 187 | + * @private |
| 188 | + */ |
| 189 | +export const DEFAULT_SVG_LOAD_OPTIONS: Required< |
| 190 | + Omit<SVGLoadOptions, "color" | "fillColor" | "onProgress" | "defaultStroke" | "defaultFill" | "textColor"> |
| 191 | +> = { |
| 192 | + scale: 1, |
| 193 | + flipY: true, |
| 194 | + minLineWidth: 1.0, |
| 195 | + lineWidthScale: 1.0, |
| 196 | + bezierSteps: 16, |
| 197 | + circleSteps: 36, |
| 198 | + renderFills: true, |
| 199 | + fillZOffset: -0.05, |
| 200 | + objectIdStrategy: "group", |
| 201 | + renderText: true, |
| 202 | + textDefaultColor: [0.05, 0.05, 0.05], |
| 203 | + textFont: "Arial, Helvetica, sans-serif", |
| 204 | + textDefaultSize: 12, |
| 205 | + textPxPerUnit: 4, |
| 206 | +}; |
0 commit comments