Make Surface remote debugging and classroom workflows viable: always-on
structured logs with one-click zip export, a single AppShell chrome,
OOXML PPTX/DOCX annotation without LibreOffice, and a first-class sticky
board. Also drop spike/legacy ink widgets and tighten pen feel
(predictor, PenInfoHistory, page-tile layer).
Co-authored-by: Cursor <cursoragent@cursor.com>
PPT slides now annotate with the single performant inking engine
(PenCanvas) instead of the old ink_canvas, per "all note features on the
pen-first canvas".
- PenSlideScreen: per-slide normalized strokes over each slide image,
prev/next + slider nav, undo/redo, shared M3 palette, and the pressure
curve / eraser size+mode / palm rejection from the shared canvas.
- slide_export: pure, tested export geometry. Because strokes are now
normalized to the page rect, the PDF exporter maps them straight into
each slide's draw rect — fixing the old exporter's known ink
misalignment (it guessed live-widget size).
- Route PPT import + open -> PenSlideScreen; delete the dead old
ppt_annotator_screen. (ink_canvas/annotation_toolbar remain for
split_view, the last old-canvas screen.)
Tests: slide_export geometry (4). flutter analyze: 0 issues. Suite: 269/269.
Production adapter wrapping a pdfrx PdfDocument: snapshots page sizes via the
real pdfrx 2.4.4 geometry API (PdfDocument.pages, PdfPage.width/height) so the
pure layout math runs on the real document. Because it lives under lib/editor/,
`flutter analyze lib/editor` (the Oracle) type-checks it against the installed
pdfrx every run — a version bump that renames/retypes these members now FAILS
analysis instead of silently drifting (SF4 source-pin, statically).
Runtime contract + layout composition tested via the pdfium-free .fromSizes
ctor; the .fromDocument pin is the static guarantee (exercising it needs pdfium
= device path).
flutter analyze lib/editor clean; 123/123 tests (+3).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Connects the two pure P0.5 pieces: a minimal PageDocumentSource abstraction
(pageCount + pageSize, a pdfrx PdfDocument in production) and
pageStackMetricsForWidth() which fits every page to a single column width
(continuous-single) — height = columnWidth × aspect — feeding
PageStackMetrics.visibleRange. Defensive against non-positive page width.
This makes the windowing math consumable + unit-testable against a fake source
(no pdfium/GPU); the production pdfrx adapter is the thin device-side wrapper
added with the page-mounting widget.
flutter analyze lib/editor clean; 120/120 tests (+5: fit-to-width, gap, empty,
zero-width guard, windowing composition).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "heavy" page-bitmap cache (R11/MF2), deliberately SEPARATE from the
resolution-independent ink Picture cache: page tiles are only crisp at the DPI
they were rasterized for, so TileKey carries a DPI bucket. get()/put() (tiles
render async via pdfrx), bounded LRU with MRU promotion, per-key replacement
disposes the old image, evictHostsExcept() for scroll-out, and post-frame
ui.Image disposal so the raster thread never frees an in-use image.
dpiBucketFor() snaps a continuous pinch scale to a coarse bucket (ceil by step,
capped at maxBucket) so a smooth zoom re-uses tiles instead of spawning one per
frame and bounds retained-DPI memory (~3× cap).
The pdfrx tile RENDERING (page_tile.dart) + zoom-settle DPI refresh remain
device-gated (crisp-at-4× on the Surface) — only the cache data structure is
automatable, and it is here, fully unit-tested.
flutter analyze lib/editor clean; 102/102 tests (+12: bucket math, LRU, MRU,
host eviction, post-frame disposal via debugDisposed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clean-room reimplementation of Saber's input model: we own the gesture
pipeline so pen draws with real pressure (perfect_freehand), two-finger
pinch zooms/pans, and palm is rejected (stylus-priority, 2nd-pointer
cancels stroke). pdfrx renders one page at a time (PdfPageView, no
gestures) under a shared transform; page-based nav. Material You theme
via dynamic_color (system accent + seed fallback) and a floating tonal
tool palette + page pill. Old pdfrx-overlay spike no longer wired.
Add pdfrx 2.4.4. PenCaptureRegion routes stylus to ink (arena-bypass
via PenCaptureBinding) while touch falls through to pdfrx scroll/zoom.
Spike pane hosts PdfViewer with page-overlay ink at normalized coords +
frame-time HUD; reachable from home screen for on-device testing.
Bench/coordinate harness under integration_test. Generated assets are
gitignored (regenerate via tool/gen_*.dart).