* Multiline attributes: read, draw and save their text
A multiline attribute (DXF attribute type 2, or 4 for a definition) has its
text as embedded MTEXT after its own groups (`101 Embedded Object`); its own
group 1 is empty. CADCraft read only the own groups, so the attribute drew
nothing, and a save wrote it back empty: its text was lost.
- `Attrib::multiline` keeps the multiline text; `text.value` holds its plain
text, which ATTEDIT and the other value editors change; an edited value
replaces the contents (`Attrib::multiline_text`).
- DXF read: ATTRIB and ATTDEF split at the marker; the MTEXT parsing is
shared with MTEXT entities (`mtext_from`).
- Drawn as multiline text; ZOOM Extents counts it.
- DXF write (2007 and later; earlier versions get one line): attribute type,
alignment point and the embedded MTEXT, only what differs from unrotated
text, as AutoCAD writes it.
- INSERT and ATTSYNC give references the definition's multiline text placed
with them; MOVE/ROTATE/SCALE, Properties rotation and scale, annotative
scaling and FLATTEN carry it.
- Tests: synthetic multiline ATTDEF and ATTRIB (read, drawn, saved, edited,
pre-2007 save, damaged embedded groups); engine INSERT, MOVE, ATTEDIT and
ATTSYNC.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Multiline attributes: read MTEXT direction from its own groups (#667, as #834 does)
#834 moves these lines' fix into the MTEXT reader; the same fix in the shared
mtext_from keeps the two compatible.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Attributes keep Verify, Preset and Lock position
ATTDEF/ATTRIB flags 4 (verify) and 8 (preset) and Lock position (group 280
after the tag, DXF 2007 and later) were dropped on save. Without Lock
position AutoCAD lets an attribute be dragged out of its reference, and its
dynamic block actions no longer carry it. A reference's attributes take Lock
position from their definitions, as AutoCAD saves them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Multiline attributes: read, draw and save their text
A multiline attribute (DXF attribute type 2, or 4 for a definition) has its
text as embedded MTEXT after its own groups (`101 Embedded Object`); its own
group 1 is empty. CADCraft read only the own groups, so the attribute drew
nothing, and a save wrote it back empty: its text was lost.
- `Attrib::multiline` keeps the multiline text; `text.value` holds its plain
text, which ATTEDIT and the other value editors change; an edited value
replaces the contents (`Attrib::multiline_text`).
- DXF read: ATTRIB and ATTDEF split at the marker; the MTEXT parsing is
shared with MTEXT entities (`mtext_from`).
- Drawn as multiline text; ZOOM Extents counts it.
- DXF write (2007 and later; earlier versions get one line): attribute type,
alignment point and the embedded MTEXT, only what differs from unrotated
text, as AutoCAD writes it.
- INSERT and ATTSYNC give references the definition's multiline text placed
with them; MOVE/ROTATE/SCALE, Properties rotation and scale, annotative
scaling and FLATTEN carry it.
- Tests: synthetic multiline ATTDEF and ATTRIB (read, drawn, saved, edited,
pre-2007 save, damaged embedded groups); engine INSERT, MOVE, ATTEDIT and
ATTSYNC.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Multiline attributes: read MTEXT direction from its own groups (#667, as #834 does)
#834 moves these lines' fix into the MTEXT reader; the same fix in the shared
mtext_from keeps the two compatible.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* doc: Space::is_paper/layout/tab_name helpers replace hand-written matches
Twenty-seven call sites in 15 files across engine, io and ui-egui matched Space by hand to get
"is this a layout", "which layout" or "Model or the layout's name". Route them
through three small helpers on Space instead. No behaviour change.
This also makes adding a space kind a few-file change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* doc: keep Space::Model comparisons that no helper shortens; test the helpers
Only the sites that repeated the same match (tab name, layout name,
paper lineweights) go through the helpers; plain Model comparisons and
plot_window's match on (space, plotArea) stay as they were.
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>
The options at MTEXT's "Specify opposite corner" prompt printed "not
available yet". Each now asks its question and returns to the corner
prompt: Height (also sets TEXTSIZE), Justify (TL..BR, the insertion point
is the box's attachment point), Line spacing (At least/Exactly, then a
factor such as 1.5x or a distance), Rotation (picked, or typed through the
drawing's angle settings; the box turns with it), Style (? lists them),
Width (replaces the opposite corner) and Columns (No; Dynamic and Static
say columns are not available yet). MText stores the line spacing style
(DXF group 73) so Exactly round-trips.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
`Attrib` gains optional per-attribute properties (`props`), each overriding
the attribute definition's. DXF reading takes them from the ATTRIB's groups
8/6/62/420/370; writing gives each ATTRIB the properties it is drawn with.
The renderer prefers them over the definition's. -ATTEDIT's Layer and Color
options set them; ATTSYNC resets them to the definitions, as in AutoCAD.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Extents: ignore rays and references to missing or empty blocks, as ZOOM Extents does
Opening real drawings in CADCraft often showed a tiny plan in a huge empty
canvas, because the extents included things that draw nothing:
- the base point of a RAY (Autodesk's own reference says infinite
construction lines and rays do not affect ZOOM Extents; an office plan in
our corpus carries two rays 1.98 million units from the building);
- the insertion point of an INSERT whose block is missing (a purged
definition, a bound xref that never came along) or empty (an unloaded
xref): a floor plan had such references 125 000 and 3.4 million units away.
XLINEs were already ignored; rays now are too, and an insert contributes only
what its block draws (attributes still count). Two regression tests use the
measured coordinates.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Extents: skip invisible block entities, attdefs and blank texts
- Entities in a block definition count for an insert's (and a dimension
block's) extents only if they are not AttDefs, have common.visible set,
and sit on layer "0" or on a layer that is on and thawed. Dynamic blocks
keep hidden constraint geometry far from the visible part.
- Text/MText that is empty, whitespace-only or only "\~" has empty bounds.
- Tests cover each rule separately.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Polyline extents were the centre line padded by const_width / 2, so
per-segment start/end widths never counted: a band built from vertex
widths, a taper, or segments of different widths reported the
zero-height bounds of the centre line. The bounds now enclose the
filled band of every segment as it is drawn: the exact corners of
straight segments (tapers included), and both edges of arc segments,
sampled along the arc with the width interpolated and widened by the
sampling tolerance so they are never too small. The constant width
still wins over vertex widths, the end vertex of an open polyline
starts no segment, and non-finite or negative widths count as zero.
Thin polylines take the same path as before.
Fixes#90.