1use glyph_brush::VariedSection;
2use glyph_brush::rusttype::{Font, SharedBytes, Rect, point};
3use std::borrow::Cow;
4
5const IDENTITY_MATRIX4: [[f32; 4]; 4] = [
6 [1.0, 0.0, 0.0, 0.0],
7 [0.0, 1.0, 0.0, 0.0],
8 [0.0, 0.0, 1.0, 0.0],
9 [0.0, 0.0, 0.0, 1.0],
10];
11
12pub struct GlyphBrushBuilder<'a, H = glyph_brush::DefaultSectionHasher> {
13 inner: glyph_brush::GlyphBrushBuilder<'a, H>,
14}
15
16impl<'a> GlyphBrushBuilder<'a> {
17 #[inline]
18 pub fn using_font_bytes<F: Into<SharedBytes<'a>>>(font: F) -> Self {
19 Self::using_font(Font::from_bytes(font).unwrap())
20 }
21
22 #[inline]
23 pub fn using_fonts_bytes<B, V>(font_data: V) -> Self
24 where
25 B: Into<SharedBytes<'a>>,
26 V: Into<Vec<B>>,
27 {
28 Self::using_fonts(
29 font_data
30 .into()
31 .into_iter()
32 .map(|data| Font::from_bytes(data).unwrap())
33 .collect::<Vec<_>>(),
34 )
35 }
36
37 #[inline]
38 pub fn using_font(font_0: Font<'a>) -> Self {
39 Self::using_fonts(vec![font_0])
40 }
41
42 pub fn using_fonts<V: Into<Vec<Font<'a>>>>(fonts: V) -> Self {
43 GlyphBrushBuilder {
44 inner: glyph_brush::GlyphBrushBuilder::using_fonts(fonts),
45 }
46 }
47}
48impl<'a, H: std::hash::BuildHasher> GlyphBrushBuilder<'a, H> {
49 glyph_brush::delegate_glyph_brush_builder_fns!(inner);
50
51 pub fn build<'g>(self, grr: &'g grr::Device) -> GlyphBrush<'a, 'g, H> {
52 let vs = grr.create_shader(grr::ShaderStage::Vertex, include_bytes!("shaders/vert.glsl")).unwrap();
53 let fs = grr.create_shader(grr::ShaderStage::Fragment, include_bytes!("shaders/frag.glsl")).unwrap();
54 let pipeline = grr.create_graphics_pipeline(grr::GraphicsPipelineDesc {
55 vertex_shader: &vs,
56 tessellation_control_shader: None,
57 tessellation_evaluation_shader: None,
58 geometry_shader: None,
59 fragment_shader: Some(&fs),
60 }).unwrap();
61 grr.delete_shaders(&[vs, fs]);
62
63 let vertex_array = grr.create_vertex_array(&[
64 grr::VertexAttributeDesc {
66 location: 0,
67 binding: 0,
68 format: grr::VertexFormat::Xyz32Float,
69 offset: 0,
70 },
71 grr::VertexAttributeDesc {
73 location: 1,
74 binding: 0,
75 format: grr::VertexFormat::Xy32Float,
76 offset: (3 * std::mem::size_of::<f32>()) as _,
77 },
78 grr::VertexAttributeDesc {
80 location: 2,
81 binding: 0,
82 format: grr::VertexFormat::Xy32Float,
83 offset: (5 * std::mem::size_of::<f32>()) as _,
84 },
85 grr::VertexAttributeDesc {
87 location: 3,
88 binding: 0,
89 format: grr::VertexFormat::Xy32Float,
90 offset: (7 * std::mem::size_of::<f32>()) as _,
91 },
92 grr::VertexAttributeDesc {
94 location: 4,
95 binding: 0,
96 format: grr::VertexFormat::Xyzw32Float,
97 offset: (9 * std::mem::size_of::<f32>()) as _,
98 },
99 ]).unwrap();
100
101 let sampler = grr.create_sampler(grr::SamplerDesc {
102 min_filter: grr::Filter::Linear,
103 mag_filter: grr::Filter::Linear,
104 mip_map: Some(grr::Filter::Linear),
105 address: (
106 grr::SamplerAddress::ClampEdge,
107 grr::SamplerAddress::ClampEdge,
108 grr::SamplerAddress::ClampEdge,
109 ),
110 lod_bias: 0.0,
111 lod: 0.0..1024.0,
112 compare: None,
113 border_color: [0.0, 0.0, 0.0, 1.0],
114 }).unwrap();
115
116 let brush = self.inner.build();
117
118 let glyph_image = {
119 let (width, height) = brush.texture_dimensions();
120 grr.create_image(grr::ImageType::D2 { width, height, layers: 1, samples: 1 }, grr::Format::R8_UNORM, 1).unwrap()
121 };
122 let glyph_image_view = grr.create_image_view(
123 &glyph_image,
124 grr::ImageViewType::D2,
125 grr::Format::R8_UNORM,
126 grr::SubresourceRange {
127 layers: 0..1,
128 levels: 0..1,
129 },
130 ).unwrap();
131
132 GlyphBrush {
133 inner: brush,
134 glyph_cache: GlyphCache {
135 image: glyph_image,
136 view: glyph_image_view,
137 },
138 grr,
139 pipeline,
140 vertex_array,
141 sampler,
142 draw: None,
143 }
144 }
145}
146
147struct DrawCommand {
148 buffer: grr::Buffer,
149 vertices: u32,
150}
151
152struct GlyphCache {
153 image: grr::Image,
154 view: grr::ImageView,
155}
156
157pub struct GlyphBrush<'font, 'grr, H = glyph_brush::DefaultSectionHasher> {
158 inner: glyph_brush::GlyphBrush<'font, H>,
159 grr: &'grr grr::Device,
160 pipeline: grr::Pipeline,
161 vertex_array: grr::VertexArray,
162 sampler: grr::Sampler,
163 glyph_cache: GlyphCache,
164 draw: Option<DrawCommand>,
165}
166
167impl<'font, 'grr> GlyphBrush<'font, 'grr> {
168 #[inline]
169 pub fn queue_custom_layout<'a, S, G>(&mut self, section: S, custom_layout: &G)
170 where
171 G: glyph_brush::GlyphPositioner,
172 S: Into<Cow<'a, VariedSection<'a>>>,
173 {
174 self.inner.queue_custom_layout(section, custom_layout)
175 }
176
177 #[inline]
178 pub fn queue<'a, S>(&mut self, section: S)
179 where
180 S: Into<Cow<'a, VariedSection<'a>>>,
181 {
182 self.inner.queue(section)
183 }
184
185 #[inline]
186 pub fn keep_cached_custom_layout<'a, S, G>(&mut self, section: S, custom_layout: &G)
187 where
188 G: glyph_brush::GlyphPositioner,
189 S: Into<Cow<'a, VariedSection<'a>>>,
190 {
191 self.inner.keep_cached_custom_layout(section, custom_layout)
192 }
193
194 #[inline]
195 pub fn keep_cached<'a, S>(&mut self, section: S)
196 where
197 S: Into<Cow<'a, VariedSection<'a>>>,
198 {
199 self.inner.keep_cached(section)
200 }
201
202 #[inline]
203 pub fn draw_queued(
204 &mut self,
205 dims: (u32, u32),
206 ) -> Result<(), String> {
207 self.draw_queued_with_transform(IDENTITY_MATRIX4, dims)
208 }
209
210 pub fn draw_queued_with_transform(
211 &mut self,
212 transform: [[f32; 4]; 4],
213 dims: (u32, u32),
214 ) -> Result<(), String> {
215 let mut brush_action;
216 loop {
217 let grr = self.grr;
218 let glyph_cache = &self.glyph_cache;
219 brush_action = self.inner.process_queued(
220 dims,
221 |rect, tex_data| {
222 grr.copy_host_to_image(
223 &glyph_cache.image,
224 grr::SubresourceLevel {
225 level: 0,
226 layers: 0..1,
227 },
228 grr::Offset { x: rect.min.x as _, y: rect.min.y as _, z: 0 },
229 grr::Extent {
230 width: rect.width(),
231 height: rect.height(),
232 depth: 1,
233 },
234 &tex_data,
235 grr::SubresourceLayout {
236 base_format: grr::BaseFormat::R,
237 format_layout: grr::FormatLayout::U8,
238 row_pitch: rect.width(),
239 image_height: rect.height(),
240 alignment: 1,
241 },
242 );
243 },
244 to_vertex,
245 );
246
247 match brush_action {
248 Ok(_) => break,
249 Err(glyph_brush::BrushError::TextureTooSmall { suggested }) => {
250 unimplemented!()
251 }
252 }
253 }
254
255 match brush_action.unwrap() {
256 glyph_brush::BrushAction::Draw(verts) => {
257 if let Some(draw) = self.draw.take() {
258 self.grr.delete_buffer(draw.buffer);
259 }
260
261 if !verts.is_empty() {
262 self.draw = Some(DrawCommand {
263 buffer:self.grr.create_buffer_from_host(grr::as_u8_slice(verts.as_slice()), grr::MemoryFlags::empty()).unwrap(),
264 vertices: verts.len() as _,
265 });
266 }
267 }
268 glyph_brush::BrushAction::ReDraw => {}
269 };
270
271 if let Some(ref cmd) = self.draw {
272 let color_blend = grr::ColorBlend {
273 attachments: vec![grr::ColorBlendAttachment {
274 blend_enable: true,
275 color: grr::BlendChannel {
276 src_factor: grr::BlendFactor::SrcAlpha,
277 dst_factor: grr::BlendFactor::OneMinusSrcAlpha,
278 blend_op: grr::BlendOp::Add,
279 },
280 alpha: grr::BlendChannel {
281 src_factor: grr::BlendFactor::One,
282 dst_factor: grr::BlendFactor::One,
283 blend_op: grr::BlendOp::Add,
284 },
285 }],
286 };
287 let depth_stencil = grr::DepthStencil {
288 depth_test: true,
289 depth_write: true,
290 depth_compare_op: grr::Compare::LessEqual,
291 stencil_test: false,
292 stencil_front: grr::StencilFace::KEEP,
293 stencil_back: grr::StencilFace::KEEP,
294 };
295
296 self.grr.bind_pipeline(&self.pipeline);
297 self.grr.bind_vertex_array(&self.vertex_array);
298 self.grr.bind_vertex_buffers(&self.vertex_array, 0, &[grr::VertexBufferView {
299 buffer: &cmd.buffer,
300 offset: 0,
301 stride: (std::mem::size_of::<f32>() * 13) as _,
302 input_rate: grr::InputRate::Instance { divisor: 1 },
303 }]);
304 self.grr.bind_color_blend_state(&color_blend);
305 self.grr.bind_depth_stencil_state(&depth_stencil);
306 self.grr.bind_samplers(0, &[&self.sampler]);
307 self.grr.bind_image_views(0, &[&self.glyph_cache.view]);
308 self.grr.draw(grr::Primitive::TriangleStrip, 0..4, 0..cmd.vertices as _);
309 }
310
311 Ok(())
312 }
313
314 #[inline]
315 pub fn fonts(&self) -> &[Font<'_>] {
316 self.inner.fonts()
317 }
318
319 pub fn add_font_bytes<'a: 'font, B: Into<SharedBytes<'a>>>(&mut self, font_data: B) -> glyph_brush::FontId {
320 self.inner.add_font_bytes(font_data)
321 }
322
323 pub fn add_font<'a: 'font>(&mut self, font_data: Font<'a>) -> glyph_brush::FontId {
324 self.inner.add_font(font_data)
325 }
326}
327
328type Vertex = [f32; 13];
329
330#[inline]
331fn to_vertex(
332 glyph_brush::GlyphVertex {
333 mut tex_coords,
334 pixel_coords,
335 bounds,
336 screen_dimensions: (screen_w, screen_h),
337 color,
338 z,
339 }: glyph_brush::GlyphVertex,
340) -> Vertex {
341 let gl_bounds = Rect {
342 min: point(
343 2.0 * (bounds.min.x / screen_w - 0.5),
344 2.0 * (0.5 - bounds.min.y / screen_h),
345 ),
346 max: point(
347 2.0 * (bounds.max.x / screen_w - 0.5),
348 2.0 * (0.5 - bounds.max.y / screen_h),
349 ),
350 };
351
352 let mut gl_rect = Rect {
353 min: point(
354 2.0 * (pixel_coords.min.x as f32 / screen_w - 0.5),
355 2.0 * (0.5 - pixel_coords.min.y as f32 / screen_h),
356 ),
357 max: point(
358 2.0 * (pixel_coords.max.x as f32 / screen_w - 0.5),
359 2.0 * (0.5 - pixel_coords.max.y as f32 / screen_h),
360 ),
361 };
362
363 if gl_rect.max.x > gl_bounds.max.x {
365 let old_width = gl_rect.width();
366 gl_rect.max.x = gl_bounds.max.x;
367 tex_coords.max.x = tex_coords.min.x + tex_coords.width() * gl_rect.width() / old_width;
368 }
369 if gl_rect.min.x < gl_bounds.min.x {
370 let old_width = gl_rect.width();
371 gl_rect.min.x = gl_bounds.min.x;
372 tex_coords.min.x = tex_coords.max.x - tex_coords.width() * gl_rect.width() / old_width;
373 }
374 if gl_rect.max.y < gl_bounds.max.y {
377 let old_height = gl_rect.height();
378 gl_rect.max.y = gl_bounds.max.y;
379 tex_coords.max.y = tex_coords.min.y + tex_coords.height() * gl_rect.height() / old_height;
380 }
381 if gl_rect.min.y > gl_bounds.min.y {
382 let old_height = gl_rect.height();
383 gl_rect.min.y = gl_bounds.min.y;
384 tex_coords.min.y = tex_coords.max.y - tex_coords.height() * gl_rect.height() / old_height;
385 }
386
387 [
388 gl_rect.min.x,
389 gl_rect.max.y,
390 z,
391 gl_rect.max.x,
392 gl_rect.min.y,
393 tex_coords.min.x,
394 tex_coords.max.y,
395 tex_coords.max.x,
396 tex_coords.min.y,
397 color[0],
398 color[1],
399 color[2],
400 color[3],
401 ]
402}