Repository navigation
Conversation
G-code (.gcode, .gco, .g, .ngc) is read and drawn as PDF (vector), SVG and pictures: from above or isometric, extrusion and cuts coloured by height, travel and rapids as thin lines. A preset option can use the preview the slicer saved in the file instead (PNG, JPG or QOI). .nc stays out (KnifeLemon#562). G-code is a read-only CAD format of the 3D and CAD fields, on the CAD donut; libraries learn its extensions in schema 87. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BPxh5sVP9ruexgBngAnMKK
The SVG of a G-code toolpath lost the quote that ends each path's d attribute, so it could not be read back (SVG → DXF / DWG on the CAD donut failed). Tests read the SVG back and convert to DXF and DWG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BPxh5sVP9ruexgBngAnMKK
KnifeLemon
left a comment
There was a problem hiding this comment.
Thanks for this, @Ugoyo. The reader is careful work: budgets are checked before allocating, damaged and binary files
get a clear reason, the arc maths is right in all three planes (I checked the R-form centre side by hand), and the
thumbnail handling (header first, format sniffed from the bytes) is exactly what we want for untrusted files. The
comparison table with the slicers' own previews was really helpful too.
CI is red because of one string, so a few changes before merging:
- CI:
engine.gcode.nameis still "G-code (built-in)" in languages that translate the suffix.
PortugueseLocalizationTests.Descriptive_engine_names_are_localized_and_brands_are_preservedfails forpt-PTand
pt-BRon every platform (no engine name may contain "built-in"). Please use the same suffix asengine.cad.name
in each of these: pt-PT(motor integrado), pt-BR(mecanismo integrado), de(integriert), it(integrato),
id(bawaan), tr(yerleşik), vi(tích hợp), fa(داخلی), bn-BD(বিল্ট-ইন). The other languages keep
"(built-in)" for CAD too, so they can stay. The two Ubuntu 22.04 package jobs only failed because the portable
artifacts were missing. - Unknown G-codes with coordinates are drawn as moves. In
GcodeToolpath.Machine.Run, a line with coordinates and
no M/T word continues the last motion, and the skip list only has G4/G10/G11/G53/G80–G89. SoG30 X100 Y100,
G29 … X YandG38.2 Z-10(probing) are drawn as G1 moves. Could you treat any G word outside the known modal set
as "not a move", or at least add G29, G30 and G38.x to the skip list? - Stream the SVG.
GcodeDrawing.ToSvgbuilds the whole document in aStringBuilderandWriteSvgthen calls
File.WriteAllText. Near the 12 M point budget, that's a few hundred MB of UTF-16 held twice. Writing to a
StreamWriteron the output file avoids it.
Smaller things, take or leave:
MaxArcSteps = 720never binds: with 5° steps an arc has at most 72 segments, sodocs/ENGINES.md("at most 720
segments") should say 72, or drop the constant.if (radius < 1e-6 || radius > MaxCoordinate)lets NaN through (e.g.R1e300with a horizontal chord). It ends up
harmless only because(int)NaNsaturates to 0.if (!(radius >= 1e-6 && radius <= MaxCoordinate))says what's
meant.- With the slicer's preview selected,
GcodeThumbnail.Largestreads the file to the end, and the 1 GB size check isn't
applied on that path. The slicers all write the block in the header, so stopping at the first G0/G1 move (and checking
the size first) saves a full extra pass on big files without a preview. - Korean: the new
ko.jsonstrings use 합니다체 (그렸습니다, 있습니다, 쓰입니다). The rest of the file uses 해요체
(그렸어요, 있어요, 쓰여요, 보여 줘요).
On .g: please leave it out, like .nc and .tap. It's also used by ANTLR grammars and GAP, and RepRapFirmware macros (config.g, homeall.g) rarely have a toolpath to draw, so the migration shouldn't add it to everyone's CAD donut.
The schema number: #1444 has just taken 87, and other open PRs want the next ones. Don't worry about it, we renumber when merging.
- Drop the .g extension (also ANTLR grammars and GAP; RepRapFirmware macros rarely have a toolpath), like .nc and .tap. Registry, migration, docs, tests. - Localize engine.gcode.name where the "(built-in)" suffix is translated (pt-PT, pt-BR, de, it, id, tr, vi, fa, bn-BD), fixing the Portuguese localization test. - A G-code line with any G word outside the known modal set is not a move, so G29, G30, G38.x probing and canned cycles are no longer drawn as G1 moves. - Stream the SVG to the output file instead of building the whole document in memory. - Only read the thumbnail block in the header: stop at the first move, and check the 1 GB size limit on that path too. - Korean strings use 해요체 like the rest of ko.json. - Guard the arc radius against NaN; drop the unreachable MaxArcSteps and fix the "720 segments" line in docs (5° steps, 72 for a full circle). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BPxh5sVP9ruexgBngAnMKK
Main took schema 87 (Arduino and Processing sketches) and 88 (NuGet and Android packages); the G-code extensions are learned in 89. Specialist count in FormatFieldsTests: 124 with main's new formats. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BPxh5sVP9ruexgBngAnMKK
What does this change?
Filee can now read G-code, the files slicers (PrusaSlicer, Cura, OrcaSlicer, Bambu Studio, SuperSlicer …) write for 3D printers and CAM programs write for CNC machines, and turn them into a picture, an SVG or a PDF. Today nothing previews a
.gcodewithout opening a slicer; people want a quick picture for a print log, a shared folder or a printer farm, and CNC users want to see a program before running it..gcode,.gco,.g(RepRapFirmware macros) and.ngc(LinuxCNC)..ncis left out on purpose: as [Format]: .nc #562 showed, it is also NetCDF (Format request: .grib #244)..tapis left out too (it is also a cassette image of old home computers).; thumbnail begin … ; thumbnail end, PNG, JPG or QOI). With the new preset option set to it, pictures are that preview (the largest one); a file without one gets the toolpath from above, with a notice. SVG and PDF always show the toolpath.;and( )comments. Klipper and RepRapFirmware commands are skipped. Details and limits are indocs/ENGINES.md(new "G-code" section).Fields (
docs/FORMAT-RULES.md): G-code is a read-only CAD format belonging to the 3D models and CAD fields (slicers for printers, CAM for CNC), graded specialist. It adds an input, no new output, so rule 5 doesn't block it. It opens on the CAD donut, whose slots (PDF, PNG, SVG, DXF, DWG, and JPG, WEBP, TIFF, Merge PDF on the back) all work for it: DXF/DWG go through the SVG, as the toolpath's lines. The new preset card is hidden while both of its fields are off, like its files' slots.Preset option:
GcodeOptions.View(Top,Isometric,Thumbnail), saved by name and read leniently likeCadOptions. Shown for pictures, SVG and PDF, after the CAD card, with its texts in all 22 languages.Migration: existing libraries learn the four extensions on the CAD donut in settings schema 87 (custom claims stay put). Main moves fast, so this number may need renumbering when merging.
Defensive reading (as asked on #1384): a damaged file fails with a clear
InvalidDataException(no moves, only moves, a coordinate past 1 km, binary data, a.bgcoderenamed.gcode). Budgets are checked before allocating: file size (1 GB), points to draw (12 million after merging points closer than 0.02 mm), line length (4096 characters, the rest of a longer comment skipped), arc segments (720), thumbnails (4096 × 4096 and 32 MB of base64, the image header read before it is decoded). Cancellation is checked while reading.Speed: SVG is written as text; PDF and pictures are drawn with SkiaSharp directly (a large print's SVG is too slow to read back), and segments hidden exactly under a later one are left out. A 35 MB PrusaSlicer file (1.3 million lines) takes about 9 s to PNG with 320 MB of memory; a 285 MB file about 28 s and 760 MB.
SvgRenderer.Rasterizegets an overload that takes a recordedSKPicture; no other engine changes. No new dependency.Not in this PR (planned as a follow-up): Prusa's binary G-code
.bgcode↔.gcode. G-code → TXT isn't added either: other text formats (JSON, YAML) don't have a plain TXT route, so it wouldn't fit.Type of change
How was it tested?
dotnet format Filee.slnx --verify-no-changes --severity warnanddotnet build Filee.slnx -c Releasedotnet test: newGcodeTests(33, generated files: PrusaSlicer-like and Cura-like prints, CNC programs with modal moves, inches and arcs, thumbnails in PNG / JPG / QOI, broken and oversized thumbnails, damaged and binary files, every target and extension, DXF/DWG through the SVG) andGcodeFormatTests(detection, fields, migration, option);FormatFieldsTestscounts updated; a preset editor render test with screenshots. Core: all pass except the two tests that need a non-root user. Engines: the same 18 failures as on main in this environment (Pandoc, FFmpeg, LibreOffice not installed, root). App (filtered): the slice-label tests crash the test host here on main too..ngcprograms. The previews were compared with the thumbnail each slicer saved in its file, and the CNC programs (arcs included) with an independent rendering made withpygcode; they match. A 3× Benchy sliced at 0.1 mm (35 MB) and an 8-fold copy of it (285 MB) were used for time and memory.Not tested: OrcaSlicer and Bambu Studio files (no free sample found; they use the same thumbnail block as PrusaSlicer), and real QOI thumbnails (tested with QOI written by ImageMagick).
Screenshots (UI changes)
3D printers: the preview each slicer saved in its file, next to Filee's drawing of the same file.
CNC programs (arcs, modal moves): an independent rendering with
pygcodenext to Filee's.pygcode(reference)heart.ngcaxis.ngcThe new preset card (shown for pictures, SVG and PDF while the 3D or CAD field is on):
Checklist
src/Filee.App/Assets/i18n/*.jsonfilesTHIRD-PARTY-NOTICES.md(none added)🤖 Generated with Claude Code