Commit Graph
14 Commits
Author SHA1 Message Date
Dylan M. Taylor 7d33d9d4dd refactor: split complex input, explode, sweep, cache and options code into helpers (#2187)
Pure extraction, no behaviour change: same order of side effects, same
early returns and error values. Clears cognitive-complexity findings on
AreaM::input, explode_kind, hatch sweep, the COMPARE overlay paint and
the Files options tab (S3776).
2026-10-25 21:50:19 -04:00
Dylan M. Taylor f24af47ffb refactor: cut helper signatures to 7 parameters (S107) (#2047)
* refactor: cut four helper signatures to 7 parameters (S107)

* fix: item_json params

* fix: keep the eight-argument dim calls to seven after rebase
2026-10-25 19:21:26 -04:00
skylartaylor 48b4165591 docs: document security limits and regression guarantees 2026-10-23 01:59:55 +02:00
Dylan M. Taylorandskylartaylor 2dbc7699a0 security: budget the rendering pipeline against DoS geometry (CWE-400/407/789) (#1849)
* security: budget the rendering pipeline against DoS geometry (CWE-400/407/789)

Several render paths let crafted drawing data spin the rendering thread or
allocate without bound:

- Hatch dash sweeping reset its per-span step counter and used emitted geometry
  as its only limit, so gap-only families (which emit nothing) could multiply
  CPU work. Skip families that cannot draw and charge every dash step against a
  shared per-hatch work budget (row 10).
- Hatch polygon deduplication compared loops with an O(n²) cyclic match and
  every loop against every kept one. Charge vertex comparisons against a shared
  budget and stop deduplicating when spent (row 12).
- Table coverage marked every merge rectangle, so overlapping merges re-marked
  covered cells quadratically. Bound marking to a small multiple of the cell
  count (row 11).
- Broken-table part layout expanded sparse rows to full width before checking
  whether detailed layout is allowed. Only expand when within the cell limit;
  otherwise leave cells sparse and let layout draw an outline (row 17).
- Dimension text substitution copied the base for every `<>` placeholder with no
  size bound. Estimate the expansion and cap it at a fixed text budget (row 32).
- Linetype range generation cycled all-gap patterns forever (nothing emitted, so
  the emit limit never tripped). Return continuous for all-gap patterns and
  bound visited pattern elements (row 38).
- Viewport contents built with a fresh expansion counter, so a layout could far
  exceed the documented block-expansion limit. Share one budget across the whole
  build, seeded with what the enclosing list already spent (row 22).

New tests for the all-gap linetype path; all render tests pass, clippy clean.

Addresses findings rows 10, 11, 12, 17, 22, 32, 38.

* fix: preserve bounded render fallbacks and text output

---------

Co-authored-by: skylartaylor <26588250+skylartaylor@users.noreply.github.com>
2026-10-22 17:08:25 -04:00
8cd0d46d58 Zoom and pan regenerate in the background instead of freezing the window (#903)
* Zoom and pan regenerate in the background instead of freezing the window

A rebuild that only the view asks for (a new 2x zoom band, a pan out of the
built area) now runs on a worker thread while the canvas keeps drawing the
previous display list, scaled by the view uniform. The worker builds the list,
converts it to vertex data and creates the GPU buffers, so the frame that swaps
it in only swaps buffers. One build runs at a time; a result from an older
drawing revision is dropped. Edits, the first build and the web build (no
threads) still rebuild synchronously.

ZOOM no longer calls touch(): it changes the view, not the drawing, and the
bumped revision made every typed zoom a full blocking rebuild (wheel zoom
never did). REGEN, REGENALL and layout switches still touch.

ui.screenshot waits (up to 6 s) for a background rebuild so agents capture
the new view; ui.inspect perf reports "building".

On a hatched 12k-entity DWG (~340k primitives) the longest UI stall per zoom
went from 2-4.5 s to 26-64 ms.

Also: cargo fmt of a comment in engine/src/prompt.rs that was failing the fmt
gate on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Cancel a background rebuild when the view moves on

A view that needs a different display list now cancels the build in flight
and starts one for itself, instead of waiting for the outdated build to land
and only then starting the next. A long scroll through many zoom bands builds
only for where it stops: the list lands about one build after the last step
(2.0-2.3 s on a hatched 12k-entity DWG) instead of up to two, and an outdated
build no longer keeps a core busy.

cadcraft_render::Options gains `cancel` (an Arc<AtomicBool>); a set flag stops
the build at the next entity (block contents included) and the hatch sweep at
its next pattern line, returning a partial list the caller discards. The
canvas's Job sets its flag when dropped, so replacing or dropping a job
cancels it; a cancelled worker sends nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* cargo fmt: crates/doc/src/dynblock.rs (fails the fmt gate on main)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-13 06:58:16 -04:00
76b0ef8897 Select: pick a solid hatch inside its fill, islands left out, not its bounding rectangle (follow-up to #747) (#763)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:20:39 -04:00
Books 488308a2de Hatch: a view covering a pattern hatch leaves its lines exactly as they are (#762)
With a view, each span of a pattern line was cut to the view's extent
intersected with the boundary's. Spans already lie within the boundary,
and the boundary extent comes from rotating the corners directly while a
span end comes from interpolating along an edge, so where a line passes
through a corner the two differ by a rounding error and the cut moved the
end (by 3e-16 on Windows, whose sin/cos round differently). The spans are
now cut to the view's extent only, so normal_zoom_pattern_is_unchanged
holds on every platform.
2026-10-13 04:34:30 -04:00
aldozarandClaude Opus 5.5 0675648de8 Hatch: pick the pattern from swatches instead of typing its name (fixes #669) (#679)
Squash of PR #679 by @aldozar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:21:49 -04:00
rangoDJandClaude Opus 5.5 875f99d26f Deduplicate identical boundary loops to prevent empty hatch fills (#671)
Squash of PR #671 by @rangoDJ.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:13:20 -04:00
STE1200andClaude Opus 5.5 244feb6e89 Render: level of detail and view clipping for pattern hatches on screen (fixes #544) (#638)
Squash of PR #638 by @STE1200.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:10:37 -04:00
aldozarandClaude Opus 5.5 135c928fea Hatches: draw the pattern definition stored in the file; scale library patterns in metric drawings (#643)
Squash of PR #643 by @aldozar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:54:18 -04:00
Valentin KleinandClaude Opus 5.5 ee34f423cc Plot styles: colour-dependent tables apply to PDF plots and layouts (part of #410) (#412)
A PlotStyleTable model in doc with our own built-in tables (default.ctb keeps
object properties, monochrome.ctb prints black, grayscale.ctb prints the grey of
each colour's luminance). The render builder resolves each object's style by its
index colour (true colours by the nearest index) and applies colour, screening,
linetype and lineweight. PLOT/EXPORTPDF use the page setup's table (or the
plotStyleTable option); layouts with Display plot styles (PAGESETUP
displayPlotStyles, DXF plot flag 2) show it on screen and in PNG/SVG exports.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:19:48 -04:00
Valentin KleinandClaude Opus 5.5 d433112f1e Draw hatch island styles, backgrounds, two-colour gradients and file pattern definitions (fixes #289, fixes #290) (#302)
- Island detection style (group 75) picks the loops that take part: outer keeps the
  outermost loops and their first islands, ignore only the outermost loops.
- A pattern hatch's background colour is filled under its pattern lines.
- Gradients blend colour 1 to colour 2 (LINEAR, CYLINDER, CURVED, SPHERICAL,
  HEMISPHERICAL and the INV forms) along their angle, shifted when not centred, drawn as
  bounded colour steps; ByLayer / ByBlock gradient colours resolve to the hatch's layer /
  block colour instead of colour 7.
- DXF HATCH pattern definition lines (78, 53, 43-46, 79, 49) of a pattern the library
  doesn't define are kept on the hatch (new `patternLines` field), drawn and written back;
  hostile counts are capped.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:55:49 -04:00
Brandon ThomasandClaude Opus 5.5 d9ab00c53c M0: CADCraft skeleton and vertical slice
Workspace (geom, dxf, color, doc, fonts, render, io, engine, ui-egui, mcp; apps cadcraft,
cadcraft-cli, cadcraft-web; xtask), AutoCAD-for-Mac style UI with code-drawn icons, command line
with prompts/keywords/AutoComplete, draw and modify commands, object snaps, polar/ortho,
selection, undo, layers and properties palettes, DXF read/write, SVG/PNG export, MCP server,
JSON control channel, CLI, wasm build, README, ROADMAP, AGENTS.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:22:25 -04:00