render: PNG screenshots via CLI and CDP

End-to-end rasterization behind the render feature (which now enables
obscura-render/paint):

- obscura-render: screenshot_png(dom, viewport) paints and encodes to PNG
  via tiny-skia's encode_png (no extra dep).
- obscura-browser: Page::screenshot renders the live DOM at a viewport.
- CLI: obscura fetch --screenshot out.png writes the settled page to a PNG.
- CDP: Page.captureScreenshot returns the PNG base64-encoded, so
  Puppeteer/Playwright page.screenshot() works. captureSnapshot still
  errors (it is a DOM/layer snapshot, not an image).

Verified: both paths produce correct 1280x720 RGBA PNGs with elements
laid out and colored as the CSS specifies (block stacking, backgrounds,
white page). Default build unchanged; obstacle course 33/33.

Text, borders, and images are not yet painted; the box layout and
background colors are rendered.
This commit is contained in:
SGavrl committed 2026-07-01 21:34:15 +00:00
1 parent 4ca85e87d8
commit cdd52ade43
9 files changed
+92 -12

No files matched your search

+8
View File
@@ -1281,6 +1281,14 @@ impl Page {
self.dom.as_ref().map(f)
}
/// Rasterize the current DOM to PNG bytes at `viewport` (CSS pixels), when
/// the render feature is compiled in. None if the page has no DOM or the
/// viewport is zero-sized.
#[cfg(feature = "render")]
pub fn screenshot(&self, viewport: (f32, f32)) -> Option<Vec<u8>> {
self.with_dom(|dom| obscura_js::screenshot_png(dom, viewport)).flatten()
}
/// Absolute URLs the page pulled in via fetch()/XHR (issue #301). Empty
/// when the page has no live JS runtime.
pub fn fetched_urls(&self) -> Vec<String> {