Revert "fix(web): composite consumes the FULL canvas, alpha crop is measure-only — transparent web margins reveal the webcam again"

This reverts commit 0f441d825a.
This commit is contained in:
2026-09-05 16:21:16 -07:00
parent 0f441d825a
commit 1295e0ed80
4 changed files with 21 additions and 151 deletions
-64
View File
@@ -114,70 +114,6 @@ public class SceneCompositorTests
AssertColor(output, 550, 700, 255, 255, 255);
}
/// <summary>The ONE integration test for the web-overlay transparency regression
/// (take-19-2/take-20 "black square over the webcam"): a FULL-canvas web frame
/// (the page background is transparent; the widget content lives at its canvas
/// position) is composited into a webcam-covered scene. The element rect is a
/// viewport onto the page, so the page's transparent margins must REVEAL the
/// layers beneath (the webcam), while the widget's opaque content still draws.
/// Feeding the ALPHA CROP instead of the full canvas zoomed the opaque content
/// box to cover the whole element rect — this test pins the reveal contract.</summary>
[Fact]
public void Composite_FullCanvasWebSource_TransparentMarginsRevealWebcam()
{
var red = Solid(1920, 1080, 255, 0, 0);
var green = Solid(1280, 720, 0, 255, 0);
var blue = Solid(1920, 1080, 0, 0, 255);
// FULL-canvas web frame (what WebView2Manager hands to the compositor):
// transparent everywhere except an opaque badge at its canvas position.
var webPixels = new byte[1920 * 1080 * 4];
for (var y = 800; y < 880; y++)
for (var x = 1400; x < 1520; x++)
{
var i = (y * 1920 + x) * 4;
webPixels[i] = blue.BgraPixels[i];
webPixels[i + 1] = blue.BgraPixels[i + 1];
webPixels[i + 2] = blue.BgraPixels[i + 2];
webPixels[i + 3] = 255;
}
var webCanvas = new VideoFrame(1920, 1080, webPixels);
var background = new Source { Type = SourceType.DisplayCapture, IsBackground = true, CaptureKey = "monitor:0" };
var webcam = new WebcamSceneConfig { X = 1360, Y = 760, Width = 536, Height = 294, ClipShape = ClipShape.Traditional };
var webSource = new Source { Type = SourceType.WebSource, X = 1279, Y = 709, Width = 703, Height = 389 };
var scene = new Scene { Name = "Live" };
scene.Elements.Add(background);
scene.Elements.Add(webcam);
scene.Elements.Add(webSource);
VideoFrame? FrameFor(SceneElement e) => e switch
{
WebcamSceneConfig => green,
Source { IsBackground: true } => red,
Source { Type: SourceType.WebSource } => webCanvas,
_ => null,
};
var options = new CompositorOptions
{
SourceRectX = 0, SourceRectY = 0, SourceRectWidth = 1920, SourceRectHeight = 1080,
OutputWidth = 1920, OutputHeight = 1080,
};
var output = new SceneCompositor().Render(scene, FrameFor, null, options);
// (1777,984) ≈ canvas (1360,760): inside the web element rect AND inside the
// webcam rect, but in the page's transparent margin -> the WEBCAM must show.
AssertColor(output, 1777, 984, 0, 255, 0);
// (1810,1010) ≈ canvas (1450,825): inside the widget's opaque badge -> the
// widget content draws over the webcam.
AssertColor(output, 1810, 1010, 0, 0, 255);
// deep margin north of the webcam: the backdrop shows through untouched.
AssertColor(output, 1300, 720, 255, 0, 0);
}
/// <summary>The take-4 memcpy fast path: a full-cover opaque backdrop (the live
/// capture's contract) must reproduce the source EXACTLY, and when supplied via the
/// <c>scratch</c> pool parameter the render must overwrite every byte of the reused