Resolve the gaps and parity-doc conflicts: keep this branch's re-audit
rows and history, fold in upstream's newer QSAVE and justification
changes, and recount the file tests (88) and catalogs (16).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Resolve the parity-doc conflicts: take upstream's header lines and newer
catalog rows, and keep this branch's re-audit history rows and the
re-audit line in each header.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
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>
* 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>
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>
SHX files referenced by text styles are found by file name through a
font map, registered bytes, an app provider, the drawing's folder and a
search path (CADCRAFT_SHXPATH); never in a CAD program's install folder.
TEXT, MTEXT, attributes, dimension text and table cells draw with the
style's font, big font and vertical flag; linetype shape elements are
drawn when their file is found. The web build registers .shx files
picked or dropped with a drawing. All test fonts are compiled in code
from shape source.
Plain MTEXT text decodes \U+XXXX escapes as the layout does, and an SHX
file whose name differs in case from the one asked for is found on
case-sensitive file systems too (the folder is looked through).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
-VPORTS saved, restored and deleted named model space viewport
configurations, and MVIEW Restore placed one in a layout, but View >
Viewports > Named Viewports... had no command. The new command
vports.named runs from the menu item. Typed or from the menu it opens
the Named Viewports dialog: the saved configurations, a preview of the
selected one's tiles, and in the Model tab the name of the configuration
whose tiles are where the Model tab's are, else *Active. Restore shows
the configuration in the Model tab, and in a layout it starts MVIEW
Restore with the name, which asks for the corners. Delete deletes the
saved configuration. The JSON form takes {name?, delete?, p1?, p2?,
layout?}, and without a name it returns the configurations and the
current one.
Catalog rows for the new menu label are added in all 15 languages. In
docs/gaps.md, U11 is narrowed, and F15, U11 and F21 no longer list MVIEW
Restore (#633) or PURGE of multiline styles, which are on main.
docs/parity-checklist.md is regenerated with cargo xtask parity.
Conflicts in docs/gaps.md and docs/target-app-parity.md resolved by keeping both
sides' log rows and headers; docs/parity-checklist.md taken from main (generated).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
DIMTFILL and DIMTFILLCLR were not modeled, so a dimension's text never had a
background and lines under it stayed visible. Dimension styles now carry both
variables. DIMTFILL 1 hides what is drawn under the text in the drawing's
background color, and DIMTFILL 2 fills the box in DIMTFILLCLR. The box is the
text box widened by DIMGAP on every side. The arc length symbol over the text
and the DIMINSPECT frame are drawn over the background.
The variables work with SETVAR, DIMOVERRIDE and the style fields. DXF stores
them as DIMSTYLE groups 69 and 70 from R2007 and in the style's CADCRAFT
xdata in older files; the reader skips the record's flags, which also use 70.
For DIMTFILL 2, the dimension's *D block and EXPLODE add a SOLID in
DIMTFILLCLR under the text. A dimension drawn from the *D block it was read
with gets a background around each of the block's texts, before the block's
first text or first segment of the text's marks, except for a text that a
SOLID of the block already covers. The background stays after the drawing is
saved and reopened.
Conflicts in file-format-parity, localization-parity, target-app-parity and
ui-parity resolved by starting from upstream and keeping only the audit
claims that still hold on main. Re-measured: catalog row counts and English
fallback counts for all fifteen catalogs, io test count (86), geometry test
counts, open PR and issue counts, acadrust version (0.6.5). Corrected rows
that main has overtaken: CI gate on pull requests (#1987), MVIEW Restore
(#633), PDF plot margins, selection cycling, Korean/Greek/Hungarian/Turkish
catalogs in the language table. Regenerated docs/parity-checklist.md with
cargo xtask parity.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
COMPAREEXPORT compares the two drawings again and opens the result as a
new untitled drawing, compare_<this> vs <other>.dwg. Model space holds
the other drawing's removed and changed objects as group
COMPARE_COMPARED and the compared tab's objects as group
COMPARE_CURRENT, in the overlay's colors: green for objects only in
this drawing or changed in it, red for the other drawing's, gray for
objects in both.
Block references, dimensions and multileaders refer to recolored copies
of their blocks, tables and tolerances use recolored copies of their
styles, and inline MTEXT and cell colors, dimension style colors,
multiline element colors and gradients follow the object. The new
drawing takes the layers and styles of the other drawing that this
drawing lacks, and the blocks its exported objects refer to; an
anonymous block whose name is taken is copied under a free name. The
comparison bar gets an Export button.
* appload: load a .lsp file from a path or the file picker (#1820)
APPLOAD had no user interface: typed or chosen from Tools > Load Application it
started a command-line prompt instead of a file browser, and the JSON form did
not say which commands the file defined.
- The desktop's APPLOAD opens an rfd file browser filtered to .lsp, starting in
the folder the last routine came from (kept in the preferences as lispDir).
A cancelled picker is a no-op; the web (no native dialog) keeps the engine's
name prompt.
- The JSON form `appload {path}` loads to the end, never opens a dialog and now
returns `commands`, the `c:` commands the file defined; a non-.lsp path is
refused and unreadable or unparsable files return an ordinary error.
- Tests: a synthetic .lsp in a temp folder loads by path and its command runs;
the picker path, its cancelled answer and the remembered folder; refused,
missing and broken files.
* appload: load a picked file interactively; keep path whitespace; web hint
Reviewer follow-ups on #1820:
- A picked file now loads through the interactive APPLOAD command (started
and answered with the picked path, as a typed name is), so a routine it
starts that calls getpoint or another get… waits for the user instead of
receiving nil. JSON calls keep the blocking run.
- A JSON `path` is read as given: only a path of blanks is refused, so a
relative name with leading or trailing spaces is not trimmed into another
file.
- The web has no file system, so APPLOAD no longer asks for a file name it
cannot read: it says to drop a .lsp file on the window, which loads the
file's contents. The host declares this through Services::no_file_system.
Tests: a picked file whose load asks for a point waits for it; a relative
path in a folder whose name starts with a space loads; on a host without a
file system APPLOAD gives the drop hint instead of prompting.
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Resolve doc conflicts in favour of upstream's newer rows; refresh open-PR count, file test count and catalog list.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Tools > Express Tools > Break-line Symbol draws one polyline from the first point to the second with a zigzag break symbol at a picked location (the midpoint on Enter), as AutoCAD's Express Tool does. Size scales the symbol (times DIMSCALE), Extension runs the line past both points, and Block takes a block of the drawing whose two points on the Defpoints layer mark where the line meets the symbol. The built-in symbol is our own geometry. One undo step; the options are remembered for the session.
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## 변경 내용
- entities 명령에 selected 불리언 필터를 추가해 현재 공간의 선택 객체만 조회
- 기존 종류·레이어·영역 필터와 결합하고 필터 적용 후 페이지 처리
- MCP query_entities 스키마와 명령·제어 프로토콜 문서에 옵션 공개
- 빈 선택, 중복·오래된 핸들, 다른 공간 객체, 잘못된 입력 및 조회 전후 상태 보존 회귀 테스트 추가
## 검증
- cargo xtask ci 6단계 통과: fmt, clippy, 테스트 2,012개, assets, layers, wasm
- 별도 .NET 클라이언트와 실제 헤드리스 엔진의 localhost 통합 검증 통과
- 실제 데스크톱 UI 조작 및 고객 DWG 왕복 검증은 수행하지 않음
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Selection cycling: a click over overlapping objects lists them, Shift+Space steps through them (fixes#1143, fixes#1145)
* canvas: keep viewport_content's doc comment on it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(render): keep filled highlight dash anchors stable
* outline test: as_chunks for clippy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(engine): support AUDITCTL system variable and .adt log generation (gaps F4)
* audit: write the .adt log only beside a saved drawing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Text, raster images, <use> copies, <style> sheets and rounded rectangle
corners aren't read yet. They were dropped without a word; the reader now
counts them and adds one read note (the channel DWG reading already uses),
which OPEN echoes and returns as a warning. Content that isn't drawn (in
<defs> or hidden) isn't counted.
A model space view carries a twist (radians CCW, View.twist, serde default
0). VIEWTWIST reports it read-only. Each VPORTS tile keeps its own twist
(VportTile.twist, DXF VPORT group 51 read and written; a single untiled
Model view's twist is kept as a lone *Active VPORT tile). VIEW Save stores
and Restore applies NamedView::twist. ZOOM fits in the twisted screen frame;
zooms, pans, the 3D mouse and view.set keep it; ZOOM Previous turns it back.
DVIEW starts with "Select objects or <use DVIEWBLOCK>:" (the picked objects,
or the DVIEWBLOCK sample, are the only things drawn while it runs) and
repeats the "Enter option [CAmera/TArget/Distance/POints/PAn/Zoom/
TWist/CLip/Hide/Off/Undo]:" prompt. TWist, PAn, Zoom, Off and Undo work on
2D views; the 3D options say they are not available yet (docs/gaps.md F1).
DVIEW works inside an active layout viewport: the doc Viewport gains a view
twist (DXF VIEWPORT group 51), drawn turned on screen and in plots, mapped
through MSPACE views, snaps and CHSPACE; a twist made there is one undo
step. A layout with no active viewport refuses it, as does view.set's twist.
Canvas: the model view and every VPORTS tile draw turned by their twist.
`Xf` gains `twist`: `to_screen` turns (p - centre) by it before scaling,
`to_world` is its exact inverse, `world_bounds` is the box of the four
turned rect corners. The GPU needs no shader change: `Xf::gpu_xform` builds
the callback xform for the drawing, drag, highlight, viewport and mask
layers. Pans map screen deltas back through the twist; clicks, hover, snaps,
grips and wheel zoom go through `to_world`/`to_screen`. Grid lines and axes
stay world-aligned; the selection window is drawn as the world box it
selects.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>