diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
new file mode 100644
index 0000000..6a8c8a1
--- /dev/null
+++ b/.config/dotnet-tools.json
@@ -0,0 +1,12 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "fallout.cli": {
+ "version": "11.0.18",
+ "commands": [
+ "fallout"
+ ]
+ }
+ }
+}
diff --git a/.fallout/build.schema.json b/.fallout/build.schema.json
new file mode 100644
index 0000000..82690d1
--- /dev/null
+++ b/.fallout/build.schema.json
@@ -0,0 +1,145 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "definitions": {
+ "Host": {
+ "type": "string",
+ "enum": [
+ "AppVeyor",
+ "AzurePipelines",
+ "Bamboo",
+ "Bitbucket",
+ "Bitrise",
+ "GitHubActions",
+ "GitLab",
+ "Jenkins",
+ "Rider",
+ "SpaceAutomation",
+ "TeamCity",
+ "Terminal",
+ "TravisCI",
+ "VisualStudio",
+ "VSCode"
+ ]
+ },
+ "ExecutableTarget": {
+ "type": "string",
+ "enum": [
+ "Clean",
+ "Compile",
+ "CreatePackage",
+ "Default",
+ "Package",
+ "PrePublish",
+ "Publish",
+ "PublishPackage",
+ "PublishPreRelease",
+ "PublishRelease",
+ "Restore",
+ "RunUnitTests"
+ ]
+ },
+ "Verbosity": {
+ "type": "string",
+ "description": "",
+ "enum": [
+ "Verbose",
+ "Normal",
+ "Minimal",
+ "Quiet"
+ ]
+ },
+ "FalloutBuild": {
+ "properties": {
+ "Continue": {
+ "type": "boolean",
+ "description": "Indicates to continue a previously failed build attempt"
+ },
+ "Help": {
+ "type": "boolean",
+ "description": "Shows the help text for this build assembly"
+ },
+ "Host": {
+ "description": "Host for execution. Default is 'automatic'",
+ "$ref": "#/definitions/Host"
+ },
+ "NoLogo": {
+ "type": "boolean",
+ "description": "Disables displaying the NUKE logo"
+ },
+ "Partition": {
+ "type": "string",
+ "description": "Partition to use on CI"
+ },
+ "Plan": {
+ "type": "boolean",
+ "description": "Shows the execution plan (HTML)"
+ },
+ "Profile": {
+ "type": "array",
+ "description": "Defines the profiles to load",
+ "items": {
+ "type": "string"
+ }
+ },
+ "Root": {
+ "type": "string",
+ "description": "Root directory during build execution"
+ },
+ "Skip": {
+ "type": "array",
+ "description": "List of targets to be skipped. Empty list skips all dependencies",
+ "items": {
+ "$ref": "#/definitions/ExecutableTarget"
+ }
+ },
+ "Target": {
+ "type": "array",
+ "description": "List of targets to be invoked. Default is '{default_target}'",
+ "items": {
+ "$ref": "#/definitions/ExecutableTarget"
+ }
+ },
+ "Verbosity": {
+ "description": "Logging verbosity during build execution. Default is 'Normal'",
+ "$ref": "#/definitions/Verbosity"
+ },
+ "BuildProjectFile": {
+ "type": [
+ "null",
+ "string"
+ ],
+ "description": "Path to the build project (.csproj) relative to the repository root. Defaults to 'build/_build.csproj' when unset. Read by the Fallout global tool's in-tool runner."
+ }
+ }
+ }
+ },
+ "allOf": [
+ {
+ "properties": {
+ "AngleSharpVersion": {
+ "type": "string",
+ "description": "AngleSharp package version override (e.g. 1.0.0 for compatibility checks)"
+ },
+ "Configuration": {
+ "type": "string",
+ "enum": [
+ "Debug",
+ "Release"
+ ],
+ "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)"
+ },
+ "ReleaseNotesFilePath": {
+ "type": "string",
+ "description": "ReleaseNotesFilePath - To determine the SemanticVersion"
+ },
+ "Solution": {
+ "type": "string",
+ "description": "Path to a solution file that is automatically loaded"
+ }
+ }
+ },
+ {
+ "$ref": "#/definitions/FalloutBuild"
+ }
+ ]
+}
diff --git a/.fallout/parameters.json b/.fallout/parameters.json
new file mode 100644
index 0000000..cc1ecf1
--- /dev/null
+++ b/.fallout/parameters.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "./build.schema.json",
+ "Solution": "src/AngleSharp.Renderer.sln"
+}
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 61e9edf..b3f20f7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -45,10 +45,22 @@ jobs:
npx pilet publish --fresh --url https://feed.piral.cloud/api/v1/pilet/anglesharp --api-key ${{ secrets.PIRAL_FEED_KEY }}
linux:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
+
+ - name: Install deterministic fonts for snapshots
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y fonts-dejavu-core fontconfig
+ fc-cache -f
+ fc-match "DejaVu Serif"
+ fc-match "DejaVu Sans"
+ fc-match "DejaVu Sans Mono"
+ fc-list | grep -q "DejaVu Serif"
+ fc-list | grep -q "DejaVu Sans"
+ fc-list | grep -q "DejaVu Sans Mono"
- name: Setup dotnet
uses: actions/setup-dotnet@v5
@@ -57,8 +69,20 @@ jobs:
10.0.x
- name: Build
+ env:
+ ANGLESHARP_SNAPSHOT_STRICT: 1
run: ./build.sh -AngleSharpVersion 1.5.0
+ - name: Upload visual assets
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: linux-visual-assets
+ path: |
+ src/AngleSharp.Renderer.Tests/verification-assets/**
+ src/AngleSharp.Renderer.Tests/failure-assets/**
+ if-no-files-found: ignore
+
windows:
runs-on: windows-latest
@@ -80,3 +104,13 @@ jobs:
} else {
.\build.ps1 -AngleSharpVersion 1.5.0
}
+
+ - name: Upload visual assets
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: windows-visual-assets
+ path: |
+ src/AngleSharp.Renderer.Tests/verification-assets/**
+ src/AngleSharp.Renderer.Tests/failure-assets/**
+ if-no-files-found: ignore
diff --git a/.gitignore b/.gitignore
index de3ed79..32b162d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,7 +59,8 @@ local.properties
[Dd]ebug/
[Rr]elease/
[Bb]in/
-[Bb]uild/
+build/bin/
+build/obj/
[Oo]bj/
# Visual Studio 2015 cache/options directory
@@ -171,7 +172,8 @@ Desktop.ini
*.egg
*.egg-info
dist
-build
+build/bin
+build/obj
eggs
parts
var
@@ -195,5 +197,5 @@ pip-log.txt
# Mac crap
.DS_Store
-# Nuke build tool
-.nuke/temp
+# Fallout build tool
+.fallout/temp
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..428c9a0
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,74 @@
+# AGENTS.md
+
+Guidance for AI coding agents working in this repository. Keep this file as the quick-start reference for the repo's commands, architecture, conventions, and test workflow.
+
+## What This Repository Is
+
+AngleSharp.Renderer adds rendering capabilities on top of AngleSharp and AngleSharp.Css. The current implementation is a display-list renderer with a SkiaSharp backend that rasterizes HTML/CSS content into PNG images.
+
+## Most Important Commands
+
+Use the solution-level test command for normal validation:
+
+```bash
+dotnet test src/AngleSharp.Renderer.sln
+```
+
+Use the test project directly when iterating on renderer behavior:
+
+```bash
+dotnet test src/AngleSharp.Renderer.Tests/AngleSharp.Renderer.Tests.csproj
+```
+
+The repo also includes build scripts that drive the Fallout bootstrapper:
+
+```bash
+./build.sh
+./build.ps1
+./build.cmd
+```
+
+The main renderer project targets `net8.0` and `net10.0`. The test project targets `net8.0`.
+
+## Architecture
+
+The renderer is intentionally split into a small number of layers:
+
+- `HtmlRenderer` builds a display list from the AngleSharp render tree and computed styles.
+- `DisplayList` is the backend-agnostic command model.
+- `SkiaRenderBackend` turns the display list into a PNG using SkiaSharp.
+- `HtmlRenderOptions` holds viewport and text defaults.
+- `AngleSharp.Css` provides the render tree and computed-style data used by the renderer.
+
+Current behavior includes block layout, margins, padding, borders, floats, inline-block, relative/fixed/absolute positioning, z-index ordering, outlines, text styling, text alignment, line-height, letter-spacing, text-indent, vertical-align, and generic font-family handling.
+
+## Code Conventions
+
+Follow the repository's existing C# style, which is defined by `.editorconfig` and the existing source files:
+
+- 4 spaces for code files, 2 spaces for `.csproj` files.
+- LF line endings and UTF-8.
+- Trim trailing whitespace.
+- Use `var` where the type is obvious from the right-hand side.
+- Keep changes narrow and consistent with nearby code.
+- Preserve the existing file style instead of reformatting whole files.
+
+## Tests And Snapshots
+
+Tests are split between structural assertions and visual conformance checks.
+
+- Structural tests live in `src/AngleSharp.Renderer.Tests/HtmlRendererTests.cs` and verify the display list directly.
+- Visual tests live in `src/AngleSharp.Renderer.Tests/VisualConformanceTests.cs` and compare PNG output against baselines in `verification-assets/`.
+- Failed visual comparisons write the actual image and a diff image into `failure-assets/`.
+- Missing baselines are auto-created unless `ANGLESHARP_SNAPSHOT_STRICT=1` or `true` is set.
+- CI runs visual tests on both Linux and Windows. To reduce drift, the renderer uses bundled deterministic font files for generic font-family resolution.
+
+When changing renderer behavior, update or add tests first, then run the focused test file or the full test project.
+
+## Repository Notes
+
+- The docs live under `docs/general/` and `docs/tutorials/`; they are the best place to document user-facing renderer behavior.
+- `AGENTS.md` should remain the primary agent note for this repo.
+- The repository already carries a snapshot-based workflow, so visual changes usually require updating the baseline PNGs together with the code change.
+- The Linux Skia setup uses native assets from the main project package references.
+- Keep an eye on `failure-assets/` after test runs; they are useful diagnostics, not source of truth.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0617092..7ab77c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
+# 0.2.0
+
+Released on Friday, July 31 2026.
+
+- Added more drawing modes such as tables, floats, ...
+- Added `WithRendering` extension to register rendering service
+
# 0.1.0
-Released on ?.
+Released on Tuesday, July 28 2026.
- Initial release
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..9f02784
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,8 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+The guidance is shared with every AI agent working here, so it lives in AGENTS.md and is
+imported below. Record new guidance there rather than in this file.
+
+@AGENTS.md
diff --git a/README.md b/README.md
index 10b5680..5bab395 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@ The project now contains a first draft implementation with:
- A backend-agnostic rendering core and display-list model
- A SkiaSharp backend that renders PNG output
- A basic DOM-driven text layout pass (block flow, heading scaling, word wrapping)
+- Basic support for HTML canvas via a bitmap-backed 2D rendering context
This is an initial vertical slice and not a full browser-grade layout engine yet.
@@ -26,7 +27,7 @@ This is an initial vertical slice and not a full browser-grade layout engine yet
using AngleSharp;
using AngleSharp.Renderer;
-var context = BrowsingContext.New(Configuration.Default);
+var context = BrowsingContext.New(Configuration.Default.WithCss().WithRendering());
var document = await context.OpenAsync(req => req.Content(@"
@@ -45,6 +46,8 @@ var image = renderer.RenderToPng(document, new HtmlRenderOptions
await File.WriteAllBytesAsync("render.png", image.Data);
```
+Registering the rendering service with `WithRendering()` is also what enables support for `