use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer};
use vulkano::Validated;
use crate::render::font::layout::{PositionedChar, TextLayout};
use crate::render::VulkanoError;
pub trait FontRenderer: Send + Sync + 'static {
fn build_commands(
&self,
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
buffer: Vec<PositionedChar>,
) -> Result<(), Validated<VulkanoError>>;
}
pub struct FontCompositor {
renderer: Box<dyn FontRenderer>,
}
impl FontCompositor {
pub fn new(renderer: Box<dyn FontRenderer>) -> Self {
Self { renderer }
}
pub fn begin_pass<'a>(
&'a self,
builder: &'a mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
) -> FontCompositorPass<'a> {
FontCompositorPass::new(self, builder)
}
}
pub struct FontCompositorPass<'a> {
compositor: &'a FontCompositor,
builder: &'a mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
layouts: Vec<&'a TextLayout>,
}
impl<'a> FontCompositorPass<'a> {
fn new(
compositor: &'a FontCompositor,
builder: &'a mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
) -> Self {
Self {
compositor,
builder,
layouts: Vec::new(),
}
}
pub fn layout(&mut self, layout: &'a TextLayout) -> &mut Self {
self.layouts.push(layout);
self
}
pub fn end_pass(self) -> Result<(), Validated<VulkanoError>> {
let layout_chars = self.layouts.into_iter()
.map(|layout| layout.iter_build())
.flatten()
.collect::<Vec<_>>();
self.compositor.renderer.build_commands(self.builder, layout_chars)
}
}