# `EmergeSkia.Native`
[🔗](https://github.com/emerge-elixir/emerge/blob/v0.2.1/lib/emerge_skia/native.ex#L1)

NIF bindings for the Skia renderer.

# `configure_assets_nif`

```elixir
@spec configure_assets_nif(
  reference(),
  [String.t()],
  boolean(),
  [String.t()],
  boolean(),
  non_neg_integer(),
  [String.t()]
) :: :ok
```

Configure native asset loading policy and source roots.

# `is_running`

```elixir
@spec is_running(reference()) :: boolean()
```

Check if the renderer is still running.

# `load_font_nif`

```elixir
@spec load_font_nif(String.t(), non_neg_integer(), boolean(), binary()) ::
  {:ok, boolean()} | {:error, String.t()}
```

Load a font from binary data and register it with a name.

## Parameters
- `name` - Font family name to register (e.g., "my-font")
- `weight` - Font weight (100-900, 400=normal, 700=bold)
- `italic` - Whether this is an italic variant
- `data` - Binary font data (TTF file contents)

## Example
    {:ok, data} = File.read("fonts/MyFont-Bold.ttf")
    {:ok, true} = EmergeSkia.Native.load_font_nif("my-font", 700, false, data)

# `measure_text`

```elixir
@spec measure_text(String.t(), float()) :: {float(), float(), float(), float()}
```

Measure text dimensions.

Returns `{width, line_height, ascent, descent}`.

# `render_tree_to_pixels_nif`

```elixir
@spec render_tree_to_pixels_nif(
  binary(),
  map()
) :: binary() | {:ok, binary()} | {:error, String.t()}
```

Render a tree to an RGBA pixel buffer (synchronous, no window).

The tree is provided as an encoded EMRG binary. Asset policy mirrors
`EmergeSkia.start/1`, with an additional offscreen asset mode.

# `render_tree_to_png_nif`

```elixir
@spec render_tree_to_png_nif(
  binary(),
  map()
) :: binary() | {:ok, binary()} | {:error, String.t()}
```

Render a tree to an encoded PNG binary (synchronous, no window).

The tree is provided as an encoded EMRG binary. Asset policy mirrors
`EmergeSkia.start/1`, with an additional offscreen asset mode.

# `renderer_patch`

```elixir
@spec renderer_patch(reference(), binary()) :: :ok
```

Apply EMRG patches, run layout, and render immediately.
Window dimensions come from the initial start config and resize events.

# `renderer_upload`

```elixir
@spec renderer_upload(reference(), binary()) :: :ok
```

Upload a full EMRG tree, run layout, and render immediately.
Window dimensions come from the initial start config and resize events.

# `set_input_mask`

```elixir
@spec set_input_mask(reference(), non_neg_integer()) :: :ok
```

Set the input event mask to filter which events are sent.

Mask bits:
- 0x01: Key events
- 0x02: Codepoint (text input) events
- 0x04: Cursor position events
- 0x08: Cursor button events
- 0x10: Cursor scroll events
- 0x20: Cursor enter/exit events
- 0x40: Resize events
- 0x80: Focus events
- 0xFF: All events

# `set_input_target`

```elixir
@spec set_input_target(reference(), pid() | nil) :: :ok
```

Set the target process to receive input events.

Input events are sent directly to the target process as
`{:emerge_skia_event, event}` messages.

# `set_log_target`

```elixir
@spec set_log_target(reference(), pid() | nil) :: :ok
```

Set the target process to receive native renderer log messages.

Native logs are sent directly to the target process as
`{:emerge_skia_log, level, source, message}` messages.

# `start`

```elixir
@spec start(String.t(), non_neg_integer(), non_neg_integer()) ::
  reference() | {:ok, reference()} | {:error, term()}
```

Start the Skia renderer with a window.

Returns a renderer resource that can be used with other functions.

# `start_opts`

```elixir
@spec start_opts(%{
  backend: String.t(),
  title: String.t(),
  width: non_neg_integer(),
  height: non_neg_integer(),
  drm_card: String.t() | nil,
  drm_startup_retries: non_neg_integer(),
  drm_retry_interval_ms: non_neg_integer(),
  asset_sources: [String.t()],
  asset_runtime_enabled: boolean(),
  asset_allowlist: [String.t()],
  asset_follow_symlinks: boolean(),
  asset_max_file_size: pos_integer(),
  asset_extensions: [String.t()],
  drm_cursor: [
    %{
      icon: String.t(),
      source: String.t(),
      hotspot_x: float(),
      hotspot_y: float()
    }
  ],
  scroll_line_pixels: float(),
  hw_cursor: boolean(),
  input_log: boolean(),
  render_log: boolean(),
  close_signal_log: boolean(),
  renderer_stats_log: boolean()
}) :: reference() | {:ok, reference()} | {:error, term()}
```

Start the Skia renderer with backend options.

Mirrors `EmergeSkia.start/1` keyword options.

# `stop`

```elixir
@spec stop(reference()) :: :ok
```

Stop the renderer and close the window.

# `tree_clear`

```elixir
@spec tree_clear(reference()) :: :ok
```

Clear the tree.

# `tree_is_empty`

```elixir
@spec tree_is_empty(reference()) :: boolean()
```

Check if the tree is empty.

# `tree_layout`

```elixir
@spec tree_layout(reference(), float(), float(), float()) ::
  {:ok, [{binary(), float(), float(), float(), float()}]} | {:error, String.t()}
```

Compute layout for the tree with given width/height constraints and scale factor.

Returns a list of `{id_binary, x, y, width, height}` tuples for all elements.
The id_binary is the Erlang term_to_binary of the element ID.

Scale is applied to all pixel-based attributes (px sizes, padding, spacing,
border radius, border width, font size). Use scale > 1.0 for high-DPI displays.

# `tree_new`

```elixir
@spec tree_new() :: reference()
```

Create a new empty tree resource.

# `tree_node_count`

```elixir
@spec tree_node_count(reference()) :: non_neg_integer()
```

Get the number of nodes in the tree.

# `tree_patch`

```elixir
@spec tree_patch(reference(), binary()) :: {:ok, boolean()} | {:error, String.t()}
```

Apply patches to an existing tree.

# `tree_patch_roundtrip`

```elixir
@spec tree_patch_roundtrip(reference(), binary()) ::
  binary() | {:ok, binary()} | {:error, String.t()}
```

Apply patches to an existing tree and return the encoded EMRG binary.

# `tree_roundtrip`

```elixir
@spec tree_roundtrip(binary()) :: binary() | {:error, String.t()}
```

Decode an EMRG binary in Rust and re-encode it.

# `tree_upload`

```elixir
@spec tree_upload(reference(), binary()) :: {:ok, boolean()} | {:error, String.t()}
```

Upload a full tree from EMRG binary format.
Replaces any existing tree contents.

# `tree_upload_roundtrip`

```elixir
@spec tree_upload_roundtrip(reference(), binary()) ::
  binary() | {:ok, binary()} | {:error, String.t()}
```

Upload a full tree and return the encoded EMRG binary.

# `video_target_new`

```elixir
@spec video_target_new(
  reference(),
  String.t(),
  pos_integer(),
  pos_integer(),
  String.t()
) ::
  reference() | {:ok, reference()} | {:error, String.t()}
```

Create a renderer-owned video target.

# `video_target_submit_prime`

```elixir
@spec video_target_submit_prime(reference(), map()) ::
  {:ok, boolean()} | {:error, String.t()}
```

Submit a DRM Prime descriptor to a video target.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
