1use std::{collections::HashMap, sync::Arc};
2
3use crate::{
4 fonts::{FontId, GlyphId},
5 geometry::{rect::RectI, vector::Vector2I},
6 FontCache,
7};
8use etagere::BucketedAtlasAllocator;
9use metal::{MTLPixelFormat, TextureDescriptor};
10use ordered_float::OrderedFloat;
11
12#[derive(Hash, Eq, PartialEq)]
13struct GlyphDescriptor {
14 font_id: FontId,
15 font_size: OrderedFloat<f32>,
16 glyph_id: GlyphId,
17}
18
19pub struct SpriteCache {
20 font_cache: Arc<FontCache>,
21 device: metal::Device,
22 size: Vector2I,
23 atlasses: Vec<Atlas>,
24 glyphs: HashMap<GlyphDescriptor, (usize, RectI)>,
25}
26
27impl SpriteCache {
28 pub fn new(device: metal::Device, size: Vector2I) -> Self {
29 Self {
30 device,
31 size,
32 atlasses: vec![Atlas::new(&device, size)],
33 glyphs: Default::default(),
34 }
35 }
36
37 pub fn render_glyph(
38 &mut self,
39 font_id: FontId,
40 font_size: f32,
41 glyph_id: GlyphId,
42 ) -> (usize, RectI) {
43 self.glyphs
44 .entry(GlyphDescriptor {
45 font_id,
46 font_size: OrderedFloat(font_size),
47 glyph_id,
48 })
49 .or_insert_with(|| {
50 let rendered_glyph = self.font_cache.render_glyph(font_id, font_size, glyph_id);
51 // let atlas = self.atlasses.last_mut().unwrap();
52 todo!()
53 })
54 .clone()
55 }
56}
57
58struct Atlas {
59 allocator: BucketedAtlasAllocator,
60 texture: metal::Texture,
61}
62
63impl Atlas {
64 fn new(device: &metal::DeviceRef, size: Vector2I) -> Self {
65 let descriptor = TextureDescriptor::new();
66 descriptor.set_pixel_format(MTLPixelFormat::A8Unorm);
67 descriptor.set_width(size.x() as u64);
68 descriptor.set_height(size.y() as u64);
69
70 Self {
71 allocator: BucketedAtlasAllocator::new(etagere::Size::new(size.x(), size.y())),
72 texture: device.new_texture(&descriptor),
73 }
74 }
75}