blob: 26df9c91954970fe985519579476b30482de2636 [file] [log] [blame] [edit]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::time::Duration;
use forma::{
buffer::{layout::LinearLayout, BufferBuilder, BufferLayerCache},
Color, Composition, CpuRenderer, RGB1,
};
use wasm_bindgen::{prelude::*, Clamped};
#[path = "../../demo/src/demos/circles.rs"]
pub mod circles;
#[path = "../../demo/src/demos/rive.rs"]
pub mod rive;
mod utils;
use circles::Circles;
use rive::Rive;
pub use wasm_bindgen_rayon::init_thread_pool;
trait App {
fn width(&self) -> usize;
fn height(&self) -> usize;
fn set_width(&mut self, width: usize);
fn set_height(&mut self, height: usize);
fn compose(&mut self, composition: &mut Composition, elapsed: Duration, keyboard: &Keyboard);
}
struct Keyboard;
#[wasm_bindgen]
pub struct Context {
composition: Composition,
renderer: CpuRenderer,
layout: LinearLayout,
layer_cache: BufferLayerCache,
app: Box<dyn App>,
buffer: Vec<u8>,
width: usize,
height: usize,
was_cleared: bool,
}
#[wasm_bindgen]
pub fn context_new_circles(width: usize, height: usize, count: usize) -> Context {
utils::set_panic_hook();
let buffer = vec![0u8; width * 4 * height];
let layout = LinearLayout::new(width, width * 4, height);
let composition = Composition::new();
let mut renderer = CpuRenderer::new();
let layer_cache = renderer.create_buffer_layer_cache().unwrap();
let app: Box<dyn App> = Box::new(Circles::new(count));
Context {
composition,
renderer,
layout,
layer_cache,
app,
buffer,
width,
height,
was_cleared: false,
}
}
#[wasm_bindgen]
pub fn context_new_rive(width: usize, height: usize, rive_buffer: Vec<u8>) -> Context {
utils::set_panic_hook();
let buffer = vec![0u8; width * 4 * height];
let layout = LinearLayout::new(width, width * 4, height);
let composition = Composition::new();
let mut renderer = CpuRenderer::new();
let layer_cache = renderer.create_buffer_layer_cache().unwrap();
let mut app: Box<dyn App> = Box::new(Rive::from_buffer(rive_buffer));
app.set_width(width);
app.set_height(height);
Context {
composition,
renderer,
layout,
layer_cache,
app,
buffer,
width,
height,
was_cleared: false,
}
}
#[wasm_bindgen]
pub fn context_draw(
context: &mut Context,
width: usize,
height: usize,
elapsed: f64,
force_clear: bool,
) -> Clamped<Vec<u8>> {
if context.width != width || context.height != height {
context.buffer = vec![0u8; width * 4 * height];
context.layout = LinearLayout::new(width, width * 4, height);
context.app.set_width(width);
context.app.set_height(height);
}
if force_clear {
for pixel in context.buffer.chunks_mut(4) {
pixel[0] = 255;
pixel[1] = 255;
pixel[2] = 255;
pixel[3] = 0;
}
context.was_cleared = true;
} else {
if context.was_cleared {
context.layer_cache.clear();
context.was_cleared = false;
}
}
context.app.compose(
&mut context.composition,
Duration::from_secs_f64(elapsed / 1000.0),
&Keyboard,
);
context.renderer.render(
&mut context.composition,
&mut BufferBuilder::new(&mut context.buffer, &mut context.layout)
.layer_cache(context.layer_cache.clone())
.build(),
RGB1,
Color { r: 1.0, g: 1.0, b: 1.0, a: 0.0 },
None,
);
Clamped(context.buffer.clone())
}