Commit Graph
1485 Commits
Author SHA1 Message Date
ramox81andClaude Opus 5.5 ac9a6b07b9 Point clouds: POINTCLOUDMANAGER palette
A dockable Point Cloud Manager lists each point cloud of the drawing (only
the selected ones while any is selected) with Regions (disabled, region
data is not read), Unassigned Points and Scans, the scans named by their
file stems. Each switch shows or hides points: the cloud, its unassigned
points, all scans or one scan. The hidden set is the cloud's
OCS_POINTCLOUD_VISIBILITY extended data (scan names plus *CLOUD_OFF /
*UNASSIGNED_OFF markers, app id registered), written as one undo step and
kept on save. The drawn points skip hidden scans by their index ranges,
and the hidden set is part of the placed-cloud key. Collapse all / expand
all, row highlight and a search box that filters rows (keeping parents of
matches). POINTCLOUDMANAGERCLOSE closes it; the pc_manager_toggle
automation action flips a switch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 13:25:22 +03:00
ramox81andClaude Opus 5.5 2e23a903a4 Point clouds: crops along the view, POINTCLOUDUNCROP, POINTCLOUDLOD
A crop is drawn on the view plane: it keeps the view's right and up
directions in the cloud's coordinates and its points in 3D, and cuts
along the view. POINTCLOUDUNCROP removes a picked cloud's crops.
POINTCLOUDLOD scales the points shown in tenths.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 11:50:26 +03:00
ramox81andClaude Opus 5.5 da25c45fdd Point clouds: normal stylization colours, project rotations in degrees
Scan normals are decoded from their cube-map codes and drawn as world
normal colours under the Normals stylization; project and scan rotation
angles are read as degrees.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 11:19:35 +03:00
ramox81andClaude Opus 5.5 8fd993f016 Point clouds: colour schemes run from their high end
A scheme lists its colours from the highest value down (Spectrum:
magenta at the highest intensity, red at the lowest), as the reference
colours an intensity- or elevation-stylized cloud.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 10:25:44 +03:00
ramox81andClaude Opus 5.5 c2d9ac5ae2 Point clouds: attach dialog, crop toolbar, stylize, palette rows
POINTCLOUDATTACH opens the Attach Point Cloud dialog after the file is
chosen; its Attach button lives in the Attach Underlay list instead of a
separate Insert panel. A selected cloud brings the crop tools to the
right-edge toolbar. POINTCLOUDSTYLIZE sets the stylization with the
reference's prompts, the External References palette lists point clouds
(unload, reload, detach, path), and definitions keep the header extents.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 10:14:44 +03:00
ramox81 3afd547e28 Merge remote-tracking branch 'origin/main' into codex/pointcloud-attach
# Conflicts:
#	Cargo.lock
2026-09-30 09:15:26 +03:00
Hakan SevenandClaude Opus 5.5 8022e25c08 fix(dgn): a short 2D text element no longer panics the reader
The byte count at 110 was read with direct indexing; a truncated element
now skips like every other field read does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 23:11:33 +03:00
Hakan Seven 232ce26105 Merge pull request #1539 from ramox81/underlay-vector
DWF/DGN underlays: vector drawing, global origin, stored extents, colour table display and 3D cells
2026-09-29 23:08:46 +03:00
Hakan SevenandClaude Opus 5.5 69a2e7c73a fix(ellipse): #1532 follow-up — one transform, in the codec
The PR's principal-axis math now lives in the codec's transform_ellipse
(8464e0a), which explode, INSERT and every other codec path share.
transform_ellipse_geometry delegates to it for the block-cache tangent,
and the entity goes back through apply_standard_entity_transform, with
MIRROR delegated to the codec's apply_mirror: the old closure reflected
only the centre and major axis, leaving mirrored arcs on the wrong side,
and the PR's version turned the normal to -Z. The mirror test now checks
the kept +Z normal and the negated parameters.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 23:04:23 +03:00
Hakan Seven df8ea089d7 Merge pull request #1532 from yztink/fix/ellipse-block-transform
fix(ellipse): accurately transform ellipse and elliptical arcs in blocks and standard transforms
2026-09-29 22:58:23 +03:00
ramox81andClaude Opus 5.5 e9c4e501db Point clouds: drawn from their scans, placed, cropped and attached as the reference does
Scans (.rcs) and projects (.rcp) are read and their points drawn as
screen-sized dots, coloured by the cloud's stylization. The cloud's
placement carries its scale and rotation; its extents and crops stay in
the scan's coordinates. A missing scan shows the extents with the saved
path. -POINTCLOUDATTACH / POINTCLOUDATTACH, POINTCLOUDCROP and the
POINTCLOUD* settings follow the reference's prompts and messages, the
Properties list is the reference's, and a locked cloud is left alone by
edits.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 17:08:46 +03:00
Hakan SevenandClaude Opus 5.5 ea91315ba8 fix(layers): turning layers on no longer re-places associative dimensions
Layer, text-style, dimension-style and object-style invalidation bumped
every dependent entity as Modified, which also re-resolved associative
dimensions, centre marks and hatches and re-ran the parametric solve.
A dimension whose association disagrees with its own points (as older
saves can) jumped its dimension line on LAYON. A restyle moves no
geometry, so it now refreshes display only.

