Render emojis
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
fff1d9c631
commit
cdcdccfb89
7 changed files with 255 additions and 56 deletions
|
@ -1,21 +1,39 @@
|
|||
use anyhow::anyhow;
|
||||
use metal::{MTLPixelFormat, TextureDescriptor, TextureRef};
|
||||
|
||||
use super::atlas::{AllocId, AtlasAllocator};
|
||||
use crate::{
|
||||
fonts::{FontId, GlyphId},
|
||||
geometry::{rect::RectI, vector::Vector2I},
|
||||
ImageData,
|
||||
platform::RasterizationOptions,
|
||||
scene::ImageGlyph,
|
||||
FontSystem, ImageData,
|
||||
};
|
||||
use std::{collections::HashMap, mem};
|
||||
use anyhow::anyhow;
|
||||
use metal::{MTLPixelFormat, TextureDescriptor, TextureRef};
|
||||
use ordered_float::OrderedFloat;
|
||||
use std::{collections::HashMap, mem, sync::Arc};
|
||||
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct GlyphDescriptor {
|
||||
font_id: FontId,
|
||||
font_size: OrderedFloat<f32>,
|
||||
glyph_id: GlyphId,
|
||||
}
|
||||
|
||||
pub struct ImageCache {
|
||||
prev_frame: HashMap<usize, (AllocId, RectI)>,
|
||||
curr_frame: HashMap<usize, (AllocId, RectI)>,
|
||||
image_glyphs: HashMap<GlyphDescriptor, Option<(AllocId, RectI, Vector2I)>>,
|
||||
atlases: AtlasAllocator,
|
||||
scale_factor: f32,
|
||||
fonts: Arc<dyn FontSystem>,
|
||||
}
|
||||
|
||||
impl ImageCache {
|
||||
pub fn new(device: metal::Device, size: Vector2I) -> Self {
|
||||
pub fn new(
|
||||
device: metal::Device,
|
||||
size: Vector2I,
|
||||
scale_factor: f32,
|
||||
fonts: Arc<dyn FontSystem>,
|
||||
) -> Self {
|
||||
let descriptor = TextureDescriptor::new();
|
||||
descriptor.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
descriptor.set_width(size.x() as u64);
|
||||
|
@ -23,7 +41,21 @@ impl ImageCache {
|
|||
Self {
|
||||
prev_frame: Default::default(),
|
||||
curr_frame: Default::default(),
|
||||
image_glyphs: Default::default(),
|
||||
atlases: AtlasAllocator::new(device, descriptor),
|
||||
scale_factor,
|
||||
fonts,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_scale_factor(&mut self, scale_factor: f32) {
|
||||
if scale_factor != self.scale_factor {
|
||||
self.scale_factor = scale_factor;
|
||||
for (_, glyph) in self.image_glyphs.drain() {
|
||||
if let Some((alloc_id, _, _)) = glyph {
|
||||
self.atlases.deallocate(alloc_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +71,37 @@ impl ImageCache {
|
|||
(alloc_id, atlas_bounds)
|
||||
}
|
||||
|
||||
pub fn render_glyph(&mut self, image_glyph: &ImageGlyph) -> Option<(AllocId, RectI, Vector2I)> {
|
||||
*self
|
||||
.image_glyphs
|
||||
.entry(GlyphDescriptor {
|
||||
font_id: image_glyph.font_id,
|
||||
font_size: OrderedFloat(image_glyph.font_size),
|
||||
glyph_id: image_glyph.id,
|
||||
})
|
||||
.or_insert_with(|| {
|
||||
let (glyph_bounds, bytes) = self.fonts.rasterize_glyph(
|
||||
image_glyph.font_id,
|
||||
image_glyph.font_size,
|
||||
image_glyph.id,
|
||||
Default::default(),
|
||||
self.scale_factor,
|
||||
RasterizationOptions::Bgra,
|
||||
)?;
|
||||
let (alloc_id, atlas_bounds) = self
|
||||
.atlases
|
||||
.upload(glyph_bounds.size(), &bytes)
|
||||
.ok_or_else(|| {
|
||||
anyhow!(
|
||||
"could not upload image glyph of size {:?}",
|
||||
glyph_bounds.size()
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
Some((alloc_id, atlas_bounds, glyph_bounds.origin()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn finish_frame(&mut self) {
|
||||
mem::swap(&mut self.prev_frame, &mut self.curr_frame);
|
||||
for (_, (id, _)) in self.curr_frame.drain() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue