Commit Graph
255 Commits
Author SHA1 Message Date
Davit MatchakhelidzeandClaude Sonnet 5.5 fe67c048ec Leave ROADMAP.md and docs/localization-parity.md to maintainers
CLAUDE.md: PRs don't edit these docs. The affected rows are named in the PR description.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-11-05 09:01:04 +04:00
Davit Matchakhelidze 2c0fe29a02 Merge remote-tracking branch 'origin/main' into ka-language 2026-11-05 09:00:31 +04:00
Tanish Manku 0d72152142 Merge main into land/2354 2026-11-03 18:21:00 -07:00
Tanish Manku 100d812155 Merge main into land/2354 2026-11-03 18:07:17 -07:00
Tanish Manku de753897c4 Merge main into land/1944 2026-11-03 18:00:03 -07:00
Tanish Manku 76d09aaddf Merge remote-tracking branch 'origin/main' into land/2354 2026-11-03 17:22:36 -07:00
Tanish Manku c2d62a2842 Merge main into land/1944 2026-11-03 17:11:42 -07:00
Tanish Manku 68e01dd487 Merge main into land/1230 2026-11-03 17:11:25 -07:00
Tanish Manku 8cdcd6f85c Merge #2354 (XCLIP and XCLIPFRAME) onto main 2026-11-03 15:00:20 -07:00
Tanish Manku 28421dd1d7 Merge #1944 (SHX shape fonts, big fonts and unifonts; linetype shapes) onto main 2026-11-03 14:59:22 -07:00
Tanish Manku 4c00b6732f Merge #2505 (raster images drawn on screen and in PNG output) onto main 2026-11-03 14:52:15 -07:00
Tanish Manku 58bb1e065e docs: date the view twist revision rows to the day they land 2026-11-03 14:50:59 -07:00
Davit MatchakhelidzeandClaude Opus 5.5 f9cb70500d docs: Georgian font fallback in the Georgian section
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 11:17:59 +04:00
Davit MatchakhelidzeandClaude Opus 5.5 4b532f6c24 i18n(ka): translate the strings added upstream; prompts without the trailing "or"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 08:01:13 +04:00
Davit MatchakhelidzeandClaude Opus 5.5 891e87a7db Merge upstream main into ka-language
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 08:01:13 +04:00
mattlafy cbc9db75b1 Merge remote-tracking branch 'upstream/main' into pr/dview
# Conflicts:
#	crates/engine/src/prompt.rs
#	crates/engine/src/session/execute.rs
#	crates/io/src/dxf_read/entities.rs
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/cmdline.rs
2026-11-02 21:53:26 -05:00
Books 2ac500925b DWG: a table cell's text height is an override only when the file flags it (part of #2501) (#2588)
* DWG: a table cell's text height is an override only when the file flags it (#2501)

acadrust's DXF writer writes group 140 for any cell with a style record, even a
default 0.18 with no override flag, and CADCraft read it as a per-cell height,
so cells ignored the table style's height. The bridge now clears the height of a
cell style that has neither the TEXT_HEIGHT property flag nor the content's
height override bit (0 reads as no override).

* Parity checklist: regenerated after merging main