Fixes #1536

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 14:16:07 +03:00
Hakan SevenandClaude Opus 5.5 e682f29ce6 fix(render): block text no longer hides behind its own background box
Inside a block, text-bearing and wide wires got their child rank as a
depth override, but fill-only wires stayed at the bare insert level. A
dimension's baked MTEXT with a DIMTFILL background therefore drew its
box in front of its own text whenever the text's rank fell below zero:
cyan boxes with no numbers. Fill-only wires now take the rank as well,
so a background ties with its text and the text pass wins.

Refs #774

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 14:01:56 +03:00
ramox81andClaude Opus 5.5 507a6ab43c DWF/DGN underlays: draw content as vector wires
A DWF sheet or DGN model is drawn as world-space wires (one line wire per
colour and width, one fill wire per colour) instead of a raster rescaled
to the view, so it stays sharp while zooming instead of showing pixels
until the raster is made again. Colours go through the colour table
mapping, contrast, fade and monochrome; clip boundaries clip the wires.
The wires are drawn and plotted but neither picked nor snapped; the
underlay's own snap geometry still serves object snaps.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 12:43:20 +03:00
ramox81andClaude Opus 5.5 be023142de DWF/DGN underlays: anti-alias slanted and curved hairlines
One-pixel hairlines keep horizontal and vertical pieces solid, but
slanted pieces and curves are anti-aliased: their pixel steps broke up
into dashes once the raster was scaled to the screen.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 12:20:27 +03:00
ramox81andClaude Opus 5.5 f7106c7d30 DGN underlays: global origin, stored extents, colour table display, 3D cells
- V8 models are placed relative to their global origin (model header).
- A V8 model's extent is the union of its elements' stored ranges; a V7
  model's text box is one text height tall.
- Files without a colour table use the standard DGN default table; colour
  255 is read from the table's background entry.
- Colours from a file's colour table follow the background: near-white
  colours swap with it, and over non-black backgrounds some shades drop a
  step.
- DGN contrast pulls towards a pivot taken from the model's own colours,
  after the fade, which is blended into the background first.
- Shared cells are read through their full 3D placement, so tilted
  instances and 3D definitions are drawn in plan.
- Deleted V8 elements are skipped; lines along the model's extent stay in
  the raster.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 11:58:47 +03:00
Hakan SevenandClaude Opus 5.5 60f35e2b1d fix(color): only colour 7 swaps with the background; true colours draw as authored
Every near-white colour turned black on a light background (and near-black
white on a dark one), including true colours. A 255,255,255 solid used as a
white mask became a black block. Now only colour 7 swaps: true colours and
ACI 255 resolve a hair off pure white/black and keep their value on screen
and in plots.

