Crate forma_render
source ·Expand description
forma is a high-performance vector-graphics renderer with a CPU & GPU back-end.
Example
The following example renders two overlapping rectangles and highlights the most common API usage:
use forma::{cpu::{buffer::{BufferBuilder, layout::LinearLayout}, Renderer, RGBA}, prelude::*};
fn rect(x: f32, y: f32, width: f32, height: f32) -> Path {
PathBuilder::new()
.move_to(Point::new(x, y))
.line_to(Point::new(x + width, y))
.line_to(Point::new(x + width, y + height))
.line_to(Point::new(x, y + height))
.build()
}
fn solid(r: f32, g: f32, b: f32) -> Props {
Props {
func: Func::Draw(Style {
fill: Fill::Solid(Color { r, g, b, a: 1.0 }),
..Default::default()
}),
..Default::default()
}
}
// The composition is akin to a `HashMap<Order, Layer>`. Layers can be inserted and
// removed from the composition by their orders.
let mut composition = Composition::new();
let mut renderer = Renderer::new();
// The layer cache enables updating only tiles that changed from last frame.
let layer_cache = renderer.create_buffer_layer_cache().unwrap();
composition
.get_mut_or_insert_default(Order::new(0).unwrap())
.insert(&rect(50.0, 50.0, 100.0, 50.0))
.set_props(solid(1.0, 0.0, 0.0));
composition
.get_mut_or_insert_default(Order::new(1).unwrap())
.insert(&rect(100.0, 50.0, 100.0, 50.0))
.set_props(solid(0.0, 0.0, 1.0));
let width = 250;
let height = 150;
let mut buffer = vec![0; width * height * 4]; // 4 bytes per pixel.
renderer.render(
&mut composition,
// Stride is width * 4 bytes per pixel.
&mut BufferBuilder::new(&mut buffer, &mut LinearLayout::new(width, width * 4, height))
.layer_cache(layer_cache.clone())
.build(),
RGBA,
Color { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
None,
);
// Background is white.
assert_eq!(buffer.chunks(4).next().unwrap(), [255, 255, 255, 255]);
// First rectangle is red.
let index = 75 + 75 * width;
assert_eq!(buffer.chunks(4).nth(index).unwrap(), [255, 0, 0, 255]);
// Overlap is blue.
let index = 125 + 75 * width;
assert_eq!(buffer.chunks(4).nth(index).unwrap(), [0, 0, 255, 255]);
// Second rectangle is blue.
let index = 175 + 75 * width;
assert_eq!(buffer.chunks(4).nth(index).unwrap(), [0, 0, 255, 255]);
Reusing the composition
For best possible performance, reusing the composition is essential. This may mean that in some cases one might have to remove, then re-insert some layers around in order to achieve the desired ordering of layers.
For simple cases, Layer::set_is_enabled can provide an alternative to removing and re-inserting layers into the composition.
Modules
Structs
A composition is an ordered collection of
Layer
s. It is the only means through which
content can be rendered.A layer is a reusable collection of geometry (i.e.
Path
s) with common properties and
order in the paint stack.