* Tests: inherited table cell heights must stay unset (review on #2588)

A cell that inherits its height must read back as None, not an explicit 0.0625 override.

* Parity checklist: regenerated after merging main

* Test: a cell style with the TEXT_HEIGHT flag, content override bit 128 and a cell with no style record keep the right height (review on #2588)

* DWG: a table cell's content height override (group 144) is kept (review on #2588)

* Parity checklist: regenerated after merging main

* DWG: table cell height takes the first content's override and the style's override flags (review on #2588)

Only the first content's bit-128 height stands for the cell (one height for its text); an
invalid content height no longer keeps the writer's default 0.18; a height marked only in
the style's override flags (newer files) is kept.
2026-11-02 15:01:57 -07:00
STE1200andClaude Opus 5.5 5ec0d215d8 CLI: info and convert report what a damaged DWG left out (read notes, #859) (#2337)
A damaged DWG opens partially since #859 and the drawing's read notes
say how many object records were left out. OPEN echoes them and MCP
`open` returns them as `warnings`, but `cadcraft-cli info` and
`convert` stayed silent: a corpus round trip wrote thousands of skipped
records away without a word.

- convert: each read note goes to stderr as `IN: <note>`, next to the
  skipped-records warning (#872). The exit code stays 0.
- drawing.inspect (and so info, MCP inspect_drawing and the control
  channel): new field `readNotes`, next to `skipped`. Existing fields
  are unchanged.
- run already prints OPEN's notes with the session log.
- README and docs/control-protocol.md say where the notes appear.

Part of #1039.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 15:01:51 -07:00
RicSchonfelder 6660d88785 i18n(pt-BR): translate the rows the sibling catalogs cover (#2581)
* i18n(pt-BR): translate the rows the sibling catalogs cover

The Brazilian Portuguese catalog covered the reference catalog and every marked UI literal, but 191
strings that the German, French, Swedish and Ukrainian catalogs already translate still fell back to
English: the Hatch and Gradient dialog, the Block Editor and dynamic-block grips, the plot and drawing
units dialogs, multileader editing, selection preview settings and the unit names.

Rows follow the catalog's vocabulary (dimension = cota, hatch = hachura, grip = pinça, layout =
apresentação, multileader = multilinha, xref = referência externa), keep the prompt keywords, SPDX
tokens and technology names in English, and are appended after the existing entries.

* docs: leave localization parity updates to maintainers
2026-11-02 14:36:48 -07:00
aiongg 9b32882065 docs: tidy wording 2026-10-31 04:25:44 +00:00
aiongg ee715f4636 docs: tidy agent, contributor and asset docs 2026-10-31 04:17:25 +00:00
Tanish Manku c808939bd1 Merge remote-tracking branch 'origin/main' into pr-1693 2026-10-30 19:25:26 -07:00
Tanish Manku 8822462be2 Merge main into #1693 2026-10-30 19:19:59 -07:00
Tanish Manku e348a30ebd Merge main into #2460 2026-10-30 19:19:54 -07:00
1ecc2a130b DXF: no CLASS instance counts in R2000 files (AutoCAD LT 2026 hung opening them) (#1060)
* DXF: no CLASS instance counts in R2000 files (AutoCAD LT 2026 hung on them)

Since #635 every CLASS record carries group 91, the instance count, at every
version. The count came with the 2004 format: R2000 CLASS records are 1, 2, 3,
90, 280, 281. AutoCAD LT 2026 stops responding when it opens an R2000 DXF
whose CLASS records have a 91, so every R2000 file CADCraft saved locked it up
(a drawing opened from an R2000 file is saved as R2000 again).

Isolated black-box in AutoCAD LT 2026 with synthetic files: the same R2000
file without the 91 groups opens, as does the same content declared AC1032.

The counts are now written only when the file (or the DWG the bridge writes)
is 2004 or later; R2000 output drops the group from every CLASS record,
classes kept from a newer file included.

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

* Test: binary R2000 drops group 91 from a kept foreign CLASS too

Review follow-up: the kept-class check covered R2000 only through ASCII
saves; it now also saves the fixture as binary R2000 and checks that the
ACME_OBJECT CLASS record is 1, 2, 3, 90, 280, 281.

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

* Test: binary 2018 keeps a kept foreign CLASS's instance count

Review follow-up: the kept-class check now saves the fixture as binary at
both R2000 (no group 91) and 2018 (group 91 after the proxy flags, with the
class's count), through one helper.

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

---------

Co-authored-by: Slopapalooza <307952167+Slopapalooza@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:16:30 -07:00
Tanish Manku 47ed3af26c Parity docs are updated by maintainers in batches, not in each PR (#2520)
docs/gaps.md conflicts in 153 open PRs and docs/ui-parity.md in 75, because every PR had to edit them. A PR now names its rows in the description.
2026-10-30 19:11:01 -07:00
Tanish MankuandAldo Zarate 3d623fc4d4 Saving over a DWG asks before it loses content, and saves keep a .bak (#2518)
Includes the .bak work from #1003.

Co-authored-by: Aldo Zarate <azarate@azf.com.mx>
2026-10-30 19:10:57 -07:00
Davit MatchakhelidzeandClaude Opus 5.5 5f6dbede5c docs: Georgian row count after the block-editor prompt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-31 06:00:43 +04:00
Davit MatchakhelidzeandClaude Opus 5.5 651615e5c2 docs: Greek and Bosnian in the language lists; Georgian on the web comes with #1971
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-31 05:00:18 +04:00
Davit MatchakhelidzeandClaude Opus 5.5 66f65b763e docs: list bs beside ka in the supported interface languages
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-31 04:38:42 +04:00
Davit MatchakhelidzeandClaude Opus 5.5 126a734b5c Merge origin/main into ka-language
Keeps Bosnian and Georgian side by side; adds the new block-editor save prompt to ka.tsv.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-31 02:52:48 +04:00
43c41b8e68 bs: Add Bosnian (bs) to the interface languages (#2502)
* Add Bosnian (bs) to the interface languages

bs.tsv: Bosnian (Latin script, Ijekavian) catalog covering every key of
CADCraft's other catalogs, its wording shared with storytold/craft-i18n
locales/bs/ and the strings craft-i18n lacks translated new. Every bs-*
locale selects it; counts use one/few/other. Locale and plural tests,
localization docs and an attribution entry (AI-assisted, not yet
reviewed by a native speaker).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tayw8nmxoLLmKv13jK93z

* docs(localization-parity): Bosnian in the Languages table (CodeRabbit)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 15:46:30 -04:00
Books 8252d0e9bd Extents: an MTEXT's wrap width only narrows its box (#2465) (#2491)
* Extents: an MTEXT's wrap width only narrows its box (#2465)

A garbage group 41 width (3e14) became the box width, so the drawing extents were 3e14
wide. The width is now capped at the longest line's estimate. The width 0 branch is
unchanged. Tests: a_huge_mtext_wrap_width_does_not_inflate_the_extents and
a_narrow_mtext_wrap_width_still_sets_the_box_width.

* Parity checklist: regenerated after merging main

* Parity checklist: regenerated after merging main
2026-10-30 15:46:20 -04:00
2ez4gcxandClaude Opus 5.5 6ec6d97ea0 LISP: getvar and setvar take angle variables in radians (#2482)
* LISP: getvar and setvar take angle variables in radians

CADCraft keeps ANGBASE, SNAPANG, POLARANG, HPANG, CHAMFERD and
DIMJOGANG in degrees as far as sysvars::get/set go, which is right for
the SETVAR command, but AutoLISP's getvar returned those degrees and
setvar took them: (getvar "DIMJOGANG") gave 45.0, and
(setvar "ANGBASE" (/ pi 2)) set 1.57 degrees.

AutoCAD 2024 gives and takes them in radians from AutoLISP: each set to
30 by SETVAR, or to (/ pi 6) by setvar, reads 0.5235987755982987. The
LISP bridge now converts these six; the SETVAR command is unchanged.
getangle_is_relative_to_angbase sets ANGBASE in radians accordingly.

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

* SETVAR: keep real dimension variables real

A dimension variable whose style field is a real (DIMJOGANG, DIMSCALE
and the other real DIM* fields) is now stored as a real header value,
even when the first value set is a whole number. SETVAR DIMJOGANG 45
followed by (setvar "DIMJOGANG" 0.5) no longer rejects the fractional
degrees the radian value gives.

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

* SETVAR: store the value the dimension style took

A real dimension variable now stores the value its style field took after validation, so any input the style accepts (true for DIMSCALE gives 1) is stored as it was before.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 15:45:53 -04:00
2ez4gcxandClaude Opus 5.5 3ba2362ec9 LISP: entity names answer prompts that pick one object (#2477)
* LISP: entity names answer prompts that pick one object

`command` fed an entity name, alone or as `entsel` returns it (name and
point), to the running command as a pick. Prompts that pick a single
object with a point (MEASURE, DIVIDE, LENGTHEN, PEDIT, BREAK, TRIM and
EXTEND in Standard mode, FILLET, OFFSET, REVCLOUD Object, dimensions…)
only take points, so routines got "Invalid input" or nothing at all.

At such a prompt the name is now entered as its point, and a pick at
exactly that point finds the named object (Session::pick_object), so
the point says where on it, as in AutoCAD. A bare name stands at the
object's DXF group 10 point, the point AutoCAD picks it at: a line's
start, a circle's or an arc's centre, a polyline's first vertex. At an
arc's centre MEASURE runs from the arc's end, as AutoCAD does.

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

* Keep a named object for its own input and its own space

A name given at a prompt picking one object now holds only while that
input is taken: a later pick at the same point finds what lies there.
A name for an object in another space picks nothing, instead of the
object under its point in the current space.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 15:45:50 -04:00
9d4b3bb091 Raster images are drawn on screen and in PNG output (#1756)
An IMAGE whose file exists was drawn as a frame with two diagonals. Now
its pixels are loaded when a drawing opens and drawn on screen and in PNG
output, with rotation, clip boundary, fade and object transparency. A file
that can't be read keeps the crossed-out frame and reports a message.

Ported from the raster commit of #1029 onto the split render and canvas
modules. New here: large images are drawn from a pyramid of levels cut
into tiles uploaded as they come into view, instead of one texture with
pixels skipped, so a large scan stays sharp zoomed in and doesn't shimmer
zoomed out.

Limits are listed in docs/gaps.md (FF10): PDF and SVG output write only
the frame, and on screen images lie under all other objects.

Co-Authored-By: Chanthawat Kiriyadee <enwuft@icloud.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 17:05:02 +01:00
ffishman 1e96a3d50c DXF: never let a trail byte 0x5C start an escape
In Shift-JIS, Big5 and GBK a double-byte character's trail byte can be 0x5C, the
backslash (表 95 5C, ソ 83 5C, 許 B3 5C, 乗 81 5C). Written as its bytes right
before U+ or M+, the file holds a backslash byte followed by U+, an escape for a
reader that looks for escapes before it decodes the code page. CADCraft decodes
first, so it read back right, but such a character there is now written as a
\U+XXXX escape and the file reads the same either way. Elsewhere it stays as
its bytes. ANSI_949 has no such trail byte.

Suggested by austin62jake on #1693.
2026-10-30 09:13:10 -03:00
austin62jake dc0564a7a7 Merge branch 'main' into fix/text-middle-bottom-justification
# Conflicts:
#	docs/file-format-parity.md
2026-10-29 21:51:43 -05:00
2d2be155dd fix(engine): refresh attribute baselines after value changes (#2214)
* xtask: the test suite and clippy pass on Windows

Two Windows-only failures stopped `cargo xtask ci` before it got going on
a Windows checkout (CI runs the gate on Linux only, so neither showed):

- parity::tests::civil_dates built a SystemTime 115,740,740 days after
  the epoch (year 318857). Windows' SystemTime ends in the year 30828, so
  the addition panicked ("overflow when adding duration to `SystemTime`").
  That case now checks `civil_from_days` on the day count, which is what
  it was about, on every platform.
- stats.rs imported `walk` for a test that only exists on Unix, so the
  import was unused on Windows and `clippy -D warnings` refused it. The
  Unix test calls `super::walk`, as its neighbour calls `super::walk_inner`.

Checked on Windows 11 x64: `cargo test --workspace` and
`cargo clippy --workspace --all-targets -- -D warnings` both pass.

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

* fix(engine): refresh attribute baselines after value changes

CC-046: invalidate the derived XY baseline for changed justified attribute
values, including small changes inside the writer's imported-font tolerance.
Preserve no-op placement, alignment anchors and Aligned/Fit endpoints.

Regression reproduced on current upstream; all three focused tests pass.
Full cargo xtask ci passed all seven stages on Windows (2558 passing test
executions, zero failures, one ignored). Release Trunk web build passed.
Browser interaction verification is pending user dismissal of a Windows
Security prompt; do not treat the build as a runtime pass.

Windows validation prerequisite: original upstream PR #2198 commit a2dd814.
Independent of editor/ribbon changes; reverting restores only this setter,
its regression tests and corresponding file-format parity record.

* fix(io): preserve insertion elevation when refreshing text baselines

CC-046 review follow-up to PR #2214 comment 4377706777. Regression reproduced insertion Z 9 becoming 7. Preserve group 10 Z; test DXF independent elevations and document the DWG bridge shared elevation. Full cargo xtask ci passes all seven gates. This separate commit is reversible; reverting it restores elevation loss during baseline recomputation. Existing browser UI verification predates this writer correction.

* test(engine): cover global attribute no-ops and two-point exports

CC-046 review 5653054817: verify equal-value global JSON and scripted
-ATTEDIT preserve imported placement, and Aligned/Fit DXF save/reopen
retain both placement points and justification.

Validation: cargo xtask ci passed all seven gates on this branch;
git diff --check passed. Test-only follow-up, no application change.
Depends on CC-046 and unchanged Windows prerequisite #2198.
Revert this commit independently to remove only these assertions.
Runtime evidence remains separately recorded for the production commits.

---------

Co-authored-by: 2ez4gcx <108074836+2ez4gcx@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:38:15 -04:00
42667d1332 ELLIPSE from axis endpoints matches what AutoCAD stores (#2197)
* ELLIPSE from axis endpoints matches what AutoCAD stores

Typed ELLIPSE input was checked against AutoCAD 2024 black-box (synthetic
input in accoreconsole, read back with entget); three rules differed:

- The major axis pointed at the second axis endpoint; AutoCAD points it at
  the first. A full ellipse looks the same, but an elliptical arc's angles
  are measured from that axis, so the arc was drawn on the opposite side of
  the center, and the stored major vector, start point and quadrant order
  all differed.
- A point at "Specify distance to other axis" gave its distance from the
  first axis; AutoCAD takes its distance from the center (the rubber band),
  then swaps the axes when it is the longer one.
- The end-angle prompt had no Included angle option, so `_I` was rejected
  and the next number became an absolute end angle. AutoCAD adds the
  included angle (default 180) to the start angle.

The JSON form (ellipse.axis / ellipse.arc with p1, p2, p3) follows the
same rules. The regression test pins ten AutoCAD-measured cases, among
them survey (VN-2000) coordinates, a near-millimetre ellipse and both
Included angle cases.

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

* docs: geometry parity says which part was measured against AutoCAD

The "How this was measured" section still said no numeric comparison
against AutoCAD had been run, next to the new ELLIPSE revision row that
reports one. It now names the 11 measured ELLIPSE cases and the test
that pins them, and keeps the rest of the document marked as read from
the source. Pointed out in review.

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

* ellipse: drop the import the axis-endpoint change left unused

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-29 21:31:26 -04:00
BooksandBrandon Thomas d15de75406 Dimensions: report the measurement as soon as one is created (#2421) (#2438)
* Dimensions: fill in the measurement when one is created (#2421)

A dimension made in the session kept measurement 0.0 until it was saved and reopened.
add_dim now sets it with the geometry call the DXF/DWG writer uses for group 42.
Block names are still assigned at save time. Test: a_new_dimension_reports_its_measurement.

* Parity checklist: regenerated after merging main

* Dimensions: a jogged radius dimension stores its radius as the measurement (#2421)

draw_jogged_radius set the text but not DimGeometry.measurement, so DIMJOGGED dimensions
kept measurement 0 (and the DXF/DWG group 42 was 0). It now sets the radius.
Test: jogged_radius asserts the stored measurement.

* Parity checklist: regenerated after merging main

* Dimensions: fill in a new dimension's text position when it is created (#2421)

A dimension made in the session kept text_mid (0,0) until it was saved and reopened.
add_dim now sets it from the same dimension_geometry result as the measurement, the
position the writer puts in group 11, unless the user placed the text.
Test: a_new_dimension_reports_its_text_position.

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-29 21:31:22 -04:00
dcbcb6ab32 fix: keep WIPEOUT closure coherent across grips and outlines (#2284)
* fix: keep WIPEOUT closure coherent across grips and outlines

Treat WIPEOUT as a closed polygon with an optional exact terminal closure marker, not as an open polyline. Centralize logical vertices, explicit outlines and closure-preserving vertex edits in the document type. Reuse this contract in grips, geometric primitives, rendering and DXF export without changing the stored schema or writer closure convention.

Add six-version DXF ASCII/binary and DWG regressions for implicit/explicit closure, both windings, all corners, API/interactive edits, undo/redo and repeated saves. Keep open/closed polylines and their coincident endpoints distinct. Cover multiple hot grips, hostile inputs and equivalent mask/frame output.

Validation: cargo xtask ci, all seven stages passed (2571 tests passed, one pre-existing skip). Two unrelated network tests failed transiently in earlier runs; each passed in isolation and the complete final run passed without exclusions. Direct and reopened grip edits produce byte-identical CLI PNG output.

Fixes #2256; related test-only matrix PR #2237 and tracker #2238 B3.

* fix(doc): keep coincident WIPEOUT endpoints separately editable

When an edit makes the endpoints of an implicit boundary coincide, add a separate closing marker rather than reclassifying the edited corner as that marker. Retain the logical vertex count and allow either coincident corner to move independently afterwards.

The document regression fails before the fix. Add API/interactive coverage for both endpoint directions and both closure forms, undo/redo, and subsequent separate edits across all six DXF/DWG versions including binary DXF and save-after-edit. Update the documented editing contract.

Validation: cargo xtask ci passed all seven stages; 2573 tests passed, one pre-existing skip.

Addresses the coincident-endpoint review on PR #2284; related #2256.

---------

Co-authored-by: cloudj <jonbahnes@gmail.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-29 21:31:17 -04:00
74e77f8a92 feat(web): persist validated browser panel layouts (#2258)
* xtask: the test suite and clippy pass on Windows

Two Windows-only failures stopped `cargo xtask ci` before it got going on
a Windows checkout (CI runs the gate on Linux only, so neither showed):

- parity::tests::civil_dates built a SystemTime 115,740,740 days after
  the epoch (year 318857). Windows' SystemTime ends in the year 30828, so
  the addition panicked ("overflow when adding duration to `SystemTime`").
  That case now checks `civil_from_days` on the day count, which is what
  it was about, on every platform.
- stats.rs imported `walk` for a test that only exists on Unix, so the
  import was unused on Windows and `clippy -D warnings` refused it. The
  Unix test calls `super::walk`, as its neighbour calls `super::walk_inner`.

Checked on Windows 11 x64: `cargo test --workspace` and
`cargo clippy --workspace --all-targets -- -D warnings` both pass.

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

* feat(web): persist validated browser panel layouts

CC-053: keep embedded floating, docked and hidden panels across reloads
through the existing host save cycle. Reject malformed/versioned records
atomically; native workspaces and drawings remain unchanged.

Validation: all seven cargo xtask ci gates passed (2558 pass, 0 fail,
1 ignored) on a2dd814 plus this exact change. Actual release Trunk bundle
and Edge floating/close/reload/reset/reload passed. Forced WebGL startup,
render and recovered layout passed; full edit cycle used default mode.

Dependency: original #2198 Windows test prerequisite. No #2226 dependency.
Revert this commit independently to stop using the optional storage key.
Upstream c3b8e7b adds nextest minimum configuration only; no runtime overlap.

---------

Co-authored-by: 2ez4gcx <108074836+2ez4gcx@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:21:42 -04:00
3ccfad60dc Block Editor: BEDIT inside it switches to another block, asking to save first (#2219)
* Block Editor: BEDIT inside it switches to another block, asking to save first

BEDIT (typed, Edit Block, Tools > Block Editor) no longer refuses while the
Block Editor is open: the Edit Block Definition dialog opens on the block being
edited, and choosing another block switches to it. With changes not saved yet
it first asks whether to save them (Yes saves, No discards, Cancel stays), at
the command line as BCLOSE does and in the dialog. The JSON form takes
`save: true|false` and refuses to switch away from unsaved changes without it;
the block to switch to is checked before anything is saved or closed.

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

* Block Editor: the save question is one translatable sentence

The block name and punctuation were added around a translated fragment, so a
translation couldn't place the name or use its own quotation marks.

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

* BEDIT: a block the Block Editor can't switch to is refused before the save question

---------

Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:21:27 -04:00
Books bcf0dbc5e8 DWG: keep the current layer (CLAYER) through a save and reopen (#2252) (#2407)
* DWG: keep the current layer (CLAYER) through a save and reopen (#2252)

The DWG header stores the current layer as a handle, and the one read from the DXF
needn't be the layer's in the document, so the drawing reopened on layer 0.
The bridge now resolves CLAYER by name to the layer's handle before writing, like
the current text and dimension styles. Test: the_current_layer_round_trips_through_dwg.

* Parity checklist: regenerated after merging main

* DWG: resolve $CLAYER through the layer table's Unicode-aware lookup (#2252)

eq_ignore_ascii_case missed non-ASCII case differences such as Survey_Ä / Survey_ä,
leaving layer 0 current. acadrust's Table::get normalises names with to_uppercase.

* DWG: test a current layer named in other letter case (#2252)
2026-10-29 21:21:15 -04:00
aldozarandClaude Opus 5.5 afc12e4dce PEDIT Multiple at the command line (#2225)
* PEDIT Multiple at the command line (#2182)

`M` at "Select polyline" answered that Multiple was only available through the JSON form. It now
works as in AutoCAD: select objects (polylines, lines and arcs), turn the lines and arcs into
polylines on Yes (left out on No), then each option applies to all of them: Close, Open, Width,
Fit, Spline, Decurve, Ltype gen and Reverse. Join joins the selected objects with each other,
ends within a fuzz distance, and reports how many it added. Undo takes the last option back.

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

* Geometry parity status line for PEDIT Multiple

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

* PEDIT Multiple: objects selected first, and Decurve after Fit or Spline

Several objects selected before PEDIT go straight into Multiple, as in AutoCAD, and M keeps a
selection made first. Decurve gives back each polyline's vertices from before its first Fit
or Spline, as single-polyline PEDIT does; a Join drops that record for the joined polylines.

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

* PEDIT Multiple: the Decurve record follows Undo and survives a Join that joins nothing

Each Undo step keeps the record of the vertices from before Fit or Spline, so Fit, Join, Undo,
Decurve gives them back; a Join drops the record only for a polyline that took on segments.

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

* PEDIT: Yes/No asked again on another answer; Decurve keeps a later Width

The convert questions (single and Multiple) take Y/Yes, N/No or Enter and ask again for any
other answer instead of treating it as Yes. Width clears the per-vertex widths of the vertices
kept for Decurve too, so Decurve after Fit or Spline and Width keeps the new width.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:20:58 -04:00
austin62jakeandClaude Opus 5.5 b17ae78cec fix(fonts): place Middle and bottom-justified text as AutoCAD does (#2229)
A justified TEXT's insertion point (group 10) is computed from its alignment point, and AutoCAD
takes it from a DWG as it is (it recomputes it only for DXF). CADCraft placed a Middle (M) text
at half its height and a bottom-justified one a third of its height below the baseline,
whatever the string or font, so in AutoCAD those texts were drawn off their alignment points:
0.35 at height 2.5 for "Tg 1234 ABC" justified M, 0.09 for BL with Arial (#2229).

- Middle (M) now centres the text on its own ink, descenders included, as AutoCAD does. Text
  that draws nothing keeps half the height. Middle Center (MC) and the others are unchanged.
- Bottom justifications with a TrueType face put the alignment point at the face's descent
  (its descent over its cap height, the text height): 0.296 of the height for Arial, where
  AutoCAD puts it. The stroke font keeps a third, which matches AutoCAD's SHX fonts.

`frame` (the DWG insertion point) and `place` (drawing) share the new `justify_offset`, so
what is drawn and what is saved agree. With the reporter's commands, the saved points are now
within 0.0006 of AutoCAD's: M -0.9032 (AutoCAD -0.9038), BL -19.2604 (-19.2599).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 10:01:18 -05:00
Francesco BVandClaude Opus 5.5 14296dc4f5 blocks: XCLIP and XCLIPFRAME, clipped references kept through DXF and DWG
XCLIP clips block and xref references to a rectangular, polygonal or
closed-polyline boundary (Invert clip, ON/OFF, Delete, generate Polyline;
Clipdepth is ignored in 2D). The boundary is Insert::clip, in block
coordinates, so it follows its reference; other references stay whole.
Clipped references are drawn, plotted and framed (XCLIPFRAME 0/1/2) cut
to the boundary, attributes included, and their extents are cut to it.
DXF and DWG read and write it as the reference's ACAD_FILTER/SPATIAL
SPATIAL_FILTER; filters the model can't hold stay foreign data. Gap F2.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-29 11:06:23 +01:00
Davit Matchakhelidze b5f0890b95 Docs: Georgian needs the embedded craft-fonts Geor face 2026-10-29 00:58:26 +04:00
mattlafy b7c62eb93d Merge remote-tracking branch 'upstream/main' into pr/dview
# Conflicts:
#	crates/doc/src/entity.rs
#	crates/engine/src/cmd/layout.rs
#	crates/engine/src/cmd/modify2.rs
#	crates/engine/src/lib.rs
#	crates/io/src/dxf_read.rs
#	crates/io/src/dxf_write.rs
#	crates/render/src/lib.rs
#	crates/ui-egui/src/canvas.rs
#	docs/gaps.md
2026-10-28 15:30:03 -04:00