[oden] It doesn't crash but it doesn't work either
This commit is contained in:
parent
71aa3c39f7
commit
8914b1795f
2 changed files with 162 additions and 50 deletions
122
src/text.rs
122
src/text.rs
|
|
@ -45,12 +45,9 @@ enum CellCacheKey {
|
|||
pub struct FontCache {
|
||||
font: Font,
|
||||
size: f32,
|
||||
atlas_width: u16,
|
||||
atlas_height: u16,
|
||||
char_width: u16,
|
||||
char_height: u16,
|
||||
texture: wgpu::Texture,
|
||||
view: wgpu::TextureView,
|
||||
pub view: wgpu::TextureView,
|
||||
pub sampler: wgpu::Sampler,
|
||||
|
||||
cells: Vec<GlyphCell>,
|
||||
cell_cache: LruCache<CellCacheKey, usize>,
|
||||
|
|
@ -58,7 +55,6 @@ pub struct FontCache {
|
|||
|
||||
enum SlotState {
|
||||
Empty,
|
||||
Allocated(u16, fontdue::Metrics),
|
||||
Rendered(u16, fontdue::Metrics),
|
||||
}
|
||||
|
||||
|
|
@ -70,8 +66,15 @@ struct GlyphCell {
|
|||
state: SlotState,
|
||||
}
|
||||
|
||||
pub struct Glyph {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub w: f32,
|
||||
pub h: f32,
|
||||
}
|
||||
|
||||
impl FontCache {
|
||||
fn new(device: &wgpu::Device, bytes: &[u8], size: f32) -> Self {
|
||||
pub fn new(device: &wgpu::Device, bytes: &[u8], size: f32) -> Self {
|
||||
let font = fontdue::Font::from_bytes(bytes, fontdue::FontSettings::default())
|
||||
.expect("Could not parse font");
|
||||
|
||||
|
|
@ -90,10 +93,21 @@ impl FontCache {
|
|||
sample_count: 4,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::R8Unorm,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::COPY_DST
|
||||
| wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
view_formats: &[],
|
||||
});
|
||||
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Nearest,
|
||||
min_filter: wgpu::FilterMode::Nearest,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
// Measure the font to figure out the size of a cell in the cache.
|
||||
// NOTE: This metric nonsense is bad, probably.
|
||||
|
|
@ -133,59 +147,71 @@ impl FontCache {
|
|||
);
|
||||
}
|
||||
|
||||
// Set up the binding group and pipeline and whatnot.
|
||||
|
||||
FontCache {
|
||||
font,
|
||||
size,
|
||||
atlas_width,
|
||||
atlas_height,
|
||||
char_width: char_width as u16,
|
||||
char_height: char_height as u16,
|
||||
texture,
|
||||
view,
|
||||
sampler,
|
||||
cells,
|
||||
cell_cache,
|
||||
}
|
||||
}
|
||||
|
||||
fn rasterize_character(&mut self, queue: &wgpu::Queue, index: u16, slot: &GlyphCell) {
|
||||
let (metrics, bitmap) = self.font.rasterize_indexed(index, self.size);
|
||||
|
||||
let mut texture = self.texture.as_image_copy();
|
||||
texture.origin.x = slot.x.into();
|
||||
texture.origin.y = slot.y.into();
|
||||
|
||||
queue.write_texture(
|
||||
texture,
|
||||
&bitmap,
|
||||
wgpu::ImageDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(metrics.width as u32),
|
||||
rows_per_image: None,
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
width: metrics.width as u32,
|
||||
height: metrics.height as u32,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn get_glyph_slot(&mut self, index: u16) -> &mut GlyphCell {
|
||||
pub fn get_char(&mut self, queue: &wgpu::Queue, c: char) -> Glyph {
|
||||
let index = self.font.lookup_glyph_index(c);
|
||||
let key = CellCacheKey::GlyphIndex(index);
|
||||
if let Some(cell_index) = self.cell_cache.get(&key) {
|
||||
return &mut self.cells[*cell_index];
|
||||
}
|
||||
let cell = match self.cell_cache.get(&key) {
|
||||
Some(cell_index) => &mut self.cells[*cell_index],
|
||||
None => {
|
||||
let (_, cell_index) = self
|
||||
.cell_cache
|
||||
.pop_lru()
|
||||
.expect("did not put all available things in the LRU cache");
|
||||
self.cell_cache.put(key, cell_index);
|
||||
let cell = &mut self.cells[cell_index];
|
||||
cell.state = SlotState::Empty; // This isn't what it used to be.
|
||||
cell
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((_, cell_index)) = self.cell_cache.pop_lru() {
|
||||
self.cell_cache.put(key, cell_index);
|
||||
let cell = &mut self.cells[cell_index];
|
||||
cell.state = SlotState::Empty;
|
||||
return cell;
|
||||
}
|
||||
// I mean, technically if we got an LRU hit here it's rendered, but
|
||||
// convincing the compiler of that is a pain.
|
||||
let metrics = match cell.state {
|
||||
SlotState::Rendered(_, metrics) => metrics,
|
||||
SlotState::Empty => {
|
||||
let (metrics, bitmap) = self.font.rasterize_indexed(index, self.size);
|
||||
|
||||
panic!("Did not put enough things in the LRU cache, why is it empty here?");
|
||||
let mut texture = self.texture.as_image_copy();
|
||||
texture.origin.x = cell.x.into();
|
||||
texture.origin.y = cell.y.into();
|
||||
|
||||
queue.write_texture(
|
||||
texture,
|
||||
&bitmap,
|
||||
wgpu::ImageDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(metrics.width as u32),
|
||||
rows_per_image: None,
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
width: metrics.width as u32,
|
||||
height: metrics.height as u32,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
);
|
||||
|
||||
cell.state = SlotState::Rendered(index, metrics.clone());
|
||||
metrics
|
||||
}
|
||||
};
|
||||
|
||||
Glyph {
|
||||
x: cell.x as f32 + metrics.bounds.xmin,
|
||||
y: cell.y as f32 + metrics.bounds.ymin,
|
||||
w: metrics.bounds.width,
|
||||
h: metrics.bounds.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue