# Apply themes and slots
Restyle a dotLottie animation at runtime from C - apply packaged or custom themes, and override colors, text, images, and numbers through slots.

Two mechanisms change how an animation looks without editing the animation itself. **Themes** apply a named set of overrides packaged in the `.lottie` file. **Slots** override individual named properties one at a time from your code.

Reach for a theme when a designer has already defined the variants you need, and for slots when the values come from your application — a user's accent color, a username, a score.

Both need a `.lottie` file. Plain Lottie JSON carries neither themes nor slot definitions.

## Themes

Theming requires the `theming` feature, which is enabled by default.

Apply a theme packaged in the loaded file by its ID:

```c
if (dotlottie_set_theme(player, "dark") != DOTLOTTIE_SUCCESS) {
  /* no such theme, or the file has none */
}
```

Return to the animation's original appearance:

```c
dotlottie_reset_theme(player);
```

Check which theme is active using the two-call string pattern:

```c
size_t size = 0;
if (dotlottie_get_theme_id(player, NULL, &size) == DOTLOTTIE_SUCCESS) {
  char *theme = malloc(size);
  dotlottie_get_theme_id(player, theme, NULL);
  /* ... */
  free(theme);
}
```

This returns `InvalidParameter` when no theme is applied.

### Themes defined in your code

To supply a theme the file doesn't contain, pass its JSON directly:

```c
const char *theme_json =
  "{\"id\":\"brand\",\"rules\":["
  "{\"id\":\"primary\",\"type\":\"Color\",\"value\":[0.1,0.4,0.9,1.0]}"
  "]}";

dotlottie_set_theme_data(player, theme_json);
```

The animation still has to define the slots the rules target, so this replaces the theme's _values_, not the animation's structure.

<Callout type="info" title="Switching animations clears the theme">
  Calling `dotlottie_load_animation()` to switch to another animation in a multi-animation file resets the active theme.
  Reapply it afterwards.
</Callout>

## Slots

A slot is a named, overridable property that the animation's author exposed. Setting one replaces that property's value everywhere it appears.

### Discover the available slots

Slot IDs come from the animation, so enumerate them rather than guessing:

```c
uint32_t count = 0;
dotlottie_get_slot_ids_count(player, &count);

for (uint32_t i = 0; i < count; i++) {
  size_t size = 0;
  dotlottie_get_slot_id(player, i, NULL, &size);

  char *id = malloc(size);
  dotlottie_get_slot_id(player, i, id, NULL);

  size_t type_size = 0;
  dotlottie_get_slot_type(player, id, NULL, &type_size);

  char *type = malloc(type_size);
  dotlottie_get_slot_type(player, id, type, NULL);

  printf("%s (%s)\n", id, type);

  free(type);
  free(id);
}
```

### Set a slot by type

Each slot has a type, and there is a typed setter for each:

| Slot type  | Function                         | Values                      |
| ---------- | -------------------------------- | --------------------------- |
| `color`    | `dotlottie_set_color_slot()`     | Three floats, `0.0`–`1.0`   |
| `scalar`   | `dotlottie_set_scalar_slot()`    | One float                   |
| `text`     | `dotlottie_set_text_slot()`      | A null-terminated string    |
| `vector`   | `dotlottie_set_vector_slot()`    | Two floats                  |
| `position` | `dotlottie_set_position_slot()`  | Two floats                  |
| `image`    | `dotlottie_set_image_slot_src()` | A source string — see below |

```c
dotlottie_set_color_slot(player, "accent", 0.1f, 0.4f, 0.9f);
dotlottie_set_scalar_slot(player, "stroke-width", 4.0f);
dotlottie_set_text_slot(player, "username", "Ada Lovelace");
dotlottie_set_position_slot(player, "badge-anchor", 120.0f, 48.0f);
```

<Callout type="warning" title="Slot colors are floats, background is bytes">
  `dotlottie_set_color_slot()` takes floats from `0.0` to `1.0` and has no alpha parameter, while
  `dotlottie_set_background()` takes four 8-bit values from `0` to `255`. Passing `255.0f` to a color slot does not
  produce white.
</Callout>

### Image slots

An image slot accepts three source forms:

```c
dotlottie_set_image_slot_src(player, "avatar", "data:image/png;base64,iVBORw0KG...");
dotlottie_set_image_slot_src(player, "avatar", "https://example.com/avatar.png");
dotlottie_set_image_slot_src(player, "avatar", "profile.png");   /* from the file's i/ folder */
```

A bare filename resolves against the `i/` folder inside the loaded `.lottie` archive. Decoding the replacement needs the matching codec feature — `tvg-png`, `tvg-jpg`, or `tvg-webp`. Without it, the image silently fails to draw.

### Setting many slots at once

For anything beyond simple static values — gradients, or keyframed values that animate — set slots from JSON:

```c
const char *slots =
  "{"
  "  \"accent\": {\"p\": {\"a\": 0, \"k\": [1.0, 0.0, 0.0]}},"
  "  \"caption\": {\"p\": {\"k\": [{\"t\": 0, \"s\": {\"t\": \"Hello\"}}]}}"
  "}";

dotlottie_set_slots_str(player, slots);
```

This is the most capable form of the slot API and matches the format used by the other dotLottie players. A single slot can be set the same way with `dotlottie_set_slot_str()`.

### Reading current values

```c
size_t size = 0;
dotlottie_get_slots_str(player, NULL, &size);

char *json = malloc(size);
dotlottie_get_slots_str(player, json, NULL);
/* ... */
free(json);
```

`dotlottie_get_slot_str()` does the same for one slot.

### Removing overrides

Two functions undo slot changes, and the difference is bookkeeping rather than appearance:

| Function                  | Effect                                                                               |
| ------------------------- | ------------------------------------------------------------------------------------ |
| `dotlottie_reset_slot()`  | Sets the slot back to the animation's original value, keeping it in the override set |
| `dotlottie_clear_slot()`  | Removes your override for the slot entirely                                          |
| `dotlottie_reset_slots()` | Resets every slot to its original value                                              |
| `dotlottie_clear_slots()` | Removes all overrides                                                                |

Either restores the animation's original look. Use `clear` when you want the slot to disappear from `dotlottie_get_slots_str()` output, and `reset` when you want it listed with its default. `dotlottie_reset_slot()` fails if the slot has no recorded default — usually a typo in the ID.

## Redraw after changing appearance

Theme and slot changes take effect on the next render. A playing animation picks them up on its next tick, but a paused or stopped one needs an explicit redraw:

```c
dotlottie_set_color_slot(player, "accent", 0.9f, 0.2f, 0.2f);
dotlottie_render(player);
```

## Learn more

- [Load animations](/en/runtimes/distributions/native/v0.x/loading-animations) — getting a `.lottie` file in
- [State machines](/en/runtimes/distributions/native/v0.x/state-machines) — drive theme and slot changes from interaction
- [C API reference](/en/runtimes/distributions/native/v0.x/api-reference) — full signatures
