Skip to main content

Crate crabshell_render

Crate crabshell_render 

Source
Expand description

Draws Crabshell windows on the CPU: backgrounds, rounded corners, borders and opacity with tiny-skia, glyphs from cosmic-text, and icons from SVG, PNG or raw pixels. Only what changed is repainted.

The platform keeps one Renderer, a DamageHistory per window and a BufferAge per buffer. Each frame it hands the renderer the window’s view and damage and a Canvas over the buffer’s memory, and reports the returned rectangles to the compositor:

use crabshell_reactive::Runtime;
use crabshell_render::{BufferAge, Canvas, DamageHistory, PixelFormat, Renderer};
use crabshell_ui::prelude::*;

let runtime = Runtime::current();
let cx = Cx::new(runtime.new_owner());
let bar = PanelWindow::new(&Output::new("DP-1"))
    .style(Style::new().background(Color::rgb(0x1e, 0x1e, 0x2e)))
    .child(Text::new("hello"));
let window = Window::new(&cx, bar);
let mut text = TextSystem::new();
window.set_size(Size::new(200.0, 30.0));
runtime.flush();
window.layout(&mut text);

let mut renderer = Renderer::new();
let mut history = DamageHistory::new();
let mut age = BufferAge::default();
let scale = 1.5;
let (width, height) = (300, 45); // 200 x 30 logical pixels at 1.5
let mut buffer = vec![0; width * height * 4];
let damage = window.take_damage();
let report = renderer.draw(
    &window.view(),
    &damage,
    &mut text,
    &mut history,
    Canvas {
        pixels: &mut buffer,
        width: width as u32,
        height: height as u32,
        scale,
        format: PixelFormat::Argb8888,
        age: &mut age,
    },
)?;
assert_eq!(report.len(), 1); // a new buffer is drawn whole

§How it works

  • Damage arrives in logical pixels and becomes buffer pixels, rounded outward. Overlapping areas are merged, a buffer that skipped frames also repaints what changed in them, and when more than half of the buffer is dirty, all of it is repainted.
  • The areas are drawn from scratch in 64-pixel tiles of a fixed grid, each into an RGBA pixmap of its own that clips the drawing, and copied into the buffer in the buffer’s byte order. A pixel is always drawn in the same tile, so a repaint gives the same pixels as drawing everything, even where a tile’s edge cuts a curve.
  • Rectangles snap to whole pixels, so edges stay sharp at fractional scales. A border is drawn inside the edge. Opacity applies to a widget and everything inside it as one layer.
  • Text is drawn from the cosmic-text buffer layout measured, as grayscale masks, with the baseline on a whole pixel. It isn’t clipped: the window’s damage covers text that overflows its widget.
  • Icons are rasterized at their size in pixels and cached by source and that size.

Structs§

BufferAge
The frame a buffer last held. Keep one next to each buffer, starting with BufferAge::default for a new one.
Canvas
A buffer to draw a window into.
CanvasError
A canvas whose bytes don’t fit its size, or whose scale isn’t a positive number.
DamageHistory
What changed in one window’s recent frames. Keep one per window.
PixelRect
A rectangle of buffer pixels.
Renderer
Draws windows. One serves every window; it holds the glyph and icon caches.

Enums§

PixelFormat
How a buffer stores each pixel, as wl_shm names the formats. Both are 32 bits per pixel with premultiplied alpha.

Constants§

DEFAULT_ICON_THEME
The theme icon names are looked up in when the config doesn’t set one.