Bump acadrust to c5a579f: the DXF MULTILEADER reader now parses the
nested CONTEXT_DATA / LEADER / LEADER_LINE sections (leader lines and
text content used to come back empty, so DXF multileaders never
rendered), and the entity-level code map matches AutoCAD's real output
on both read and write (170 path type vs 172 content type).
Co-Authored-By: Claude Fable 5 <[email protected]>
Bump acadrust to 1e79519: the DXF reader now skips the R2018+
"101 / Embedded Object" section of MTEXT (and multiline ATTRIB/ATTDEF)
instead of letting its group codes overwrite the entity's already-parsed
insertion point, rotation, attachment and line spacing.
Closes#345
Co-Authored-By: Claude Fable 5 <[email protected]>
Follow-up to the LINE/POINT WCS fix - the same bug class elsewhere:
- 2D SOLID rendered its OCS corners raw in both the wire path and the
shared fill builder (solid_hatch_model); SHAPE placed its marker at
the raw OCS insertion. Both now map through the arbitrary axis.
- Grips: central wrap in view/dispatch.rs shows planar entities' grips
at their world position (OCS→WCS) and converts drags back (WCS→OCS
via the new wcs_point_to_ocs) - per-entity grip code stays in raw
field space, INSERT keeps handling its own OCS.
- Pulls acadrust 81ebfee: OCS-aware bounding boxes, translate,
transform and mirror for the ten planar entity types, so MOVE /
ROTATE / MIRROR and culling work on mirrored entities too.
Co-Authored-By: Claude Fable 5 <[email protected]>
wgpu/naga report pipeline and shader failures through the log facade,
then leave the canvas empty - with no logger installed on wasm the
message was lost, so a broken GPU path looked like "draws nothing" with
a clean console. Install a web logger that mirrors Error-level records
to the browser console and into a fixed DOM overlay with selectable
text, a Copy button and repeat-collapsing; panics land in the same
banner via a chained hook. Windows Chrome/Edge reporters can now paste
the exact ANGLE/D3D11 error instead of a screenshot of a blank canvas.
Co-Authored-By: Claude Fable 5 <[email protected]>
Bumps acadrust to 1b0a362: block headers no longer list handles of
deleted entities, so DWG saves from a session that removed entities
open with full content in TrueView/AutoCAD instead of empty.
Co-Authored-By: Claude Fable 5 <[email protected]>
OLE2FRAME entities whose compound file carries a metafile presentation
(Excel/Word previews, scanned WMF pages) drew only their border frame —
the old decoder scanned the raw blob for a contiguous BMP, which the
CFB sector layout almost never provides. acadrust now extracts the
picture bytes tagged by kind; the new scene/model/gdi player rasterizes
EMF and WMF record streams on the CPU (pens/brushes, polygons, paths,
DIB blits, clipping, transforms) with text drawn through the existing
system-font glyph cache, and image_model feeds the result into the
raster pipeline. Rasters (BMP/PNG/JPEG/GIF, CF_DIB) decode as before
via the image crate.
Co-Authored-By: Claude Fable 5 <[email protected]>
Section marks and drawing-view borders are now real acadrust entity
types instead of Unknown-with-extras, so the renderer dispatches on the
variant directly, the arrow-direction resolver reads the active viewport
off the ViewBorder entity, and selection / properties show "Section
Symbol" and "View Border" instead of "Unknown". View borders are
non-plotting and tessellate to nothing; both count toward the lossy
Save-As warning since they round-trip via their raw records.
Bumps acadrust for the entity promotion.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The section mark's appearance now comes entirely from file data instead
of invented conventions:
- Arrow direction: resolved through the drawing-view graph — the
symbol's parent AcDbViewRep, the section view (owner of the section
definition), each view border's active viewport — by projecting the
section camera's sight onto the parent camera's basis, using the same
yaw/pitch/twist convention the viewport renderer does. Only when the
chain is unavailable (DXF, older files) does a geometric fallback
apply.
- Broken cutting line: driven by the style's plane-line / end-segment
flags rather than hard-coded.
- Arrowhead: resolved through the shared dimension/leader arrow table
from the style's arrow block handle; a null handle gives the standard
ClosedFilled default.
- Label gap: the style's identifier offset.
Bumps acadrust for the style and view-graph decode.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Draw decoded section symbols (AcDbSectionSymbol) as their "A-A" cut mark:
the cut line through both endpoints extended past each end by its signed
tick, a short perpendicular barb at each tip, and the identifier glyph.
The mark now appears on the layout alongside the drawing views instead
of being silently dropped.
Bumps acadrust to pick up the section-symbol decode.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Re-evaluate AcDbField-driven MTEXT — date/login/document-property fields, table
formulas and object properties — against the current system instead of showing
the frozen last-save cache. The evaluation engine lives in `acadrust::fields`;
OCS supplies only the environment (system clock, OS login, env vars) through a
FieldContext implementation, and hooks the resolved text into MTEXT rendering,
falling back to the cached value for anything it can't evaluate.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Lights, camera views and the geographic-location marker had no on-screen
representation. Add display glyphs for all three:
- Lights render through a new EntityType::Light: a cone/flashlight for spot
lights, a wire sphere for point lights, a sun for distant lights, sized in
screen space (fixed-world fallback).
- Camera views (perspective VIEW records) and the GEODATA "daisy" marker are
synthesized into the model-space resident wire set from the document, since
they are not entities.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The editor preview mis-sized imported MTEXT badly (tiny, huge, or
collapsed). Two root causes:
- The entity's base height often isn't the visible text height: relative
`\H…x;` codes compound, so an entity of height 1 whose body is `\H0.2x`
renders at 0.2. Normalize the preview scale by the DOMINANT rendered run
height (the mode of glyph-box heights, skipping zero-width caret slots),
not `height_value()`, so the body lands at a fixed readable size and
headings keep their proportions. EM_PX = 15.
- The bug that made it "completely wrong" was in the serializer, fixed in
acadrust 389b31a (\H heights decayed on the parse→serialize→parse the
editor does via folded_value); bumped here.
Also render multi-column MTEXT with its columns side by side (as the
drawing does) and let the preview scroll horizontally to reach them.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up the ezdxf-audited MTEXT parser fixes: raw LF as a paragraph
break, control chars rendered as spaces, and the corrected `\c`
true-color byte order (so `\c` colors no longer come out red/blue
swapped).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Two defects in tabbed fields inside a multi-column MText:
- Stop positions are relative to the paragraph's own left edge, but the
tab logic compared them against the column-absolute `cursor_x`. In a
second column `cursor_x` already carries the column offset, so no stop
ever matched and the field shot off to the default 4-em grid, way past
the page. Measure against the column's `box_left` instead.
- A field after a center/right/decimal tab aligns on the stop, reaching
only part of its width to the right, but word-wrap flushed it left and
wrapped it off the line by its full width — dropping a wide decimal
number onto a fresh, un-tabbed line. Don't wrap the field that follows
an aligning tab.
Picks up acadrust b16137f (decimal stop position parse).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
A `\t` reaching a center, right, or decimal (`D`) tab stop now aligns the
field that follows it — the run of words up to the next space/tab — instead
of just advancing the pen:
- decimal: the field's first `.` lands on the stop (a column of numbers
aligns on the decimal point; a field with no `.` aligns its end),
- right: the field's end lands on the stop,
- center: its middle.
The stop wins even when the field is wider than the room before it, so the
dot/edge stays put and the field overruns to the left, keeping the column
aligned. Left stops and the default 4-em grid are unchanged. Picks up
acadrust 162f194, which carries the tab-stop kinds.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
`qj`/`qd` were stubbed to left. Now the layout fills the line to the
content width:
- Distribute (`qd`, and headings that reset with `q*` → justify) shares
the slack across every glyph gap — word gaps widen and letters spread
via tracking (LFF stroke fonts; TTF with zero letter-spacing spread
their word gaps only). Every line, including the paragraph's last.
- Justify spreads only the word gaps and leaves the last line ragged.
Bumps acadrust to 504281a, which parses `\pqd` as Distributed and
`\pq*` as Justified so these alignments reach the layout at all.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
An IMAGE whose file can't be opened (a URL, or a missing/renamed file) now
draws its clip/frame outline plus the saved path as centred text in the
image colour — AutoCAD's broken-reference placeholder — instead of an empty
frame. OCS never fetches remote paths. Bumps acadrust so the entity's path
is populated from its ImageDefinition.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up the ATTDEF flags/geometry fix so a CONSTANT block attribute
renders instead of being skipped as a template.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
A CONSTANT ATTDEF has no per-insert ATTRIB — its value belongs to the block
itself — so block expansion must draw it instead of skipping every ATTDEF.
Non-constant templates are still skipped (the insert supplies their ATTRIB).
Also bumps acadrust to decode the embedded MTEXT of R2018 multiline
attributes, so a value like "A\PB" renders both lines.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up the ATTRIB flags/generation/field-length/lock fix so an
attribute tagged invisible is no longer drawn (ATTMODE 1).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Pulls the acadrust fix that decides the R2013 has_ds bit for MULTILEADER by
peeking the class_version, so a MULTILEADER whose writer emits the bit
(budweiser handle 9821) decodes its leader roots / arrowhead / content instead
of an empty context. The leader now renders.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
A Table whose cells are baked into a *T block (block_record_handle) was rendered
by tessellating the block's sub-entities directly. Those are laid out in
block-local space (origin at the table's top-left corner) — the Table entity
carries the world placement in insertion_point + horizontal_direction, exactly
like an INSERT — so the whole table drew at the world origin instead of its
location.
Each baked sub-entity is now cloned and placed (rotated about the local origin
by the horizontal_direction angle, then translated by insertion_point) before
tessellation, so tessellate_entity produces correctly located, relative-to-eye
geometry. Verified on budweiser handle 9378: its baked lines move from (0,0) to
the insertion point (-1200018.7, -800071.4).
Also bumps acadrust to pull the OLE2FRAME corner-decode fix, which places
OLE2FRAME entities (e.g. handle 3088) at their real corners instead of the
(1,1)/(0,0) defaults.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Adds SatIntCurve (nubs B-spline parse + De Boor sampler, plus sample_range
for an edge's own arc), so intcurve-curve spline edges decode to real
geometry instead of nothing.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The MTEXT parser turned `\N` into a plain paragraph, identical to `\P`, so
a multi-column MTEXT arrived with nothing left to lay columns out from —
and the writer sent every break back as `\P`, collapsing the columns for
good on round-trip. `MTextParagraph::starts_column` now carries it.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Pulls acadrust 769741d: the classes reader never derived is_an_entity from
item_class_id, so the flag was false for every class and any class-based entity
without an explicit type mapping was decoded as an object and dropped. Drawings
carrying an application's custom entity silently lost it.
Surfaces such entities as EntityType::Unknown with their raw record and proxy
graphics, so the renderer can fall back to the cached outline the way AutoCAD
does for an object whose enabler is absent.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Pulls acadrust dd4a4dc: the R2013+ has_ds bit was skipped for any entity
carrying preview graphics, which desynced every preview-bearing IMAGE and
WIPEOUT — an IMAGE's imagedef handle decoded one off, so the IMAGEDEF lookup
missed, the file path resolved to nothing and the linked image silently
disappeared. Regression since v0.8.1 (the has_ds gate landed in 208bb09).
The skip is now narrowed to MULTILEADER, the one type actually observed to
omit the bit; IMAGE, WIPEOUT and MULTILEADER all decode correctly.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Linetypes converted from MicroStation DGN keep their pattern in DGN line-style
objects (empty standard LTYPE), so entities using them drew as a plain line and
lost the symbols (e.g. a pipe's end circles). Walk the line-style tree
(resolved by name to its LSDefinition), collect the symbol components' anonymous
blocks, and draw each at the host polyline's endpoints, scaled by the symbol's
decoded scale (geometry / scale) so it matches the drawing (verified: a 0.75
ellipse renders at the file's intended 0.375 radius).
Bumps acadrust to 8e18c6b (DGN line-style symbol-scale decode). First pass: the
stroke dash pattern and exact per-vertex placement need more of the line-style
leaf decoded; the base line still draws solid.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up acadrust 6508b76: reads DGN line-style objects (AcDbLS*) into the
document's dgn_ls_definitions / dgn_ls_components tables. No OCS code consumes
them yet — that lands with the linetype linkage and renderer.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Multilines were drawn with a fixed ±scale/2 two-line guess in the entity
colour, ignoring the MLINESTYLE entirely, so a drawing's custom style (per-
element offsets, colours and linetypes) was lost — a red/yellow multiline
rendered as a white box.
- mline.rs: resolve the MLINESTYLE (by style_handle, then name) and build one
parallel line per element from its offset x scale + justification shift.
- tessellate.rs: special-case MLINE (like Leader) to emit one WireModel per
element in the element's own colour, CPU-dashing every element through
apply_along so the parallel lines stay in phase.
- linetypes.rs: render a drawing's OWN complex linetypes (embedded text/shape),
document definition first and the bundled .lin catalog only as a fallback, so
a file-defined text linetype like PLYN shows its text.
- Run the dash/glyph layout in a local frame (f64 origin subtracted, re-split to
double-single after) so spacing stays precise at UTM coordinates, and pass
tracking = 1.0 so embedded text keeps its letter spacing.
Cargo.lock pins acadrust to the MLINE->MLINESTYLE handle-link reader fix.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Point the acadrust patch at the OpenAEC-Foundation/acadifc fork (still the
`acadrust` crate). Its main carries the Arc copy-on-write entity storage that
makes the undo document clone O(entities) refcount bumps instead of a full deep
copy — cutting the per-edit snapshot on a 788k-entity drawing from ~1.7s to
~70ms. No source changes here: acadrust`s public API is unchanged.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up the DXF fix that reads DIMENSION group code 2, so dimensions
imported from DXF keep their baked *D block and render (their text no
longer drifts vs the DWG of the same drawing).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up the DXF over-annotative MULTILEADER fix (companion to the MTEXT
one): enable_annotation_scale now defaults false and DXF reads code 293.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up the DXF over-annotative-MTEXT fix: acadrust now defaults
MTEXT.is_annotative to false, so imported DXF MTEXT is no longer flagged
annotative and over-scaled in annotation-scaled viewports.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Make objects genuinely annotative — carrying real per-scale
representations that interoperate with other CAD apps — rather than just
a native flag. `create_annotation_context` synthesizes the extension-dict
chain (AcDbContextDataManager -> ACDB_ANNOTATIONSCALES -> per-scale leaf)
from the entity's placement; the editable Annotative toggle now covers
Text and block references as well as MText/MLeader; and a new
"Annotation Object Scale" dialog (OBJECTSCALE) adds/removes an object's
per-scale memberships. Requires the acadrust ObjectContextData encoder
(Cargo.lock bump).
Also fixes a render bug where objects carrying an *empty*
ACDB_ANNOTATIONSCALES (a single-representation marker with no per-scale
reps) were treated as annotative and (mis)scaled by the annotation factor
in scaled paper viewports, ballooning the text: an object is now
annotative-by-context only when its scale collection is non-empty, so
such objects render at their base geometry.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The "Dim line color" row on Leader and Dimension entities was
read-only: an earlier attempt wired it to Leader.override_color, which
acadrust never serialises, so the pick was lost on save. Store it
instead as a standard ACAD_DSTYLE per-object dimension-style override
(DXF code 176, an ACI index) through the existing dim_override codec,
so it round-trips through both DWG and DXF like the other dim
overrides. RGB picks collapse to the nearest ACI, matching the rest of
the dim-colour stack (dimension styles are index-only through the file
layer). The renderer prefers the override over the style's DIMCLRD.
The write branch is guarded to leaders and dimensions so a mixed
selection cannot stamp the override onto other entity types.
Bumps acadrust to c9fe982, which carries parsed XDATA onto dimensions
on DXF read (it was dropping common.extended_data), so the dimension
override persists on DXF save as well as DWG.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Pulls the acadrust fix that emits XDATA for every entity on DXF save (not
just hatches), so the leader dimension overrides and hyperlinks now
round-trip through DXF as well as DWG.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Picks up the DWG reader reflecting CANNOSCALE from the AcDbVariableDictionary
into the header, so the status-bar annotation-scale pill shows the drawing's
real model-space scale (e.g. 1:70) instead of the "1:1" default.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Resolve, per selected entity, whether it is annotative (from its text /
dimension / multileader style, or its own flag) and — when annotative — the
name(s) of the annotation scale(s) applied to it, shown as a read-only
"Annotative scale" row (Text / MText / Leader / MLeader).
The applied scale is read from the entity's per-scale object-context leaves
via the new acadrust CadDocument.context_scales map (context leaf ->
AcDbScale handle), walked from the entity's extension dictionary
(AcDbContextDataManager -> ACDB_ANNOTATIONSCALES). Bumps acadrust to pick up
that parsing.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Pulls acadrust 4ac3d68: entities with proxy/preview vector graphics
(MULTILEADER, WIPEOUT) omit the R2013+ has_ds_data bit, so reading it
desynced the record and produced garbage MultiLeader text_location
(~2e39 → NaN glyphs). The labels now parse with finite locations and
render through the existing MText SDF path.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
First real Windows build surfaced errors that a Linux host couldn't catch:
* Enable the missing `windows` feature gates (Win32_System_LibraryLoader,
Win32_System_SystemServices, Win32_Security — the last brings in the
`Ex` registry APIs) so the imports resolve.
* Depend on `windows-core`: the `#[implement]` macro expands to
`windows_core::` paths, which need the crate nameable in the root.
* `IClassFactory::LockServer` takes `Win32::Foundation::BOOL`, not a
`core` BOOL.
* Name the returned image type via a new `dwg_thumbnailer::RgbaImage`
re-export instead of a direct `image` dependency.
Verified with `cargo check --target x86_64-pc-windows-gnu -p
dwg-thumbnailer-win` (and the native check still passes).
Co-Authored-By: Claude Opus 4.8 <[email protected]>