Read per-path extrusion width and line height from slicer comments - #458
Merged
Merged
Conversation
|
Visit the preview URL for this PR (updated for commit 39961eb): https://gcode-preview--pr458-interpreter-line-wid-kx9lalpy.web.app (expires Wed, 07 Oct 2026 18:01:52 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: 59bd114ae4847b32c2bba0b68620b9069a3e3531 |
4 tasks done
- Parse standalone ;WIDTH:/;HEIGHT: comments (PrusaSlicer, SuperSlicer, OrcaSlicer, Bambu Studio) in a new interpreter comment handler and track the values on the job state, so adaptive-layer-height prints render each path with its true dimensions instead of the hardcoded 0.6/0.2 - Break the in-progress path lazily at the next move when the state dimensions changed (Job.continuePath), which keeps streamed parses identical to one-shot parses across chunk boundaries - Make ObjectsManager.lineHeight optional, mirroring extrusionWidth: unset means each path renders with its own height (tubes and the line midplane offset); an explicitly set global value overrides as before - Files without dimension comments are unaffected: paths keep defaulting to 0.6/0.2
- Security-review hardening: the value capture is now a strict decimal pattern, so ;WIDTH:0.45mm is ignored instead of parseFloat silently truncating it to 0.45
Reworks the ;WIDTH:/;HEIGHT: support after review feedback: no comment command in the interpreter — the dimensions ride the same metadata pipeline the layer comments already use, and become per-path values that take precedence over the global settings. - Delete the interpreter comment handler; PrusaFamilyMetadataParser gains parseExtrusionDimensions (with a base-class default reporting none), reported as line-indexed events with sub-layer granularity, accumulated across streaming chunks with whole-file line indices like the layer metadata - ;WIDTH:/;HEIGHT: now also identify the Prusa family dialect - Job.beginCommand, called by the interpreter once per command, maps the line-indexed events onto the command stream and folds them into the state; path breaking stays lazy at the next move (continuePath), keeping streamed parses identical to one-shot parses - Precedence flip: a path's own dimensions (from metadata) win, the global lineHeight/extrusionWidth settings fill in for paths without them, and the built-in 0.6/0.2 defaults apply last — paths and state now leave dimensions undefined until metadata announces them
- CodeQL flagged js/polynomial-redos on the strict numeric capture: the ambiguous adjacent digit runs in \d*\.?\d+ backtrack quadratically on long digit strings with a non-matching tail - \d+(?:\.\d+)? fails in linear time; exponent notation is dropped too, since the dialect never emits it — overflow-to-Infinity is still rejected by the finiteness check
sophiedeziel
force-pushed
the
interpreter-line-width-height
branch
from
September 7, 2026 16:24
bc5b773 to
e64eced
Compare
;WIDTH:/;HEIGHT: were added to the PrusaSlicer family's identification patterns, but Slic3r -- which PrusaSlicer was forked from -- emits the same comments in its verbose gcode. The family parser is tried first, so a file whose header says "generated by Slic3r" was claimed by it anyway, and Slic3r's own layer markers (;move to next layer) then went unparsed. The generator comments already identify the family; the dimension comments identify no single slicer. Test fixtures that leaned on them to be detected now carry a generator comment, like real files do. Also labels the demo's extrusion width control as a fallback: paths that carry a ;WIDTH: of their own ignore it, which is every bundled demo file except the two CNC ones (3DBenchy alone has 33,168 of them).
3 tasks done
A slicer emits one dimension comment per extrusion -- 33,168 of them in the bundled 3DBenchy -- and every comment in the file is offered to this pattern. The capture arrays were a fifth of the scan's cost, and both captured values are recoverable for less: the leading letter says which dimension it is, and the pattern has already vouched for everything past the colon being the number. A first-character check now rejects the other comments before the pattern runs. Measured on the bundled files, the scan is 14-23% faster and its output byte-identical; against the whole parse the gain is 0.4 ms of ~55 ms, below the noise floor.
This was referenced Sep 14, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Prints sliced with adaptive layer height render as uniform 0.2 mm slabs, because every path is built with the same hardcoded dimensions. PrusaSlicer-family slicers (PrusaSlicer, SuperSlicer, OrcaSlicer, Bambu Studio) already announce the truth in
;WIDTH:/;HEIGHT:comments, so this reads them through the slicer metadata pipeline rather than teaching the interpreter about comments.The comments are line-indexed rather than folded into the per-layer metadata: width changes many times within a layer (33,168 times in the bundled 3DBenchy), so per-layer granularity would not fit. A dimension change breaks the current path lazily, at the next move rather than at the comment, because the interpreter resumes the last path at every streaming chunk boundary — an eager break would be undone and streamed output would diverge from one-shot.
Ref #96. #461 and #462 are stacked on this.
Behavior changes
lineHeight/extrusionWidthare now a fallback, not an override. Precedence per path: slicer value → global setting → built-in 0.6 / 0.2. A file that carries dimension comments ignores the global settings, so the demo's extrusion-width slider no longer affects it (relabelled accordingly). Files without the comments render byte-identically to before.Public API changes
SceneManager.lineHeightgetter is nownumber | undefined— breaking for TypeScript consumers who annotate it asnumber. It has to be able to report "unset", which is what lets a path's own height win.Path.extrusionWidth/Path.lineHeightare now optional (undefined= the slicer announced none); newPath.DEFAULT_EXTRUSION_WIDTH/DEFAULT_LINE_HEIGHTconstants expose the built-in values.Path.geometryoptions renamedextrusionWidthOverride→extrusionWidthFallback(same for height), with inverted semantics. No@deprecatedalias: an alias would have to keep the old precedence to be meaningful, which is the behavior being replaced.ExtrusionDimensionMetadatatype,Metadata.extrusionDimensions, and an overridableSlicerMetadataParser.parseExtrusionDimensionsthat defaults to reporting none.Screenshots
Calibration cube sliced with adaptive layer heights (0.07–0.33 mm), same camera:
Checks
npm run checkpasses (test + typeCheck + lint)npm run test:coverage—src/still at 100%enhancement)Assisted by Claude Code - Fable 5