veloren_voxygen/ui/ice/
cache.rs1use super::graphic::{Graphic, GraphicCache, Id as GraphicId};
2use crate::{
3 error::Error,
4 render::{Renderer, Texture, UiTextureBindGroup},
5};
6use common::assets::{AssetExt, BoxedError, FileAsset};
7use glyph_brush::GlyphBrushBuilder;
8use std::{
9 borrow::Cow,
10 cell::{RefCell, RefMut},
11};
12use vek::*;
13
14const GLYPH_CACHE_SIZE: u32 = 1;
19const SCALE_TOLERANCE: f32 = 0.5;
23const POSITION_TOLERANCE: f32 = 0.5;
24
25type GlyphBrush = glyph_brush::GlyphBrush<(Aabr<f32>, Aabr<f32>), ()>;
26
27pub type Font = glyph_brush::ab_glyph::FontArc;
29
30pub fn load_font(specifier: &str) -> Font { Font::load_expect(specifier).cloned() }
31
32#[derive(Clone, Copy, Default)]
33pub struct FontId(pub(super) glyph_brush::FontId);
34
35pub struct Cache {
36 glyph_brush: RefCell<GlyphBrush>,
37 glyph_cache_tex: (Texture, UiTextureBindGroup),
38 graphic_cache: GraphicCache,
39}
40
41impl Cache {
43 pub fn new(renderer: &mut Renderer, default_font: Font) -> Result<Self, Error> {
44 let (w, h) = renderer.resolution().into_tuple();
45
46 let max_texture_size = renderer.max_texture_size();
47
48 let glyph_cache_dims =
49 Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).clamp(512, max_texture_size));
50
51 let glyph_brush = GlyphBrushBuilder::using_font(default_font)
52 .initial_cache_size((glyph_cache_dims.x, glyph_cache_dims.y))
53 .draw_cache_scale_tolerance(SCALE_TOLERANCE)
54 .draw_cache_position_tolerance(POSITION_TOLERANCE)
55 .build();
56
57 let glyph_cache_tex = {
58 let tex = renderer.create_dynamic_texture(glyph_cache_dims);
59 let bind = renderer.ui_bind_texture(&tex);
60 (tex, bind)
61 };
62
63 Ok(Self {
64 glyph_brush: RefCell::new(glyph_brush),
65 glyph_cache_tex,
66 graphic_cache: GraphicCache::new(renderer),
67 })
68 }
69
70 pub fn glyph_cache_tex(&self) -> (&Texture, &UiTextureBindGroup) {
71 (&self.glyph_cache_tex.0, &self.glyph_cache_tex.1)
72 }
73
74 pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphBrush, &(Texture, UiTextureBindGroup)) {
75 (self.glyph_brush.get_mut(), &self.glyph_cache_tex)
76 }
77
78 pub fn glyph_cache_mut(&mut self) -> &mut GlyphBrush { self.glyph_brush.get_mut() }
79
80 pub fn glyph_calculator(&self) -> RefMut<'_, GlyphBrush> { self.glyph_brush.borrow_mut() }
81
82 pub fn add_font(&mut self, font: RawFont) -> FontId {
84 let font = Font::try_from_vec(font.0).unwrap();
85 let id = self.glyph_brush.get_mut().add_font(font);
86 FontId(id)
87 }
88
89 pub fn clear_fonts(&mut self, default_font: Font) {
91 self.glyph_brush = RefCell::new(
92 self.glyph_brush
93 .get_mut()
94 .to_builder()
95 .replace_fonts(|mut fonts| {
96 fonts.clear();
97 fonts.push(default_font);
98 fonts
99 })
100 .build(),
101 );
102 }
103
104 pub fn graphic_cache(&self) -> &GraphicCache { &self.graphic_cache }
105
106 pub fn graphic_cache_mut(&mut self) -> &mut GraphicCache { &mut self.graphic_cache }
107
108 pub fn add_graphic(&mut self, graphic: Graphic) -> GraphicId {
109 self.graphic_cache.add_graphic(graphic)
110 }
111
112 pub fn replace_graphic(&mut self, id: GraphicId, graphic: Graphic) {
113 self.graphic_cache.replace_graphic(id, graphic)
114 }
115
116 pub fn resize_graphic_cache(&mut self, renderer: &mut Renderer) {
119 self.graphic_cache.clear_cache(renderer);
120 }
121
122 pub fn resize_glyph_cache(&mut self, renderer: &mut Renderer) -> Result<(), Error> {
124 let max_texture_size = renderer.max_texture_size();
125 let cache_dims = renderer
126 .resolution()
127 .map(|e| (e * GLYPH_CACHE_SIZE).clamp(512, max_texture_size));
128 let glyph_brush = self.glyph_brush.get_mut();
129 *glyph_brush = glyph_brush
130 .to_builder()
131 .initial_cache_size((cache_dims.x, cache_dims.y))
132 .build();
133
134 self.glyph_cache_tex = {
135 let tex = renderer.create_dynamic_texture(cache_dims);
136 let bind = renderer.ui_bind_texture(&tex);
137 (tex, bind)
138 };
139
140 Ok(())
141 }
142}
143
144#[derive(Clone)]
146pub struct RawFont(pub Vec<u8>);
147
148impl FileAsset for RawFont {
149 const EXTENSION: &'static str = "ttf";
150
151 fn from_bytes(bytes: Cow<[u8]>) -> Result<Self, BoxedError> { Ok(Self(bytes.into())) }
152}