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.
This commit is contained in:
+12
-4
@@ -30,7 +30,15 @@ Stream widget bounding box: hug the widget on all four sides, pinned to canvas (
|
|||||||
wasn't 0,0. Same silent JSON bug — the crop still never executed — and the measure was scroll
|
wasn't 0,0. Same silent JSON bug — the crop still never executed — and the measure was scroll
|
||||||
extents regardless. Lesson: verify declared mechanics actually execute; assume nothing ran.
|
extents regardless. Lesson: verify declared mechanics actually execute; assume nothing ran.
|
||||||
|
|
||||||
## Current iteration (`582d1f4`)
|
## Current iteration (web bounding box — committed, NOT pushed, verification pending)
|
||||||
Script returns a real object: the union of every visible `body *` `getBoundingClientRect` (the
|
- Render stays the confirmed-solid 1920×1080 canvas-size viewport + `Stretch="Fill"` (UNTOUCHED).
|
||||||
widget's true rect including its top‑left offset). `CaptureFrame` crops AT that offset; Fill maps
|
- Crop BEHAVIOR restored to f39ebd9 exactly: capture cropped from (0,0) to
|
||||||
the frame flush under the box. Committed, not pushed, visual verification pending.
|
`scrollWidth/scrollHeight` extents — the code that nailed right/bottom. Real-object return
|
||||||
|
keeps the crop actually executing (past cause: JSON.stringify double-encode silently disabled it).
|
||||||
|
|
||||||
|
## Iteration that just failed (`582d1f4` — union of every `body *` element rect)
|
||||||
|
Gap moved to ALL sides. The union includes invisible full-canvas layout wrappers, so the crop rect
|
||||||
|
came out larger than the visible widget; the offset crop (+ Rewatched fills from a subset of the
|
||||||
|
canvas. Over-engineering: the fix that already worked was f39ebd9's simple scroll-extents crop.
|
||||||
|
Creator's instruction: go back to that code. DONE — do not re-introduce element-union measuring.
|
||||||
|
Lesson: when a prior iteration is declared good, REVERT TO IT; do not build a cleverer replacement.
|
||||||
+13
-37
@@ -29,8 +29,6 @@ public sealed class WebView2Manager : IDisposable
|
|||||||
public VideoFrame? LatestFrame;
|
public VideoFrame? LatestFrame;
|
||||||
public double ViewportCssW;
|
public double ViewportCssW;
|
||||||
public double ViewportCssH;
|
public double ViewportCssH;
|
||||||
public double ContentCssX;
|
|
||||||
public double ContentCssY;
|
|
||||||
public double ContentCssW;
|
public double ContentCssW;
|
||||||
public double ContentCssH;
|
public double ContentCssH;
|
||||||
public bool Disposed;
|
public bool Disposed;
|
||||||
@@ -165,33 +163,15 @@ public sealed class WebView2Manager : IDisposable
|
|||||||
// viewport for widgets that don't fill it — the leftover area is dead space
|
// viewport for widgets that don't fill it — the leftover area is dead space
|
||||||
// that must not stretch across the selection box. Crop the capture to the
|
// that must not stretch across the selection box. Crop the capture to the
|
||||||
// content bounds (anchored at 0,0) so the box shows exactly the widget.
|
// content bounds (anchored at 0,0) so the box shows exactly the widget.
|
||||||
// The widget's ACTUAL visible content bounds — the union of every visible
|
// This restores f39ebd9's measurement (scrollWidth/Height), which the
|
||||||
// body rectangle (getBoundingClientRect). This is the real widget rect,
|
// creator confirmed nailed the right and bottom of the box. The result is
|
||||||
// excluding the page's own margins/dead space, with its top-left offset.
|
// returned as a real JS object, NOT JSON.stringify — ExecuteScriptAsync
|
||||||
// A real object is returned (NOT JSON.stringify — ExecuteScriptAsync
|
// JSON-encodes the result, so stringifying would double-encode and the
|
||||||
// JSON-encodes the result, which would double-encode a string).
|
// JSON parse would throw, silently disabling the crop.
|
||||||
private const string ContentBoundsScript =
|
private const string ContentBoundsScript =
|
||||||
"(function(){" +
|
"({w:document.documentElement.scrollWidth||document.body.scrollWidth||0," +
|
||||||
"var rs=[];var body=document.body;" +
|
"h:document.documentElement.scrollHeight||document.body.scrollHeight||0," +
|
||||||
"if(body){var br=body.getBoundingClientRect();if(br.width||br.height)rs.push(br);}" +
|
"vw:window.innerWidth||1,vh:window.innerHeight||1})";
|
||||||
"var els=document.querySelectorAll('body *');" +
|
|
||||||
"for(var i=0;i<els.length;i++){" +
|
|
||||||
"var s=getComputedStyle(els[i]);" +
|
|
||||||
"if(s&&s.display==='none')continue;" +
|
|
||||||
"var r=els[i].getBoundingClientRect();" +
|
|
||||||
"if(r.width||r.height)rs.push(r);" +
|
|
||||||
"}" +
|
|
||||||
"if(!rs.length)return null;" +
|
|
||||||
"var l=rs[0].left,t=rs[0].top,rt=rs[0].right,bt=rs[0].bottom;" +
|
|
||||||
"for(var j=1;j<rs.length;j++){" +
|
|
||||||
"l=Math.min(l,rs[j].left);" +
|
|
||||||
"t=Math.min(t,rs[j].top);" +
|
|
||||||
"rt=Math.max(rt,rs[j].right);" +
|
|
||||||
"bt=Math.max(bt,rs[j].bottom);" +
|
|
||||||
"}" +
|
|
||||||
"return {l:l,t:t,w:Math.max(1,rt-l),h:Math.max(1,bt-t)," +
|
|
||||||
"vw:window.innerWidth||1,vh:window.innerHeight||1};" +
|
|
||||||
"})()";
|
|
||||||
|
|
||||||
private async Task QueryContentBoundsAsync(string sourceId)
|
private async Task QueryContentBoundsAsync(string sourceId)
|
||||||
{
|
{
|
||||||
@@ -205,8 +185,6 @@ public sealed class WebView2Manager : IDisposable
|
|||||||
var root = doc.RootElement;
|
var root = doc.RootElement;
|
||||||
session.ViewportCssW = root.GetProperty("vw").GetDouble();
|
session.ViewportCssW = root.GetProperty("vw").GetDouble();
|
||||||
session.ViewportCssH = root.GetProperty("vh").GetDouble();
|
session.ViewportCssH = root.GetProperty("vh").GetDouble();
|
||||||
session.ContentCssX = root.GetProperty("l").GetDouble();
|
|
||||||
session.ContentCssY = root.GetProperty("t").GetDouble();
|
|
||||||
session.ContentCssW = root.GetProperty("w").GetDouble();
|
session.ContentCssW = root.GetProperty("w").GetDouble();
|
||||||
session.ContentCssH = root.GetProperty("h").GetDouble();
|
session.ContentCssH = root.GetProperty("h").GetDouble();
|
||||||
_ = CaptureFrame(sourceId);
|
_ = CaptureFrame(sourceId);
|
||||||
@@ -252,25 +230,23 @@ public sealed class WebView2Manager : IDisposable
|
|||||||
|
|
||||||
var stride = pixW * 4;
|
var stride = pixW * 4;
|
||||||
|
|
||||||
int cropX = 0, cropY = 0, cropW = pixW, cropH = pixH;
|
int cropW = pixW, cropH = pixH;
|
||||||
if (session.ViewportCssW >= 1 && session.ViewportCssH >= 1 &&
|
if (session.ViewportCssW >= 1 && session.ViewportCssH >= 1 &&
|
||||||
session.ContentCssW >= 1 && session.ContentCssH >= 1)
|
session.ContentCssW >= 1 && session.ContentCssH >= 1)
|
||||||
{
|
{
|
||||||
var sx = pixW / session.ViewportCssW;
|
var sx = pixW / session.ViewportCssW;
|
||||||
var sy = pixH / session.ViewportCssH;
|
var sy = pixH / session.ViewportCssH;
|
||||||
cropX = (int)Math.Clamp(Math.Round(session.ContentCssX * sx), 0, pixW - 1);
|
cropW = (int)Math.Clamp(Math.Round(session.ContentCssW * sx), 1, pixW);
|
||||||
cropY = (int)Math.Clamp(Math.Round(session.ContentCssY * sy), 0, pixH - 1);
|
cropH = (int)Math.Clamp(Math.Round(session.ContentCssH * sy), 1, pixH);
|
||||||
cropW = (int)Math.Clamp(Math.Round(session.ContentCssW * sx), 1, pixW - cropX);
|
|
||||||
cropH = (int)Math.Clamp(Math.Round(session.ContentCssH * sy), 1, pixH - cropY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var outPixels = pixels;
|
var outPixels = pixels;
|
||||||
if (cropW != pixW || cropH != pixH || cropX != 0 || cropY != 0)
|
if (cropW != pixW || cropH != pixH)
|
||||||
{
|
{
|
||||||
var dstStride = cropW * 4;
|
var dstStride = cropW * 4;
|
||||||
outPixels = new byte[dstStride * cropH];
|
outPixels = new byte[dstStride * cropH];
|
||||||
for (var r = 0; r < cropH; r++)
|
for (var r = 0; r < cropH; r++)
|
||||||
Buffer.BlockCopy(pixels, (cropY + r) * stride + cropX * 4, outPixels, r * dstStride, dstStride);
|
Buffer.BlockCopy(pixels, r * stride, outPixels, r * dstStride, dstStride);
|
||||||
}
|
}
|
||||||
|
|
||||||
var wb = new WriteableBitmap(cropW, cropH, 96, 96, PixelFormats.Bgra32, null);
|
var wb = new WriteableBitmap(cropW, cropH, 96, 96, PixelFormats.Bgra32, null);
|
||||||
|
|||||||
Reference in New Issue
Block a user