Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

image

A picture from a file: wallpapers, album art, avatars, thumbnails. It can decode off-thread, hold the previous picture while a new one loads, and cross-fade or run a shader between them. For theme icons, use an icon.

SVG and SVGZ <text> use the fonts loaded by Mantle. Declare required families in fonts { ... }; text without a family uses the chain’s primary font. Generic names use the families declared in the chain. An unavailable family falls back to the loaded serif family, or the primary if none is loaded. SVG text uses SVG layout and shaping, so its spacing can differ from a text node. Images, icons and file masks share this behavior, including background decoding.

A wallpaper that crossfades when the path changes:

local path = state("wallpaper", "/usr/share/backgrounds/a.jpg")

return { panel {
    id = "wallpaper",
    layer = "background",
    anchor = { top = true, bottom = true, left = true, right = true },
    width = "fill",
    height = "fill",
    child = image {
        id = "wallpaper_image", -- keeps the node, and so the held picture, across source changes
        source = path,
        async = true,
        transition = { duration = 600, easing = "in_out_cubic" },
        width = "fill",
        height = "fill",
    },
} }

Properties

image takes the common properties, plus:

PropertyTypeDefaultBehaviour
sourcestring|Bound""A file path (mantle.config_dir .. "/img/a.png", or ~/ under $HOME), never a theme name; "" draws nothing. PNG, JPEG, WebP, GIF, ICO, BMP, SVG or SVGZ; animated GIF, WebP and APNG loop
fit"cover"|"contain"|"stretch"|Bound"cover""cover" fills the box and crops, "contain" fits inside it, "stretch" distorts to it
asyncboolean|Boundfalsefalse decodes in the frame that first draws it. true decodes on a worker and draws nothing until the first decode lands. A resize keeps drawing the previous size, scaled, until the new size decodes; use it for many or large images
retainboolean|BoundfalseKeep drawing the last picture while a new source decodes, and on a failed decode. Needs async = true and a stable id
transitionTransition|BoundNoneCross from the held picture to each newly decoded source. Implies retain; needs async = true and a stable id. Unknown keys are refused. See transition
source_blurnumber|Bound, [0, 8192]0Blur sigma in px, baked into the pixels once at decode (three box passes approximating a Gaussian); see blurs. Animations ignore it. Under async, a change blanks the image until the re-decode lands; retain does not cover it
radiusnumber|Corners|Bound, [0, 8192]0Corner radius px of the drawn picture, as rect.radius: a number sets all four corners, a missing corner is 0, corners too big for a side shrink together. Rounds the visible picture, so "contain" rounds the fitted picture, not the box. Hit-testing ignores it
corner_smoothingnumber|Bound, [0, 1]0Continuous corners on the drawn picture, as rect.corner_smoothing. The shader that rounds a transition approximates a smoothed corner by a superellipse through its endpoints and midpoint
playingboolean|Boundtruefalse holds an animation on its current frame, the first if it never played, and stops its frame requests; true resumes from there. Per node: another image showing the same file plays on, and a node keeps its place while scrolled out or resized. Stills ignore it
statusBoundNoneAn image_status(name) signal. The engine writes the load of source; see load status

transition

FieldValuesDefaultBehaviour
durationms, [1, 60000]RequiredLength of the cross
easingAn easing"in_out_quad"Drives u_progress
shaderAbsolute, or ~/ under $HOME, .frag pathBuilt-in cross-dissolveReplaces the dissolve. Recompiled when the file changes
params{ name = number | { up to 4096 numbers } }{}Uniforms for that shader, as on a shader node. Refused without shader
images{ name = "/abs/path.png" }{}Up to 8 rasters to sample by name, with the rules of a shader node’s images; they take the units after u_from and u_to. Refused without shader

The first picture appears without a transition. A transition shader gets everything a shader node gets, plus:

NameWhat
mantle_from(uv), mantle_to(uv)Outgoing and incoming picture at a box coordinate, premultiplied, already placed by fit; transparent outside the picture
u_from_rect, u_to_rectEach picture’s (x, y, w, h) in box fractions; may pass 0..1 under "cover"

u_progress is the eased progress 0..1. A transition shader that fails to build logs once and the node falls back to the cross-dissolve.

Load status

status = image_status("name") reports whether source is loading, ready (with the file’s own size) or failed: see image_status.

How do I…

TaskAnswer
Crossfade a wallpaperThe example above: async, transition and a stable id
Wipe instead of fadetransition = { duration = 700, shader = mantle.config_dir .. "/shaders/wipe.frag" } with a .frag that mixes mantle_from and mantle_to
Round an image’s cornersBelow
Make a circular avatarThe same, with radius half the size (paint)
Show many thumbnails without stutterasync = true on each, in a list
Blur a wallpaper oncesource_blur = 20
Freeze an animation until askedplaying = live, a boolean state the config turns on
Show a file that ships with the configsource = mantle.config_dir .. "/img/logo.png"
Fade in once decoded, show a load error or a resolutionLoad status

Round an image’s corners

radius rounds the picture itself, as on a rect, so it needs no clipping wrapper. It rounds what shows: with fit = "contain" that is the fitted picture, not the box.

image {
    width = 96,
    height = 96,
    radius = 12,
    source = "/usr/share/backgrounds/a.jpg",
    fit = "cover",
    async = true,
}

Gotchas

TrapFix
The image does not appearIt has no intrinsic size. Give width and height
An image flashes blank when its source changes despite retainretain needs async = true and a node that survives: give it a stable id
The shell stutters while images loadInline decode blocks drawing. Set async = true
source = "firefox" draws nothingsource is a path. Use icon for theme names
A relative source draws nothingIt resolves against the Renderer’s working directory, not the config. Build paths from mantle.config_dir
transition.params or transition.images is refusedBoth need a shader
An animation restarts from its first framePlayback, playing included, is per node and file: a new source, or the node leaving the tree (its surface closes, a list drops it), starts it again
Two nodes on one animation show each other’s framePast the texture budget, or eight nodes on one file and size, nodes share one texture

See also: icon, shader, paint, animation.

Source: vocabulary, content parsers, transition, shader stage, decode, animation.