incular-rendering 0.1.1

Renderer-neutral scene, canvas, display-list, and compositor APIs for Incular
Documentation
# incular-rendering

## Architecture and support

| Contract | Status |
| --- | --- |
| Ownership | Renderer-neutral commands, paths, canvas and retained compositor layers. |
| API class | backend; re-exports and path overrides follow the [architecture contract]https://github.com/FabortLabs/incular/blob/master/system-design/ARCHITECTURE.md. |
| Support | Available; backend resources belong to WGPU. |

`incular-rendering` owns Incular's renderer-neutral presentation boundary:
paths, brushes, ordered display lists, canvas recording, and retained
compositor layers. It intentionally contains no window, surface, or GPU state.

Paths are retained as `kurbo::BezPath` values: Kurbo supplies tight quadratic
and cubic bounds plus winding queries, while `incular-wgpu` translates those
same elements directly to Lyon for tessellation. `incular_core::Transform`
uses Kurbo affine composition/inversion while retaining Incular's `f32`
`Offset` and `Rect` values at the public layout boundary.

Backends such as `incular-wgpu` consume these values and remain responsible for
physical DPI conversion, resource allocation, and submission. The public facade
also exposes this crate as `incular::painting` for application-facing naming.

Display lists can also carry balanced `SurfacePartitionId` markers. They are
renderer-neutral no-ops during ordinary in-view rendering, but a multi-surface
host can detach selected retained subtrees while preserving painter order and
nested partition ownership. This is the boundary used by desktop transient
surfaces: rendering owns partition identity/command separation, while native
window creation and GPU-surface policy remain outside this crate.

## Display-list and compositor contract

`incular-rendering` owns compact ordered `DisplayList` and `PaintCommand` values. It depends on
renderer-neutral core/assets types and contains no GPU state. `GlyphRun` holds
the selected font and shaped glyph positions rather than characters, so a
backend can rasterize/draw without reshaping. Render objects cache local lists;
backends must preserve command order, transforms, and rectangular clips when
lowering rectangle and glyph operations.

`PaintCommand::Image` carries an `ImageHandle`, a pixel-space source rectangle,
and a local logical destination rectangle. It follows normal painter order,
transforms, and clipping without exposing GPU resources.

`LayerTree` stores stable generational `Picture`, `Transform`, and
`ClipRect` layers. Pictures retain `Arc<DisplayList>` payloads, transforms and
clips change independently, and flattening produces only the transient ordered
submission stream. Bounds-driven rectangular culling is conservative.

## Coordinate spaces and transform composition

Pictures contain local logical commands only. Parent-relative layout placement
and compositor-only movement are transform layers, accumulated by `flatten` to
world logical coordinates exactly once. Clip rectangles are transformed into
that same world space before culling. `flattened_pictures()` provides the local
bounds, world bounds, and active clip observed during the latest flattening for
CPU regression tests; physical DPI conversion belongs exclusively to a backend.

## Retained opacity isolation

`LayerTree` also retains an `Opacity` isolation layer. It owns only a
normalized alpha value and a stable content generation; it never owns a GPU
texture or render pass. Flattening emits `PushOpacity`/`PopOpacity` around the
child stream together with conservative subtree bounds and a generation. A
backend can therefore render the child stream into a tight transparent target
and composite that result once, while an alpha-only change remains a
compositor update. A clip inside the layer is part of the cached child stream;
a clip above it remains active when the group quad is composited.

## Gaussian effects

`GaussianBlur` and `DropShadowEffect` are renderer-neutral descriptions. Their
sigma values are logical pixels and are normalized (`< 0` and non-finite values
become zero); the backend multiplies them by the active DPI scale before
building a kernel. `LayerTree` emits `PushBlur`/`PushDropShadow` and a matching
`PopEffect`, while the source subtree's generation remains independent of its
effect parameters. This lets a compositor update sigma, shadow offset, or
shadow color without repainting the child display list. A zero-sigma blur is an
identity and does not require an isolation target.

Bounds use a finite three-sigma support: a blur expands a source by
`3 * sigma_x/y`, and a shadow unions the source with the offset, expanded source
rectangle. These are conservative logical bounds; physical target dimensions
are rounded outward by the backend. Effects do not change hit testing or
semantics geometry, and they contain no renderer or GPU resources.

Effect layers preserve command order and nesting. Clips inside an effect are
rendered into its isolated source; clips above the effect remain active when
the final result is composited. The source is therefore still an ordinary
retained display-list subtree rather than a special box-only shadow primitive.

## Color filters, blend modes, and effect chains

`ColorFilter` is a renderer-neutral 4×5 matrix over normalized straight RGBA.
`apply` uses zero RGB for transparent input, clamps/sanitizes all results, and
zeros RGB when the output alpha is zero. The GPU converts retained
premultiplied pixels to this straight representation, applies the matrix, and
premultiplies the result again. `identity`, `grayscale`, `sepia`, `brightness`,
`contrast`, `saturate`, `invert`, and `opacity` cover common adjustments.
`ColorFilter::then` composes `B(A(x))` as `B * A`, including the affine bias.

`EffectChain` is an ordered list of single-input stages. `optimized` fuses only
adjacent color matrices; blur remains a separate spatial stage, so
`color → blur → color` cannot be reordered or collapsed. Drop shadows remain a
separate multi-output layer because they emit both a shadow and the original
source. Pure color and blend stages do not expand visual bounds.

`BlendMode` defines Porter–Duff and separable artistic modes over normalized
premultiplied pixels. The public `blend_premultiplied` reference follows the
alpha-aware equation used by the GPU and is safe for zero-alpha inputs. A
blend-mode property belongs to the final composite state: it does not change
the source generation or invalidate upstream filter pixels.