Discussion #1500

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 06:16:18 +03:00
yztink a35fc949f3 fix(ellipse): accurately transform ellipse and elliptical arcs in blocks and standard transforms
- Add transform_ellipse_geometry helper in scene::view::transform to compute exact principal semi-axes, normal, ratio, and shifted arc parameters under any affine transform (negative scales, reflections, negative rotations, non-uniform scaling, and translations).
- Use transform_ellipse_geometry in block_cache::transform_tangent for TangentGeom::PlanarEllipse so GPU analytical instances and curve endpoints match true WCS positions.
- Update entities::ellipse::apply_transform to use transform_ellipse_geometry for complete scaling, rotation, mirroring, and affine transformations.
- Clean up tangent parameters in to_render for Ellipse so start_param and end_param are consistently unwrapped.
- Add comprehensive unit tests in transform.rs, block_cache.rs, and ellipse.rs verifying negative rotations, negative scales, and distant origins.
2026-09-28 16:09:41 -07:00
Karim Jerbi fdbbcc419e perf(flatten): pre-sized collect/plan and batched entity publish
flatten_plan 2,289 -> 1,098-1,144 us (-50..-52%); flatten_scene_apply 1,213 -> 789-813 us (-33..-35% vs baseline; -28.5% same-session O2-vs-O1, drift-corrected).

Pre-sizes collect/plan vectors and adds Scene::update_entities so FLATTEN issues one geometry bump per batch instead of per entity; single update_entity keeps its exact bump-per-call semantics.
2026-09-28 20:29:40 +01:00
Karim Jerbi f4dfead9c0 test(flatten): add golden, filter, invariant, and differential regression tests
11 tests in tests/flatten_regression.rs: projection goldens (line/circle/polyline3d/polyline2d/text/solid), None cases, locked-layer/selection/space collection filters, plan/apply invariants, legacy-loop differential. Adds 2 ring-depth tests in src/scene/mod.rs pinning update_entities' collapsed block-sentinel delta (legacy 2 vs batch 1, final-state equality).
2026-09-28 20:29:39 +01:00
Hakan SevenandClaude Opus 5.5 51d26eb81f fix(plot): XCLIP also clips block hatches plotted through a viewport
Follow-up to 0bfd5dcc:
- A clipped block hatch kept its unclipped plane-local outline, which the
  viewport plot projection prefers, so fills bled past the XCLIP boundary
  on layouts. Rebuild it from the clipped outline.
- insert_spatial_filter / filter_handle run for every INSERT in each
  render walk; resolve the xdictionary through the entity link or the
  document index only, and leave the whole-object scan to set_insert_clip.

Fixes #1508

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 21:28:57 +03:00
Hakan SevenandClaude Opus 5.5 3754426361 fix(paste): pasted associative hatches follow the pasted boundary
Paste (and WBLOCK, which shares the kernel) kept the source boundary
handles, so the pasted hatch stayed tied to the original outline or to
unrelated handles in another drawing. The COPY remap now lives at the
document level and runs for both.

Refs #1370

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:33:54 +03:00
Hakan SevenandClaude Opus 5.5 b66b5100bd fix(annotative): MOVE/ROTATE/SCALE carry every scale representation; copies get their own
Only the displayed annotation context followed a transform, so other
scales reappeared at the old place, and a copied annotative entity other
than a LEADER/MTEXT pair shared the source's context tree.

Fixes #700

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 19:27:31 +03:00
Hakan SevenandClaude Opus 5.5 d1a6187678 fix(copy): copied raster images, OLE frames and underlays draw their picture
COPY added the entity without its derived image model, so only the frame
appeared at the copy.

Fixes #829

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 19:13:45 +03:00
Hakan SevenandClaude Opus 5.5 38fe2b0b08 fix(plot): text and leader background masks plot paper-white, not black
The mask is filled with the canvas colour; plotting carried that dark
colour (or the light-to-black rule) onto the sheet.

Fixes #1072

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 19:01:56 +03:00
Hakan SevenandClaude Opus 5.5 805979ea36 fix(dimension): custom arrow blocks keep their polyline width
The width of a wide polyline lives on the wire as a GPU band, which the
custom-arrow extraction dropped, so the arrow drew as a hairline.

Fixes #1130

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 18:49:26 +03:00
Hakan SevenandClaude Opus 5.5 05502aac63 fix(move): dimensions with a baked block redraw where they were moved
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 <[email protected]>
2026-09-28 18:45:34 +03:00
Hakan SevenandClaude Opus 5.5 3b2dd8dcb5 fix(plot): top-level hatches plot at their draw-order depth
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 <[email protected]>
2026-09-28 18:39:20 +03:00
Hakan SevenandClaude Opus 5.5 1091168196 fix(copy): copied associative hatches follow the copied boundary
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 <[email protected]>
2026-09-28 18:34:52 +03:00
Hakan SevenandClaude Opus 5.5 b365e51620 fix(image): new image definitions allocate their own handle so DWG keeps them
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 <[email protected]>
2026-09-28 18:24:38 +03:00
Karim Jerbi 0bfd5dcc52 fix(plot): honor XCLIP boundary on block references when plotting
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).
2026-09-28 16:16:25 +01:00
Hakan SevenandClaude Opus 5.5 e97314cdef fix(pick): overlapping entities resolve to the front-most in draw order
Fixes #1439

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 18:01:38 +03:00
Hakan SevenandClaude Opus 5.5 0c1676e612 fix(underlay): bound how far DWF packages and DGN streams inflate
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 <[email protected]>
2026-09-28 17:17:38 +03:00
Hakan Seven d9899be35e Merge pull request #1514 from ramox81/codex/dwf-dgn-underlays
Attach Underlay ribbon menu, DWF/DGN attach dialog, DGN true colours
2026-09-28 17:17:17 +03:00
ramox81andClaude Opus 5.5 5b6cbff5b2 Attach Underlay ribbon menu, DWF/DGN attach dialog, DGN true colours
- 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 <[email protected]>
2026-09-28 17:08:06 +03:00
Hakan SevenandClaude Opus 5.5 e26e0352b7 fix(underlay): malformed DWF and DGN files no longer crash or hang the reader
- 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 <[email protected]>
2026-09-28 17:06:14 +03:00
ramox81 fecbcd8138 Merge remote-tracking branch 'origin/main' into codex/dwf-dgn-underlays
# Conflicts:
#	Cargo.lock
2026-09-28 16:13:14 +03:00
ramox81andClaude Opus 5.5 56ecf786f1 DWF/DGN underlays: clipping, layers, text, 3D DGN, colours and zoom extents
- 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 <[email protected]>
2026-09-28 16:10:01 +03:00
Hakan Seven 7694c506aa Merge pull request #1512 from ramox81/codex/frame-parity
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.
2026-09-28 13:52:06 +03:00
ramox81andClaude Opus 5.5 1cbe89ef62 Underlays are rasterised for the view's scale; DGN V7 strokes one pixel wide
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 <[email protected]>
2026-09-28 13:49:33 +03:00
Hakan Seven 6c481c92fe Merge pull request #1513 from ramox81/codex/image-transparency
Raster images: draw opaque when transparency is off; TRANSPARENCY command
2026-09-28 13:48:51 +03:00
ramox81andClaude Opus 5.5 cb7860e50e DWF and DGN underlays: attach, display, snaps, frames and references
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 <[email protected]>
2026-09-28 12:53:25 +03:00
Hakan SevenandClaude Opus 5.5 d40e6c8d1d chore(text): English-only comments for the hint-reliant font path
#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 <[email protected]>
2026-09-28 11:58:38 +03:00
Hakan Seven ee2a12f778 Merge pull request #1506 from Chrisyeh1983/fix/kaiu-hinting
fix(text): run the TrueType interpreter for hint-reliant fonts (DFKai-SB / MingLiU)
2026-09-28 11:56:45 +03:00
ramox81andClaude Opus 5.5 5ca7becd97 Raster images: transparency off draws pixels opaque; TRANSPARENCY command
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 <[email protected]>
2026-09-28 11:23:19 +03:00
ramox81andClaude Opus 5.5 7f8f8457c7 Frames: state-following ribbon list, DWF/DGN frames, image frame encoding and profile, frame-only picking
- 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 <[email protected]>
2026-09-28 10:53:53 +03:00
Karim Jerbi 801882314f perf(explode): batch erasure, section map, pre-sized vectors
EXPLODE apply 504ms -> 61ms (-88%), geometry 70.2ms -> 58.1ms (-17%) on the 2,500-compound fixture.
2026-09-28 06:58:47 +01:00
Chris YehandClaude Opus 5.5 5a36ecda74 fix(text): hint TrueType fonts that need the interpreter (DFKai-SB, MingLiU) before outlining
DFKai-SB (kaiu.ttf), MingLiU and other early DynaLab fonts assemble each
ideograph from stroke components that only the TrueType instructions move
into place. ttf-parser's `outline_glyph` returns the raw, unhinted `glyf`
outline, so these fonts rendered with missing or displaced strokes
('自' drawn as '目'; 範, 直, 啟, 動 broken). FreeType calls them "tricky"
and always runs the interpreter for them.

