view infinite_canvas/docs/rendering.md @ 278:8d560f50ed4c

Improve infinite canvas interactions and browser chrome Render Lucide icons directly with Raylib, add searchable icon browsing, robust text editing, entity lifecycle animations, z-order-safe input, semantic themes, and animated editable browser controls. Document rendering, pinning, context, and component extension for future agents. Co-authored-by: Copilot <[email protected]> Copilot-Session: f68442b1-fa8f-46a0-9689-81710613bbd4
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 22:16:14 -0700
parents
children
line wrap: on
line source

# Rendering Surfaces

## Choose the renderer by content

| Content | Entity type | Native | WebAssembly |
| --- | --- | --- | --- |
| Shapes, text, controls | regular `CANVAS_ENTITY_*` | Raylib | Raylib/WASM |
| Lucide icons | `CANVAS_ENTITY_LUCIDE_GALLERY` | Raylib line segments | Raylib/WASM line segments |
| Image URL or file | `CANVAS_ENTITY_IMAGE` | CEF off-screen pixels uploaded to a Raylib texture | positioned `<img>` overlay |
| Live web page | `CANVAS_ENTITY_WEB_CONTENT` | CEF off-screen pixels uploaded to a Raylib texture | positioned `<iframe>` overlay |

Do not route vector icons or ordinary components through CEF. They belong in
`Canvas_Draw_Entity()` so they inherit camera transforms, theme colors,
selection, dragging, pinning, and context behavior without another rendering
runtime.

## Raylib entities

`Canvas_Draw_World()` opens one `BeginMode2D()` camera and draws every retained
entity through `Canvas_Draw_Entity()`. Components such as buttons, dropdowns,
cards, calendars, tables, and switches are immediate Raylib draw calls backed
by state in `Canvas_Entity`.

The scene-array order is the z-order. The main frame interleaves each Raylib
entity layer with its native CEF/image texture, so a later button can genuinely
draw over and receive input ahead of an earlier browser surface. Picking and
native browser input both resolve the same reverse scene order.

The Lucide gallery follows the same path. The generator
`tools/generate_lucide_data.mjs` downloads pinned Lucide 1.31.0 definitions,
flattens SVG paths and primitives into line segments, and writes
`generated/lucide_data.h`. The gallery virtualizes rows: only cards fully inside
its visible body issue Raylib draw calls. Its Raylib search field filters icon
names case-insensitively and resets the internal scroll offset when edited.

Regenerate after changing the pinned icon version:

```bash
node infinite_canvas/tools/generate_lucide_data.mjs
```

## Native image and web surfaces

`web_surface_native.cc` maintains a pool of at most `CANVAS_MAX_WEB_VIEWS`
off-screen CEF browsers. Visible image and web entities are reconciled by stable
entity ID. CEF paint callbacks fill arena-owned RGBA buffers; `Sync()` creates or
updates Raylib textures; `Draw()` composites those textures into the
camera-derived screen bounds.

Resolution follows displayed size in stable buckets and is capped. Off-screen
entities release their active pool slot, small background views receive lower
frame rates, and the focused view receives the largest frame budget.

When a web entity is selected, C reserves a fixed-screen-height toolbar above
the page viewport. The reserved height and toolbar clip animate together so
selection pushes the page down like an opening accordion and deselection pulls
it back up. Raylib draws the themed editable address field and Lucide
navigation icons after that entity's CEF texture, preserving scene z-order.
The URL editor retains its own draft, caret, selection, horizontal scroll, and
clipboard focus; committing updates the entity URL, which triggers backend
navigation. CEF reports main-frame address changes and history availability
back to the toolbar.
CEF emulates the canvas `prefers-color-scheme` value and updates the page
`color-scheme` when the canvas theme changes.

Images use a bundled `image-view.html` wrapper for `object-fit: contain`.
Filesystem paths are resolved to `file://`; URLs remain URLs.

## WebAssembly image and web surfaces

`web_surface_web.c` cannot composite cross-origin page pixels into WebGL, so it
positions DOM overlays over the Raylib canvas. It creates `<img>` elements for
images and sandboxed `<iframe>` elements for live pages, converts Raylib screen
coordinates to CSS coordinates, and removes overlays that are no longer
visible.

Selected iframe entities use the same Raylib toolbar geometry and move the DOM
viewport below it. The iframe element receives the canvas `color-scheme`.
History navigation is best-effort because cross-origin iframe history and
address inspection remain browser-controlled; the displayed URL falls back to
the entity's configured URL.

This is intentionally different from native. Shared scene semantics live in C;
the platform backend owns only presentation and input details.