Windows reports AltGr as Ctrl+Alt, so '@' and similar layout glyphs were
treated as shortcuts and dropped; polar input like @10<45 failed.
Fixes#1236
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MOVE shifted the *D block contents but left the block cache on the old
epoch, so reopened drawings showed dimensions in place until REGEN.
Fixes#1342
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
They went out at depth 0 while lines kept theirs, so some fills
covered lines that DRAWORDER had put on top.
Fixes#1345
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The copy kept the source boundary handles, so editing the source
regenerated the copy onto the source outline and it seemed to vanish.
Fixes#1370
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reference direction, base point and locked point went through f32,
so the drawn line drifted off true parallel.
Fixes#1387
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dot-named temp file is stored Hidden by Samba and the attribute
followed it through the replace. Clear it unless the drawing was
already hidden.
Fixes#1414
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The definition took a peeked handle that the image then also received;
the DWG writer dropped the shared-handle definition and reopened images
lost their file.
Fixes#1421
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the SPATIAL filter through extension-dictionary fallbacks
(missing xdictionary handle, DictionaryWithDefault, case/whitespace
tolerant keys) so clipped INSERTs no longer plot unclipped. The
inverse-block matrix is used as stored; the codec decodes the on-disk
column-major layout (fixed upstream).
#1521 inserted crash_log between web_diag's doc comment and its module, so the comment documented crash_log instead. #1519 wrote the survived marker with a literal line break inside the string.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The DWF package reader, the DGN stream inflater and the new DGN
ExtendedColors scan each read a zlib/zip payload to its end, so a
crafted or corrupt file could inflate until memory ran out. Cap them:
1 GiB for a whole DWF package, 512 MiB per DGN stream, 4 MiB per
ExtendedColors record candidate - far above real files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A release build hides the console and is stripped, so a panic ended the
process with nothing on screen, nothing on stderr and nothing on disk.
The window simply disappeared. That is all a reporter has ever had to
work from, which is why #635 and #845 ask for crash logs and why a
crash like #830 can be reported for months with no detail beyond the
steps to reach it.
Every panic now writes one file to <config>/crash_logs naming the
version, the OS, the graphics backend that was live, the thread, the
panic message, the source location and a backtrace. The hook chains
onto whatever was installed before it, so a debug build still prints to
stderr as well, and it is installed after the child-process handoffs:
a GPU probe aborting is how an unusable backend gets detected, not a
crash worth filing.
The report is written by a plain function taking the message and
location, so the layout is covered by tests without installing a panic
hook -- a test that asserts inside a hook fires on every other test's
panic and aborts the whole binary, which is how the first version of
these tests failed.
Backtraces use `force_capture`, not `capture`: a report that says
"disabled backtrace" because the user never set RUST_BACKTRACE is
exactly the report that helps nobody.
The text is deliberately English and does not go through `t!`. It is
read by whoever receives the bug report, and a panic handler that calls
into the localisation machinery risks a second panic while handling the
first.
Confirmed on Windows 11 by reproducing a real crash: opening either of
two large drawings on an Intel Iris Xe dies inside wgpu, and the report
names it -- "Buffer with '(wgpu internal) StagingBelt staging buffer'
label is invalid", backend dx12, with the full frame list.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Insert > Reference: the PDF Attach button becomes an Attach Underlay menu
(PDF / DWF / DGN); its face runs the last one chosen.
- DWFATTACH, DGNATTACH and ATTACH on a .dwf/.dwfx/.dgn open the Attach
dialog for that kind: sheets or models with thumbnails (one chosen),
placement, path type, file details with the sheet / model size, and for
DGN the conversion units (sub units offer 1 / sub units per master as the
scale).
- DGN V8 true colours come from the ExtendedColors record packed in the
non-model attributes stream; the colour word's high part numbers them.
- A DGN model's extent includes each text's box (its length along the
baseline and 1.5 x its height), as the reference sizes a model.
- DWFx text uses the family named in its embedded (deobfuscated) font.
- DWF contrast pivots at 0.73 once colours are turned over for a dark
background.
- Hairline strokes are drawn solid one pixel wide, and underlay rasters are
made at or below their size on screen so those lines stay unbroken.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drops the Google Play banner and its image from the Start page sponsors; the OpenAEC sponsor stays.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- W2D: a stream cut off right after an extended opcode's '(' sliced its
body backwards and panicked.
- DGN V8: the compound-file header was indexed before its length was
known (a short file with the signature panicked), the sector shift was
taken on trust (0 or 1 underflowed `sector / 4 - 1` into an endless
loop), and the DIFAT chain count was unbounded. The header must now be
complete, the shift 9 or 12, and the chain no longer than the file.
Found fuzzing the #1514 readers with truncated and random input.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The crash sentinel is armed before the event loop and disarmed after it
returns, so anything that stops the process without unwinding leaves the
file behind and the next launch skips that backend. A real GPU failure
does that — and so does the user closing the app from Task Manager, an
OOM kill, a power cut, or a panic with nothing to do with graphics.
The cost is not a one-off: the skip is permanent, and each later
abnormal end takes the next backend with it, walking a machine down
dx12 -> vulkan -> gl -> software rasterizer. The user is told their
driver is at fault the whole way.
Seen on this machine: a debug build died once while opening a large
drawing, and every launch afterwards reported "dx12 is not usable on
this GPU" on an Intel Iris Xe. Probing the backends directly showed
dx12 not merely usable but the best of the three
(max_storage_buffers_per_shader_stage 262144, against 59 for Vulkan
and 16 for GL). Clearing the stale sentinel brought dx12 straight back.
The failures this guard was built for kill the process at GPU init or
on the first drawing viewport, which is why arming it at all works. A
run that keeps drawing well past that has already shown the backend is
fine, so it now marks the sentinel `survived=1` after
SENTINEL_PROOF_DELAY, and a sentinel carrying that marker accuses
nobody. An early death still blacklists exactly as before.
Verified both ways on Windows 11 with an Intel Iris Xe: killed after
40s, the next launch still chose dx12; killed after 8s, the next launch
skipped dx12 and fell back to Vulkan.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`with_printer_devmode` sized the driver's DEVMODE with a
`DocumentPropertiesW` call that passed `DM_OUT_BUFFER` and no output
buffer to write into. That combination is not a size query: drivers
answer it with -1, the `needed <= 0` guard returned early, and the
function handed back `None` for every printer on every machine.
Measured here on Windows 11 x86-64, both an installed virtual printer
and a physical one:
fMode = 0 -> 5428 / 2684 bytes (the real size)
fMode = DM_OUT_BUFFER, NULL out -> -1
Two things were broken by it, both silently:
- `oriented_printer_devmode` builds the DEVMODE a print job is spooled
with. Getting `None` back, the direct GDI path fell through to
"CreateDC then falls back to the driver default", so the plot's
orientation and sheet never reached the job. A landscape plot came
out however the driver happened to be set. This is the route users
without a PDF application take.
- `PRINTERS <name>` could never name the driver's default sheet,
because the id it matches on comes from that same DEVMODE.
With the size query asking for a size, both work: the report now says
"Default sheet: ISO A4 (210 x 297 mm)" for both printers here, and a
landscape plot leaves `dmOrientation = DMORIENT_LANDSCAPE` set in the
job's DEVMODE.
The two new tests both fail with the old flag and pass with it removed.
The existing GDI ink tests do not catch this: they accept the raster
rotation fallback as an equally good outcome, so the page looked right
while the DEVMODE was empty.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- PDFOSNAP, DWFOSNAP and DGNOSNAP are separate; UOSNAP sets them all and
reads 2 while they differ. Enable Snap switches the selected kind's.
- DWFCLIP / DGNCLIP clip their own kind with the kind's prompts and message;
CLIP routes DWF and DGN underlays there; Enter at a corner asks again.
- The right-edge underlay tools show for DWF and DGN too (import is PDF
only).
- Underlay layers: DGN levels (V8 level table, "Default" listed as "0"; V7
used levels named from the level name table), hidden through the layer
override data with the DGN placeholder string first; a plotted DWF has
none.
- V8 colour read from its colour word (by level, index, or a true colour
drawn as its nearest index); 3D V8 elements drawn in plan (lines, line
strings, ellipses and arcs by their orientation, text); a model's extent
includes its text.
- DWF 6 TrueType text (font, height, rotation from the font opcode) and DWFx
glyph runs are drawn; the default W2D colour map is the measured one.
- Contrast pulls lightness towards a per-kind pivot as measured (PDF 0.5,
DWF 0.243, DGN 0.65).
- Zoom extents includes raster images and underlays whose frames are hidden.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Properties… in the Plot dialog froze the application on Windows.
`on_printer_properties` called `DocumentPropertiesW` with `DM_IN_PROMPT`
from inside the closure handed to `iced::window::run`, and iced runs that
closure synchronously on the winit event-loop thread. The driver's
property sheet wants to run its own modal message loop on that same
thread, so the two loops collide: the sheet is never created at all, the
window stops painting, and the thread spins at 100% of one core with no
way back.
Measured on Windows 11 x86-64: the pinned thread is the window's own UI
thread, and compstui.dll plus the driver's PrintConfig.dll are loaded
into the process, so execution does reach the driver's property-sheet
code and never leaves it. It reproduces with a physical printer as
readily as with Microsoft Print to PDF, so the mechanism was broken for
every printer, not only the virtual one named in the report.
The system's own printing-preferences UI is now started as a separate
process, which pumps its own messages and leaves ours free, so the
freeze is impossible by construction rather than merely unlikely. The
command that does it already existed for the case where no printer is
selected; it now serves a named printer too, and the in-process modal
path is gone. Preferences still reach the job: the sheet writes the
per-user DEVMODE that the plot path reads back through
`DocumentPropertiesW`, which was confirmed by changing the orientation
in the sheet and watching the value the plot path reads change with it.
The new test pins down that the printer name must reach `printui` as a
single argument: split across several it matches nothing and the process
exits 0 without drawing anything, which would be a failure with nothing
to show the user.
Fixes#1474
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#1513 added the field; this integration test's struct literal was not updated, so the test target no longer compiled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1511 added an orthogonal ellipse projection and a nearest-end
arc_parameter to draw/modify/geom.rs, the latter shadowing the kernel
function of the same name. Both now live in opencadkernel 237827e and
are re-exported here, so every kernel caller gets them too.
test_coincident_line_and_arc_grip_move only printed values and asserted
nothing; removed.
Pins opencadkernel 237827e, opencadgraph fe36957.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Frames: follow the drawing state, DWF/DGN frames, image frame profile, frame-only picking
The codec [patch] to ramox81/cadcodec@ea5edaa is dropped: that commit landed as opencadcodec#63 and main already pins ad16215, which contains it.
A page shown small was drawn from its full-size raster and thin lines broke
up into dots. Once a zoom settles on another quarter-octave step, PDF, DWF
and DGN underlays are rasterised again near their size on screen (never
above the full-size raster), frames are requested until that happens, and
the adjusted-pixel memo is kept per raster size. V7 element weights no longer
widen strokes, matching V8 models.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in the DWFFRAME/DGNFRAME header variables (codec #63) and robust 2D tangency plus ellipse-circle intersection (kernel #68). Pins opencadcodec ad16215, opencadkernel 1e02630, opencadgraph 7ef5ae4.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A transparent pixel wrote depth, hiding lines and objects under the image
that were drawn after it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DWFATTACH / -DWFATTACH and DGNATTACH / -DGNATTACH attach a DWF / DWFx sheet
or a DGN (V7 or V8) model with the reference's prompts; ATTACH routes the
file types to them. The sheet or model is read into vector paths, drawn as a
transparent underlay raster (contrast, fade, monochrome and background
adjustment apply) and offers its geometry to object snaps. Definitions are
kept in ACAD_DWFDEFINITIONS / ACAD_DGNDEFINITIONS, the External References
palette lists and reloads them, and image textures get line-keeping mip
levels so thin underlay lines stay visible when zoomed out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1506 paired each comment with a Chinese line; the codebase comments in English. Code and test data are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An image's transparency flag decides whether transparent pixels show what
is behind the image or draw in their stored colour: the image pass and PDF
plots now follow it (it was ignored, so every PNG alpha showed through).
TRANSPARENCY selects images and asks for the mode, defaulting to the first
image's current one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The Frames list shows the drawing's frame state (hide / display and plot /
display but not plot / frames vary), follows commands, undo and document
switches, and lists the mixed state as a disabled item.
- DWFFRAME and DGNFRAME are frame variables of their own, kept in the header,
and FRAME sets them with the others.
- Out-of-range frame values say "Requires an integer between 0 and 2." and
ask again; a set value reports "Regenerating model.".
- IMAGEFRAME is stored in the image variables as bits (2 is written as 3) and
a drawing without them uses the profile value, which setting IMAGEFRAME
updates and the settings file keeps.
- Raster images, PDF underlays and wipeouts are picked on their frame only;
underlay snap geometry is never picked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
opencadcodec a35f43e reads R13/R14 LAYER records as plottable, the root
cause #1507 worked around on load; drop the host-side correction. Its
tests stay and now cover the codec fix end to end. They wrote one temp
file per version and ran in parallel, so each test now gets its own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>