Every non-test `outline_glyph` call site in ttf_glyph.rs (`glyph`,
`outline_char` - shared by both native fallback paths -, the web
`build_fallback`, and both `build_shaped` variants) now goes through
`outline_glyph_into`; `outline_char` takes the font data and face index
for that. When skrifa's `require_interpreter()` says the face
is hint-reliant, the glyph is hinted with the TrueType interpreter
(Target::Mono) at 512 ppem and scaled back to font units (x upem / 512);
every other font keeps the exact ttf-parser outline. The decision and the
HintingInstance are cached once per face, keyed by (byte length, face
index, head.checkSumAdjustment) because fontdb may hand out a new buffer
per call. The hinted path is recorded first and replayed only on success,
so a failed draw falls back to ttf-parser without a half-drawn glyph.

skrifa 0.42.1 is already in the lockfile (via hayro / glifo).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-27 21:44:52 +08:00
Hakan SevenandClaude Opus 5.5 89512c2f20 fix(text): no stroke-font tracking after big-font and fallback glyphs (#1470)
Every glyph advanced by the face's letter spacing, including CJK glyphs a
style's big font or the TrueType fallback supplies. Their advances already
carry the gap (big font) or side bearings (TrueType), so with an LFF primary
such as iso each ideograph took 1.33 heights instead of one.
Face::spacing_after(ch) gives the tracking only to glyphs the stroke font
draws itself; every layout path uses it.

The 1.8-height widths in the report were the TEXT bounds estimate counting
UTF-8 bytes; opencadcodec 1109d52 counts characters.

Pins opencadcodec 1109d52, opencadkernel 8a246b0, opencadgraph 3c4af1c.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-25 21:27:17 +03:00
Hakan SevenandClaude Opus 5.5 fdc01e13c8 fix(render): show Inventor drawing views, each in its own viewport (#1285)
Inventor DWG exports place every sheet block with AcIdBlockReference,
which the codec skipped, so these drawings opened blank. opencadcodec
7c20aa7 decodes it as an INSERT and keeps the viewport each model-space
view reference is bound to.

Those view blocks overlap in model space, so a content viewport now also
hides model-space references bound to a different viewport. The handles
join the viewport's frozen-layer set (entity and layer handles never
collide), which the wire and render-graph visibility checks and every
per-viewport cache key already use.

Pins opencadcodec 7c20aa7, opencadkernel d71a828, opencadgraph 1543a5a.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-25 19:48:36 +03:00