Commit Graph

15 Commits

Author SHA1 Message Date
gramps d35823a4a9 feat(ux)+fix(rings): release counter #N in the wordmark; all shared-frame rings 4->8 (#11)
Roll-forward of today-slices 6fd1d9c onto the slice-8 base, two-loop hunk dropped.

Release counter (per-build GUID read as noise; +1 per commit from git rev-list,
baseline 241 -> #13, generated by GenerateBuildStamp; GUID demotes to startup.log).
Tests pinned to Label/#N >= 13; wordmark display test asserts the Label.

Flash fix (take 14 finding): consumer holds must never outlive depth x source
period — 4 slots at high refresh lap ~27ms vs a <=50ms compositor read, so a
recycled slot flashed its new frame over the lagged old one. All shared rings 4->8
(OBS/overlay precedent for ring discipline).

Camera producer now rotates an 8-deep ring + Epoch instead of a fresh ~3.7MB
array per device frame (110-220MB/s LOH churn); WebView2 capture reuses a canvas
scratch + 8-deep output ring + a reused WriteableBitmap instead of two fresh
arrays + a fresh bitmap per 10Hz tick. Paste cache stays identity-keyed (Epoch).
2026-09-05 14:31:03 -07:00
gramps 9b56e88800 Revert ab29ec8: container==content auto-fit made it worse — back to alpha-crop with the container at element size
The container tracks the element's own Width/Height again; the crop stays in the bitmap.
2026-08-28 12:09:13 -07:00
gramps ab29ec801d Web source: container == content — element grid + selection box sized to the cropped frame's canvas extent
- FindContentBounds already trimmed the bitmap; the grid/box still rendered at the uncropped user
  size, so Fill stretched the tight widget into a bigger frame = dead-between-content-and-border.
- ContentCanvasSize maps the crop rect to canvas units (1920/pixW per axis, DPI-correct) and the
  preview event now carries (bitmap, canvasW, canvasH).
- OnWebView2PreviewBitmapChanged sets the element Width/Height to that size; the grid and the
  SelectionOverlay (both bound to the element's Width/Height) now equal the widget exactly.
- IsPreviewDragging (set in MainWindow drag/resize) suppresses auto-fit mid-gesture.
- Tests 10/10 (alpha bounds, canvas-size mapping incl. DPI, control size); 0 warnings.
2026-08-28 12:08:04 -07:00
gramps bccdb4892c Web source: crop to the frame's ALPHA bounding box — the widget's true rendered extent, no DOM timing, can't break the render
- FindContentBounds scans the Bgra32 capture for the bounding box of non-transparent pixels
  (background is injected transparent, so alpha = widget extent). Crop to that rect + Stretch=Fill
  maps the widget flush under the selection box: full-canvas widgets fall through to the full frame
  (identical to the confirmed-good image); floating widgets get tight-fitted with no dead space.
- Removes QueryContentBoundsAsync + the JS script entirely — the DOM-union attempt (a5b9952) broke
  rendering by measuring an unsettled layout on NavigationCompleted; alpha measurement is immune.
- 3 new unit tests: tight box, no-alpha no-crop, full-alpha no-crop. 7/7 pass, 0 warnings.
2026-08-28 11:53:36 -07:00
gramps 5348b5c480 Revert web render to the creator-verified-good base (70fe2b8): full-frame capture, no crop, plain Stretch=Fill
The wrapper-excluded content-union crop measured an unsettled layout on NavigationCompleted
(async fonts/images, load animations) and produced a broken/zoomed sliver — the image was gone.
Restoring the exact confirmed-good pipeline; the bounding-box dead-space problem stays open and
will not be touched without explicit approval.
2026-08-28 11:49:21 -07:00
gramps a5b9952cbd Web source: crop to the WIDGET rect (visible-element union excluding full-viewport wrappers) — kills the ghost-boundary dead space
- scrollWidth/scrollHeight returns the whole 1920x1080 canvas for widgets whose body/background
  spans it, so the crop kept massive transparent margins and the content floated in the Fill box.
- ContentBoundsScript now unions every visible element's getBoundingClientRect, excluding elements
  that span >=98% of the viewport (bodies, full-canvas background layers); full-bleed widgets fall
  back to the full rect. Crop taken AT the rect's top-left (l,t) — content pins to bitmap (0,0).
- Web Image explicitly Margin=0 + Left/Top alignment so the frame and widget coincide at the origin.
- Canvas-size render untouched.
2026-08-28 11:45:31 -07:00
gramps b862a0fb04 Web source: revert crop measurement to f39ebd9 scrollWidth/Height (nailed right/bottom) — canvas-size render untouched
- ContentBoundsScript back to scrollWidth/scrollHeight extents, kept as a real JS object
  (the JSON.stringify double-encode bug that silently disabled the crop stays fixed).
- Crop again from (0,0), no X/Y offset. The union-of-elements approach (582d1f4) created an
  all-sides gap by including invisible full-canvas wrappers; revert to the proven code.
2026-08-28 11:35:30 -07:00
gramps 582d1f4b0f Web source: crop to the widget's true content rect (union of visible body elements) — bounding box tight on all four sides, pinned to (0,0)
- QueryContentBoundsAsync now returns a real JS object (not JSON.stringify — ExecuteScriptAsync
  double-encodes strings, which silently killed the old crop) and measures the union of every
  visible body element's getBoundingClientRect: the widget's actual rect, top-left offset included.
- CaptureFrame crops AT that offset (x,y) instead of from (0,0), so the widget anchors at origin
  and the box is flush on right/bottom. Fill maps the frame flush under the box.
2026-08-28 11:25:06 -07:00
gramps 70fe2b80b2 Web source: render at canvas size 1920x1080 — full-bleed widgets no longer truncated to upper-left 2026-08-28 11:16:46 -07:00
gramps f39ebd96ce Web source: crop capture to actual content bounds (anchor 0,0); slider click-to-position; web URI X clears; tab order 2026-08-28 11:10:49 -07:00
gramps 23874c2dd6 Web source: stable viewport (snapshot at register) + Stretch=Fill + overflow:hidden — no reflow, no scrollbars, no dead space 2026-08-28 10:56:23 -07:00
gramps 8d793af91a Web source: geometry-agnostic viewport==box model — viewport locked to element box, Stretch=Fill, no dead space 2026-08-28 10:48:53 -07:00
gramps 9d4103c44b Web source: CSS reset per document + (0,0) anchor — kill box-vs-content padding 2026-08-28 10:41:33 -07:00
gramps e917c41a48 Web source: fix rendering — fixed 1920×1080 viewport (OBS pattern), Stretch=Uniform, startup registration 2026-08-28 10:23:59 -07:00
gramps fd6e02b687 Web source: off-screen WebView2 capture + layout persistence + transparent bg
Bundle exception (2026-08-27): this lands prior-session work plus today's
transparency fix as one commit per creator instruction.

WebView2Manager (new): off-screen WebView2 control parked at -5000/-5000 in
the window's visual tree, captures via CapturePreviewAsync every 100 ms into
a BGRA8 VideoFrame. Source Width/Height sync to the control via
PropertyChanged. JS transparent-background injection runs on every
NavigationStarting/NavigationCompleted so the page's own CSS does not paint
white over the capture.

Transparency fix: DefaultBackgroundColor = System.Drawing.Color.Transparent
set on the WPF control before EnsureCoreWebView2Async. The WPF SDK doc says
the value is forwarded to the controller on init; the IDL (ICoreWebView2-
Controller2) confirms alpha=0 makes the capture alpha-preserving. The
prior-session 'CoreWebView2.BackgroundColor' path was the wrong property
name and has been replaced.

LayoutStore: WebUri column added (idempotent ALTER TABLE) and round-tripped
on save/load (schema v11).

MainViewModel: WebView2Manager constructed on Loaded; loaded web sources
re-registered; Source.WebUri PropertyChanged forwards to manager.

MainWindow: off-screen host Canvas added to visual tree.

Tests: 3 scale-sync + WebView2_DefaultBackgroundColor_Is_Transparent +
LayoutStorePersistenceTests.WebSource_WebUri_Persists. 234/236 pass
(2 pre-existing failures unchanged).

Scale bug (DPI/physical-pixel mismatch) still open.
2026-08-27 08:52:39 -07:00