Implement batch creation
This commit is contained in:
parent
941aaea676
commit
d59bafced1
100
src/batch.rs
100
src/batch.rs
|
@ -8,6 +8,79 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use atlas::Atlas;
|
||||||
|
use compute_shader::buffer::{Buffer, BufferData, HostAllocatedData, Protection};
|
||||||
|
use compute_shader::device::Device;
|
||||||
|
use glyph_buffer::GlyphBufferBuilder;
|
||||||
|
use std::u16;
|
||||||
|
|
||||||
|
const POINTS_PER_SEGMENT: u32 = 32;
|
||||||
|
|
||||||
|
pub struct BatchBuilder {
|
||||||
|
pub atlas: Atlas,
|
||||||
|
pub indices: Vec<u16>,
|
||||||
|
pub images: Vec<ImageDescriptor>,
|
||||||
|
pub point_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BatchBuilder {
|
||||||
|
/// FIXME(pcwalton): Including the shelf height here may be a bad API.
|
||||||
|
#[inline]
|
||||||
|
pub fn new(available_width: u32, shelf_height: u32) -> BatchBuilder {
|
||||||
|
BatchBuilder {
|
||||||
|
atlas: Atlas::new(available_width, shelf_height),
|
||||||
|
indices: vec![],
|
||||||
|
images: vec![],
|
||||||
|
point_count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_glyph(&mut self,
|
||||||
|
glyph_buffer_builder: &GlyphBufferBuilder,
|
||||||
|
glyph_index: u32,
|
||||||
|
point_size: f32)
|
||||||
|
-> Result<(), ()> {
|
||||||
|
let descriptor = &glyph_buffer_builder.descriptors[glyph_index as usize];
|
||||||
|
|
||||||
|
// FIXME(pcwalton): I think this will check for negative values and panic, which is
|
||||||
|
// unnecessary.
|
||||||
|
let pixel_size = descriptor.pixel_rect(point_size).size.ceil().cast().unwrap();
|
||||||
|
let atlas_origin = try!(self.atlas.place(&pixel_size));
|
||||||
|
|
||||||
|
if self.point_count % POINTS_PER_SEGMENT == 0 {
|
||||||
|
self.indices.push(self.images.len() as u16)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.images.push(ImageDescriptor {
|
||||||
|
atlas_x: atlas_origin.x,
|
||||||
|
atlas_y: atlas_origin.y,
|
||||||
|
point_size: point_size,
|
||||||
|
glyph_index: glyph_index,
|
||||||
|
start_point_in_glyph: descriptor.start_point,
|
||||||
|
start_point_in_batch: self.point_count,
|
||||||
|
point_count: descriptor.point_count as u32,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.point_count += descriptor.point_count as u32;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(&mut self, device: &mut Device) -> Result<Batch, ()> {
|
||||||
|
let indices = BufferData::HostAllocated(HostAllocatedData::new(&self.indices));
|
||||||
|
let images = BufferData::HostAllocated(HostAllocatedData::new(&self.images));
|
||||||
|
Ok(Batch {
|
||||||
|
indices: try!(device.create_buffer(Protection::ReadOnly, indices).map_err(drop)),
|
||||||
|
images: try!(device.create_buffer(Protection::ReadOnly, images).map_err(drop)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Batch {
|
||||||
|
pub indices: Buffer,
|
||||||
|
pub images: Buffer,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct GlyphRange {
|
pub struct GlyphRange {
|
||||||
pub start: u16,
|
pub start: u16,
|
||||||
|
@ -45,22 +118,15 @@ impl Iterator for GlyphRangeIter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[repr(C)]
|
||||||
pub struct FontGlyphRange {
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub font_id: u32,
|
pub struct ImageDescriptor {
|
||||||
pub ranges: Vec<GlyphRange>,
|
atlas_x: u32,
|
||||||
}
|
atlas_y: u32,
|
||||||
|
point_size: f32,
|
||||||
#[derive(Clone)]
|
glyph_index: u32,
|
||||||
pub struct FontGlyphRanges {
|
start_point_in_glyph: u32,
|
||||||
pub fonts: Vec<FontGlyphRange>,
|
start_point_in_batch: u32,
|
||||||
}
|
point_count: u32,
|
||||||
|
|
||||||
impl FontGlyphRanges {
|
|
||||||
pub fn new() -> FontGlyphRanges {
|
|
||||||
FontGlyphRanges {
|
|
||||||
fonts: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,38 +8,30 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use compute_shader::buffer::Buffer;
|
use compute_shader::buffer::{Buffer, BufferData, HostAllocatedData, Protection};
|
||||||
|
use compute_shader::device::Device;
|
||||||
|
use euclid::{Point2D, Rect, Size2D};
|
||||||
use otf::glyf::GlyfTable;
|
use otf::glyf::GlyfTable;
|
||||||
use otf::loca::LocaTable;
|
use otf::loca::LocaTable;
|
||||||
|
|
||||||
pub struct GlyphBuffers {
|
pub struct GlyphBufferBuilder {
|
||||||
pub coordinates: Vec<(i16, i16)>,
|
pub coordinates: Vec<(i16, i16)>,
|
||||||
pub operations: Vec<u8>,
|
pub operations: Vec<u8>,
|
||||||
pub descriptors: Vec<GlyphDescriptor>,
|
pub descriptors: Vec<GlyphDescriptor>,
|
||||||
pub cached_coordinates_buffer: Option<Buffer>,
|
|
||||||
pub cached_operations_buffer: Option<Buffer>,
|
|
||||||
pub cached_descriptors_buffer: Option<Buffer>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphBuffers {
|
impl GlyphBufferBuilder {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> GlyphBuffers {
|
pub fn new() -> GlyphBufferBuilder {
|
||||||
GlyphBuffers {
|
GlyphBufferBuilder {
|
||||||
coordinates: vec![],
|
coordinates: vec![],
|
||||||
operations: vec![],
|
operations: vec![],
|
||||||
descriptors: vec![],
|
descriptors: vec![],
|
||||||
cached_coordinates_buffer: None,
|
|
||||||
cached_operations_buffer: None,
|
|
||||||
cached_descriptors_buffer: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_glyph(&mut self, glyph_id: u32, loca_table: &LocaTable, glyf_table: &GlyfTable)
|
pub fn add_glyph(&mut self, glyph_id: u32, loca_table: &LocaTable, glyf_table: &GlyfTable)
|
||||||
-> Result<(), ()> {
|
-> Result<(), ()> {
|
||||||
self.cached_coordinates_buffer = None;
|
|
||||||
self.cached_operations_buffer = None;
|
|
||||||
self.cached_descriptors_buffer = None;
|
|
||||||
|
|
||||||
let mut point_index = self.coordinates.len() / 2;
|
let mut point_index = self.coordinates.len() / 2;
|
||||||
let mut operations = if point_index % 4 == 0 {
|
let mut operations = if point_index % 4 == 0 {
|
||||||
0
|
0
|
||||||
|
@ -70,8 +62,29 @@ impl GlyphBuffers {
|
||||||
self.operations.push(operations)
|
self.operations.push(operations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(pcwalton): Add a glyph descriptor.
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn finish(&self, device: &mut Device) -> Result<GlyphBuffers, ()> {
|
||||||
|
let coordinates = BufferData::HostAllocated(HostAllocatedData::new(&self.coordinates));
|
||||||
|
let operations = BufferData::HostAllocated(HostAllocatedData::new(&self.operations));
|
||||||
|
let descriptors = BufferData::HostAllocated(HostAllocatedData::new(&self.descriptors));
|
||||||
|
Ok(GlyphBuffers {
|
||||||
|
coordinates: try!(device.create_buffer(Protection::ReadOnly, coordinates)
|
||||||
|
.map_err(drop)),
|
||||||
|
operations: try!(device.create_buffer(Protection::ReadOnly, operations).map_err(drop)),
|
||||||
|
descriptors: try!(device.create_buffer(Protection::ReadOnly, descriptors)
|
||||||
|
.map_err(drop)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GlyphBuffers {
|
||||||
|
pub coordinates: Buffer,
|
||||||
|
pub operations: Buffer,
|
||||||
|
pub descriptors: Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -82,6 +95,15 @@ pub struct GlyphDescriptor {
|
||||||
pub height: i16,
|
pub height: i16,
|
||||||
pub units_per_em: u16,
|
pub units_per_em: u16,
|
||||||
pub point_count: u16,
|
pub point_count: u16,
|
||||||
pub index_of_first_point: u32,
|
pub start_point: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlyphDescriptor {
|
||||||
|
#[inline]
|
||||||
|
pub fn pixel_rect(&self, point_size: f32) -> Rect<f32> {
|
||||||
|
let pixels_per_unit = point_size / self.units_per_em as f32;
|
||||||
|
Rect::new(Point2D::new(self.left as f32, self.bottom as f32),
|
||||||
|
Size2D::new(self.width as f32, self.height as f32)) * pixels_per_unit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ extern crate test;
|
||||||
|
|
||||||
pub mod atlas;
|
pub mod atlas;
|
||||||
pub mod batch;
|
pub mod batch;
|
||||||
pub mod buffers;
|
|
||||||
pub mod charmap;
|
pub mod charmap;
|
||||||
|
pub mod glyph_buffer;
|
||||||
pub mod otf;
|
pub mod otf;
|
||||||
pub mod rasterizer;
|
pub mod rasterizer;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
Loading…
Reference in New Issue