Skip to content

Images

The two ways to put a picture on the panel: an Image, a 1-bit bitmap you ship with the application, and an Icon, which the host draws from its own registry when handed an IconRef. An image is exactly its own bits and its own size; an icon's glyph and size are the host's answer, so nothing is scaled and nothing is guessed.

A book row: a book icon in outline beside Middlemarch in bold over George Eliot in the small interface face, and a bookmark ribbon at the far edge

Text and fonts is the other half of what puts something on the panel. Canvas and chrome is how a host draws the bitmaps and icons these name. This page is what each piece does.

ImageA 1-bit bitmap.
IconAn icon from the host's registry.
IconRefAn icon the host owns.

A 1-bit bitmap.

pub struct Image

A small solid bookmark ribbon beside the word Bookmarked

A picture you ship yourself, where an Icon is one the host ships.

The buffer format. Row-major, top row first, most significant bit first within each byte, (width + 7) / 8 bytes per row, with each row padded on its own. Bit 0 is ink and bit 1 is white. That is inverted from the usual convention, so a buffer produced elsewhere will very likely render as a negative.

It is borrowed, not copied. Assets are arrays in flash, and copying one onto a small heap to draw it is waste, so the data is &'static.

It is exactly its own size. Nothing scales a bitmap, so it measures as its width and height whatever it is offered. A buffer too short for those dimensions measures zero and draws nothing, rather than being read past its end.

Example — a bookmark from sixteen rows

Written with 1 as ink, which reads, and inverted as it is packed.

Rust
use xpui::{Alignment, HStack, Image, Text, hstack};
const RIBBON: [u16; 16] = [
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111111111100,
0b0011111001111100,
0b0011110000111100,
0b0011100000011100,
0b0011000000001100,
0b0010000000000100,
];
static BOOKMARK: [u8; 32] = {
let mut bytes = [0; 32];
let mut row = 0;
while row < 16 {
let [high, low] = (!RIBBON[row]).to_be_bytes(); // bit 0 is ink
bytes[row * 2] = high;
bytes[row * 2 + 1] = low;
row += 1;
}
bytes
};
let row: HStack<()> =
hstack![8; Image::new(&BOOKMARK, 16, 16), Text::new("Bookmarked")].align(Alignment::Center);

Example — a buffer too short for its size

Rust
use xpui::{Image, Size, View};
static SHORT: [u8; 4] = [0; 4];
let mut image = Image::new(&SHORT, 16, 16); // needs 32 bytes
View::<()>::measure(&mut image, Size::new(480, 800));
assert_eq!(View::<()>::size(&image), Size::ZERO);

Wraps a bitmap of width x height pixels.

pub fn new(data: &'static [u8], width: i32, height: i32) -> Self
ParameterMeaning
dataThe packed rows, in the format above. Longer than needed is fine.
widthPixels across. Each row takes (width + 7) / 8 bytes.
heightRows.

See also: Icon

An icon from the host's registry.

pub struct Icon

Four icons in a row: a sun in outline, the same sun solid, a book in outline, and a smaller solid battery

An icon is chosen by what it means, not by file name. The framework passes the host an opaque IconRef, and the host decides which glyph that is. A backend publishes its own names and converts them into an IconRef, so a screen writes Icon::new(Glyph::Sun) and never a number. The picture above is drawn by the gallery's backend, whose glyphs are lines and rectangles.

BuilderSetsWhen not called
Icon::newwhich icon—
filledsolid rather than outlinethe icon's first variant
sizethe edge length asked for32 pixels

Its size is the host's answer. An icon measures as the edge the host says it would draw, square. An icon the host ships nothing for measures zero and draws nothing, rather than painting something arbitrary at a guessed size.

It is kept apart from Image because the two use different asset conventions and are not interchangeable. An icon to switch on and off is IconToggle, in controls.

Example — a backend's glyphs

Rust
use xpui::{Icon, IconRef};
/// What a backend publishes. The framework only ever sees the number.
#[derive(Copy, Clone)]
enum Glyph {
Sun = 0,
Book = 11,
}
impl From<Glyph> for IconRef {
fn from(glyph: Glyph) -> IconRef {
IconRef::new(glyph as u16)
}
}
let light_on = true;
let outline_or_solid = Icon::new(Glyph::Sun).filled(light_on); // solid means on
let small = Icon::new(Glyph::Book).size(24); // outline, the first variant

Example — an icon beside its label

Centre a row that mixes an icon with a line of text, or the text hangs off the top.

Rust
use xpui::{Alignment, Font, HStack, Icon, IconRef, Spacer, Text, VStack, hstack, vstack};
let book: HStack<()> = hstack![12;
Icon::new(Glyph::Book),
vstack![4; Text::new("Middlemarch").bold(), Text::new("George Eliot").font(Font::ui_small())],
Spacer::new(),
]
.align(Alignment::Center);

An icon for a role, asking the host for a 32-pixel edge.

pub fn new(icon: impl Into<IconRef>) -> Self

Solid rather than outline, where the role has both variants.

pub fn filled(self, filled: bool) -> Self
ParameterMeaning
filledtrue asks for variant 1, solid. false asks for variant 0, outline.

Solid for on and outline for off is the convention, which is why this takes a bool: .filled(self.light_on). An icon with one variant draws the same either way.

Preferred edge length; the host draws the nearest size it ships.

pub fn size(self, size: i32) -> Self
ParameterMeaning
sizeIn pixels. The host may round it, or answer zero for a size too small to draw.

See also: IconRef, Image

An icon the host owns.

pub struct IconRef

Deliberately opaque numbers: which glyph they select is the host's business, and naming them in the framework would tie it to one product's assets. This is what an Icon hands the host to measure and to draw.

Field
IconRef::kindWhich icon, in whatever numbering the host uses.
IconRef::variantA variant of the same icon, where the host offers one (solid vs outline).
IconRef::sizePreferred edge length; the host picks the nearest size it ships.

A backend's own enum of glyphs, converted with From, is how a screen names one; see the example on Icon. The fields are public so a host can read them.

Rust
use xpui::IconRef;
let battery = IconRef::new(9);
assert_eq!((battery.kind, battery.variant, battery.size), (9, 0, 32));
let solid_and_small = IconRef { variant: 1, size: 16, ..battery };
assert_eq!(solid_and_small.kind, 9);

Icon kind in its first variant, asking for a 32-pixel edge.

pub fn new(kind: u16) -> Self

See also: Icon