Skip to content

Renderer-gaps quick wins: DOMVersion, ShowMasterItems, overset, GraphicLine, VerticalScale, Position, MasterPageTransform#1

Merged
drietsch merged 1 commit into
mainfrom
renderer-gaps-quick-wins
May 31, 2026
Merged

Renderer-gaps quick wins: DOMVersion, ShowMasterItems, overset, GraphicLine, VerticalScale, Position, MasterPageTransform#1
drietsch merged 1 commit into
mainfrom
renderer-gaps-quick-wins

Conversation

@drietsch

Copy link
Copy Markdown
Contributor

Implements the small-scope ("quick win") items from the private
renderer-gaps.md roadmap, after verifying each against the code at the
pinned commit. Several documented "gaps" turned out to be already done
(NestedStyle splitting, Knuth–Plass, nested-in-group frames, Dotted strokes);
those are reconciled in the roadmap doc separately, not here.

Changes

  • DOMVersion — parsed onto DesignMap; surfaced read-only in paged-inspect
    (human summary + JSON). No version branching yet.
  • ShowMasterItems — parsed on <Page>; when false, the whole master-stamp
    loop body is skipped (suppresses master frames, lines, and page-number text
    together).
  • Overset — the existing dropped_overflow_lines counter is now surfaced as
    a diagnostic (inspect line + JSON) instead of dropping clipped lines silently.
  • GraphicLine — strokes the real multi-segment / open anchor path (reusing
    polygon_path_from_anchors_with_open + frame_outer_transform) instead of the
    bounds diagonal; contours default to open. Falls back to the diagonal only when
    anchorless.
  • VerticalScale — mirrors HorizontalScale end to end:
    StyledRun.vertical_scale_pctPositionedGlyph.y_scale → the glyph affine's
    y term (scales height about the baseline; advance/leading unchanged). Layout
    cache hash updated.
  • Position (super/subscript) — new position_metrics() applies InDesign's
    factory defaults (58.3% size, ±33.3% baseline) via the existing point-size +
    baseline-shift plumbing. Exact values await Preferences parsing (separate gap).
  • MasterPageTransform — master items are stamped under the full affine
    translate(target) ∘ MPT ∘ translate(-master origin) via compose_outer_matrix,
    not translation-only. Identity MPT reduces to the prior (dx, dy) shift.
  • Strokes — custom <DottedStrokeStyle> patterns are now consumed; the
    Striped/Wavy → solid fallback is made explicit (true multi-line/sine rendering
    needs a new rasterizer stroke capability — deferred, tracked in the roadmap).

Tests

New unit tests: DOMVersion parse (present/absent), ShowMasterItems parse,
position_metrics, compose_outer_matrix (identity + scale), vertical-scale
glyph affine, stroke_for custom styles. Full cargo test --workspace is green
(the one pre-existing paged-script storyRange baseline failure is unrelated).
No new clippy lints.

🤖 Generated with Claude Code

…set, GraphicLine, VerticalScale, Position, MasterPageTransform)

Closes the small-scope items from thoughts/docs/paged/core/renderer-gaps.md
after verifying each against the code; several documented "gaps" were already
done and are noted in that doc separately.

- DOMVersion: parse onto DesignMap, surface read-only in paged-inspect
  (human summary + JSON). No version branching yet.
- ShowMasterItems: parse on <Page>; skip the whole master-stamp loop body
  for a page when false (suppresses master frames, lines, and page-number
  text at once).
- Overset: surface the existing dropped_overflow_lines counter as a
  diagnostic (inspect line + JSON) instead of dropping lines silently.
- GraphicLine: stroke the real multi-segment/open anchor path (reusing
  polygon_path_from_anchors_with_open + frame_outer_transform) instead of
  the bounds diagonal; contours default to open. Falls back to the diagonal
  only when anchorless.
- VerticalScale: mirror HorizontalScale end to end — StyledRun.vertical_scale_pct
  -> PositionedGlyph.y_scale -> the glyph affine's y term (scales height about
  the baseline; advance/leading unchanged). Layout-cache hash updated.
- Position (super/subscript): new position_metrics() applies InDesign's
  factory defaults (58.3% size, +/-33.3% baseline) via the existing point
  size + baseline-shift plumbing. Exact values await Preferences parsing.
- MasterPageTransform: stamp master items under the full affine
  translate(target) o MPT o translate(-master origin) via compose_outer_matrix,
  not translation only. Identity MPT reduces to the prior (dx,dy) shift.
- Strokes: consume custom <DottedStrokeStyle> patterns; make the
  Striped/Wavy -> solid fallback explicit (true multi-line/sine rendering
  needs a new rasterizer capability — deferred).

New unit tests: DOMVersion parse, ShowMasterItems parse, position_metrics,
compose_outer_matrix (identity + scale), vertical-scale affine, stroke_for
custom styles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@drietsch drietsch merged commit 08a0d8f into main May 31, 2026
1 of 6 checks passed
@drietsch drietsch deleted the renderer-gaps-quick-wins branch May 31, 2026 07:10
drietsch pushed a commit that referenced this pull request Jun 6, 2026
…index shifts

The editor's E2E op suite caught two symptoms of one cache family
(editor/docs/engine-findings.md #1 and #3, 2026-06-05):

- undo/redo of a text op kept the stale post-edit text layout: the
  forward paths (apply_mutation's text arm, apply_operation) clear
  master_text_emit_cache + body_story_emit_cache before rebuild, but
  undo()/redo() did not — and the body-story signature matches on
  content-only edits, so the rebuild spliced the pre-undo emission.
- insertPage in the MIDDLE of the page set panicked the renderer
  ('index out of bounds: the len is N but the index is N' at the
  body-story splice) once a pipeline existed: the signature ignored
  the chain's page INDICES, so cached per-page deltas survived
  page-set changes with stale absolute indices; the un-cleared undo
  path then spliced past pages.len() and mutate() never resolved.

Three layers, defense in depth:
- undo()/redo() clear both emit caches before rebuild_after_mutation,
  for both log arms (frame inverses replay structural ops under the
  same caches), mirroring the forward paths.
- body_story_signature hashes the chain's page indices (plus a
  present/absent discriminant per wrap-rect lookup) — an index shift
  is a key change. Indices are stable across gestures, so the cache's
  hot path keeps its hit ratio.
- the splice loop treats any out-of-range per_page index as a cache
  miss (fresh emission) instead of panicking inside the worker.

tests/emit_cache_undo.rs asserts on built display lists (the scene-
hash determinism tests cannot see these bugs — the scene round-trips
while the rendered output goes stale): text undo/redo repaint,
mid-set insertPage undo/redo round-trip (reproduces the exact panic
pre-fix), story-stays-on-its-page after the shift, and the
style-edit repaint cascade (engine side of finding #2 — the cascade
works; the E2E symptom was fixture direct formatting).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant