Update `glyph_brush` to `0.7` 🎉

This commit is contained in:
Héctor Ramón Jiménez 2020-05-27 22:43:21 +02:00
parent 7d5021ca82
commit 2e39948843
6 changed files with 188 additions and 200 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "glow_glyph" name = "glow_glyph"
version = "0.1.0" version = "0.2.0"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2018" edition = "2018"
description = "A fast text renderer for glow, powered by glyph_brush" description = "A fast text renderer for glow, powered by glyph_brush"
@ -12,7 +12,7 @@ readme = "README.md"
[dependencies] [dependencies]
glow = "0.4" glow = "0.4"
glyph_brush = "0.6" glyph_brush = "0.7"
log = "0.4" log = "0.4"
bytemuck = "1.2" bytemuck = "1.2"

View File

@ -1,7 +1,8 @@
use glow::HasContext; use glow::HasContext;
use glow_glyph::{GlyphBrushBuilder, Region, Scale, Section}; use glow_glyph::{ab_glyph, GlyphBrushBuilder, Region, Section, Text};
use std::error::Error;
fn main() -> Result<(), String> { fn main() -> Result<(), Box<dyn Error>> {
env_logger::init(); env_logger::init();
// Open window and create a surface // Open window and create a surface
@ -26,10 +27,11 @@ fn main() -> Result<(), String> {
}); });
// Prepare glyph_brush // Prepare glyph_brush
let inconsolata: &[u8] = include_bytes!("Inconsolata-Regular.ttf"); let inconsolata = ab_glyph::FontArc::try_from_slice(include_bytes!(
let mut glyph_brush = GlyphBrushBuilder::using_font_bytes(inconsolata) "Inconsolata-Regular.ttf"
.expect("Load fonts") ))?;
.build(&gl);
let mut glyph_brush = GlyphBrushBuilder::using_font(inconsolata).build(&gl);
// Render loop // Render loop
context.window().request_redraw(); context.window().request_redraw();
@ -66,11 +68,12 @@ fn main() -> Result<(), String> {
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) } unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }
glyph_brush.queue(Section { glyph_brush.queue(Section {
text: "Hello glow_glyph!",
screen_position: (30.0, 30.0), screen_position: (30.0, 30.0),
color: [0.0, 0.0, 0.0, 1.0],
scale: Scale { x: 40.0, y: 40.0 },
bounds: (size.width as f32, size.height as f32), bounds: (size.width as f32, size.height as f32),
text: vec![Text::default()
.with_text("Hello wgpu_glyph!")
.with_color([0.0, 0.0, 0.0, 1.0])
.with_scale(40.0)],
..Section::default() ..Section::default()
}); });
@ -79,11 +82,12 @@ fn main() -> Result<(), String> {
.expect("Draw queued"); .expect("Draw queued");
glyph_brush.queue(Section { glyph_brush.queue(Section {
text: "Hello glow_glyph!",
screen_position: (30.0, 90.0), screen_position: (30.0, 90.0),
color: [1.0, 1.0, 1.0, 1.0],
scale: Scale { x: 40.0, y: 40.0 },
bounds: (size.width as f32, size.height as f32), bounds: (size.width as f32, size.height as f32),
text: vec![Text::default()
.with_text("Hello wgpu_glyph!")
.with_color([1.0, 1.0, 1.0, 1.0])
.with_scale(40.0)],
..Section::default() ..Section::default()
}); });

View File

@ -1,7 +1,8 @@
use glow::HasContext; use glow::HasContext;
use glow_glyph::{GlyphBrushBuilder, Scale, Section}; use glow_glyph::{ab_glyph, GlyphBrushBuilder, Section, Text};
use std::error::Error;
fn main() -> Result<(), String> { fn main() -> Result<(), Box<dyn Error>> {
env_logger::init(); env_logger::init();
// Open window and create a surface // Open window and create a surface
@ -26,10 +27,11 @@ fn main() -> Result<(), String> {
}); });
// Prepare glyph_brush // Prepare glyph_brush
let inconsolata: &[u8] = include_bytes!("Inconsolata-Regular.ttf"); let inconsolata = ab_glyph::FontArc::try_from_slice(include_bytes!(
let mut glyph_brush = GlyphBrushBuilder::using_font_bytes(inconsolata) "Inconsolata-Regular.ttf"
.expect("Load fonts") ))?;
.build(&gl);
let mut glyph_brush = GlyphBrushBuilder::using_font(inconsolata).build(&gl);
// Render loop // Render loop
context.window().request_redraw(); context.window().request_redraw();
@ -72,20 +74,22 @@ fn main() -> Result<(), String> {
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) } unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }
glyph_brush.queue(Section { glyph_brush.queue(Section {
text: "Hello glow_glyph!",
screen_position: (30.0, 30.0), screen_position: (30.0, 30.0),
color: [0.0, 0.0, 0.0, 1.0],
scale: Scale { x: 40.0, y: 40.0 },
bounds: (size.width as f32, size.height as f32), bounds: (size.width as f32, size.height as f32),
text: vec![Text::default()
.with_text("Hello wgpu_glyph!")
.with_color([0.0, 0.0, 0.0, 1.0])
.with_scale(40.0)],
..Section::default() ..Section::default()
}); });
glyph_brush.queue(Section { glyph_brush.queue(Section {
text: "Hello glow_glyph!",
screen_position: (30.0, 90.0), screen_position: (30.0, 90.0),
color: [1.0, 1.0, 1.0, 1.0],
scale: Scale { x: 40.0, y: 40.0 },
bounds: (size.width as f32, size.height as f32), bounds: (size.width as f32, size.height as f32),
text: vec![Text::default()
.with_text("Hello wgpu_glyph!")
.with_color([1.0, 1.0, 1.0, 1.0])
.with_scale(40.0)],
..Section::default() ..Section::default()
}); });

View File

@ -1,67 +1,57 @@
use core::hash::BuildHasher; use core::hash::BuildHasher;
use glyph_brush::ab_glyph::Font;
use glyph_brush::delegate_glyph_brush_builder_fns; use glyph_brush::delegate_glyph_brush_builder_fns;
use glyph_brush::{rusttype, DefaultSectionHasher}; use glyph_brush::DefaultSectionHasher;
use rusttype::{Error, Font, SharedBytes};
use super::GlyphBrush; use super::GlyphBrush;
/// Builder for a [`GlyphBrush`](struct.GlyphBrush.html). /// Builder for a [`GlyphBrush`](struct.GlyphBrush.html).
pub struct GlyphBrushBuilder<'a, H = DefaultSectionHasher> { pub struct GlyphBrushBuilder<F, H = DefaultSectionHasher> {
inner: glyph_brush::GlyphBrushBuilder<'a, H>, inner: glyph_brush::GlyphBrushBuilder<F, H>,
} }
impl<'a, H> From<glyph_brush::GlyphBrushBuilder<'a, H>> impl<F, H> From<glyph_brush::GlyphBrushBuilder<F, H>>
for GlyphBrushBuilder<'a, H> for GlyphBrushBuilder<F, H>
{ {
fn from(inner: glyph_brush::GlyphBrushBuilder<'a, H>) -> Self { fn from(inner: glyph_brush::GlyphBrushBuilder<F, H>) -> Self {
GlyphBrushBuilder { inner } GlyphBrushBuilder { inner }
} }
} }
impl<'a> GlyphBrushBuilder<'a> {
/// Specifies the default font data used to render glyphs.
/// Referenced with `FontId(0)`, which is default.
#[inline]
pub fn using_font_bytes<B: Into<SharedBytes<'a>>>(
font_0_data: B,
) -> Result<Self, Error> {
let font = Font::from_bytes(font_0_data)?;
Ok(Self::using_font(font))
}
#[inline]
pub fn using_fonts_bytes<B, V>(font_data: V) -> Result<Self, Error>
where
B: Into<SharedBytes<'a>>,
V: Into<Vec<B>>,
{
let fonts = font_data
.into()
.into_iter()
.map(Font::from_bytes)
.collect::<Result<Vec<Font>, Error>>()?;
Ok(Self::using_fonts(fonts))
}
impl GlyphBrushBuilder<()> {
/// Specifies the default font used to render glyphs. /// Specifies the default font used to render glyphs.
/// Referenced with `FontId(0)`, which is default. /// Referenced with `FontId(0)`, which is default.
#[inline] #[inline]
pub fn using_font(font_0: Font<'a>) -> Self { pub fn using_font<F: Font>(font: F) -> GlyphBrushBuilder<F> {
Self::using_fonts(vec![font_0]) Self::using_fonts(vec![font])
} }
pub fn using_fonts<V: Into<Vec<Font<'a>>>>(fonts: V) -> Self { pub fn using_fonts<F: Font>(fonts: Vec<F>) -> GlyphBrushBuilder<F> {
GlyphBrushBuilder { GlyphBrushBuilder {
inner: glyph_brush::GlyphBrushBuilder::using_fonts(fonts), inner: glyph_brush::GlyphBrushBuilder::using_fonts(fonts),
} }
} }
} }
impl<'a, H: BuildHasher> GlyphBrushBuilder<'a, H> { impl<F: Font, H: BuildHasher> GlyphBrushBuilder<F, H> {
delegate_glyph_brush_builder_fns!(inner); delegate_glyph_brush_builder_fns!(inner);
/// When multiple CPU cores are available spread rasterization work across
/// all cores.
///
/// Significantly reduces worst case latency in multicore environments.
///
/// # Platform-specific behaviour
///
/// This option has no effect on wasm32.
pub fn draw_cache_multithread(mut self, multithread: bool) -> Self {
self.inner.draw_cache_builder =
self.inner.draw_cache_builder.multithread(multithread);
self
}
/// Sets the section hasher. `GlyphBrush` cannot handle absolute section /// Sets the section hasher. `GlyphBrush` cannot handle absolute section
/// hash collisions so use a good hash algorithm. /// hash collisions so use a good hash algorithm.
/// ///
@ -72,14 +62,14 @@ impl<'a, H: BuildHasher> GlyphBrushBuilder<'a, H> {
pub fn section_hasher<T: BuildHasher>( pub fn section_hasher<T: BuildHasher>(
self, self,
section_hasher: T, section_hasher: T,
) -> GlyphBrushBuilder<'a, T> { ) -> GlyphBrushBuilder<F, T> {
GlyphBrushBuilder { GlyphBrushBuilder {
inner: self.inner.section_hasher(section_hasher), inner: self.inner.section_hasher(section_hasher),
} }
} }
/// Builds a `GlyphBrush` in the given `glow::Context`. /// Builds a `GlyphBrush` in the given `glow::Context`.
pub fn build(self, gl: &glow::Context) -> GlyphBrush<'a, H> { pub fn build(self, gl: &glow::Context) -> GlyphBrush<F, H> {
GlyphBrush::<H>::new(gl, self.inner) GlyphBrush::<F, H>::new(gl, self.inner)
} }
} }

View File

@ -12,30 +12,31 @@ pub use region::Region;
use pipeline::{Instance, Pipeline}; use pipeline::{Instance, Pipeline};
pub use builder::GlyphBrushBuilder; pub use builder::GlyphBrushBuilder;
pub use glyph_brush::ab_glyph;
pub use glyph_brush::{ pub use glyph_brush::{
rusttype::{self, Font, Point, PositionedGlyph, Rect, Scale, SharedBytes}, BuiltInLineBreaker, Extra, FontId, GlyphCruncher, GlyphPositioner,
BuiltInLineBreaker, FontId, FontMap, GlyphCruncher, GlyphPositioner, HorizontalAlign, Layout, LineBreak, LineBreaker, Section, SectionGeometry,
HorizontalAlign, Layout, LineBreak, LineBreaker, OwnedSectionText, SectionGlyph, SectionGlyphIter, SectionText, Text, VerticalAlign,
OwnedVariedSection, PositionedGlyphIter, Section, SectionGeometry,
SectionText, VariedSection, VerticalAlign,
}; };
use ab_glyph::{Font, FontArc, Rect};
use core::hash::BuildHasher; use core::hash::BuildHasher;
use std::borrow::Cow; use std::borrow::Cow;
use glyph_brush::{BrushAction, BrushError, Color, DefaultSectionHasher}; use glyph_brush::{BrushAction, BrushError, DefaultSectionHasher};
use log::{log_enabled, warn}; use log::{log_enabled, warn};
/// Object allowing glyph drawing, containing cache state. Manages glyph positioning cacheing, /// Object allowing glyph drawing, containing cache state. Manages glyph positioning cacheing,
/// glyph draw caching & efficient GPU texture cache updating and re-sizing on demand. /// glyph draw caching & efficient GPU texture cache updating and re-sizing on demand.
/// ///
/// Build using a [`GlyphBrushBuilder`](struct.GlyphBrushBuilder.html). /// Build using a [`GlyphBrushBuilder`](struct.GlyphBrushBuilder.html).
pub struct GlyphBrush<'font, H = DefaultSectionHasher> { pub struct GlyphBrush<F = FontArc, H = DefaultSectionHasher> {
pipeline: Pipeline, pipeline: Pipeline,
glyph_brush: glyph_brush::GlyphBrush<'font, Instance, H>, glyph_brush: glyph_brush::GlyphBrush<Instance, Extra, F, H>,
} }
impl<'font, H: BuildHasher> GlyphBrush<'font, H> { impl<F: Font, H: BuildHasher> GlyphBrush<F, H> {
/// Queues a section/layout to be drawn by the next call of /// Queues a section/layout to be drawn by the next call of
/// [`draw_queued`](struct.GlyphBrush.html#method.draw_queued). Can be /// [`draw_queued`](struct.GlyphBrush.html#method.draw_queued). Can be
/// called multiple times to queue multiple sections for drawing. /// called multiple times to queue multiple sections for drawing.
@ -44,7 +45,7 @@ impl<'font, H: BuildHasher> GlyphBrush<'font, H> {
#[inline] #[inline]
pub fn queue<'a, S>(&mut self, section: S) pub fn queue<'a, S>(&mut self, section: S)
where where
S: Into<Cow<'a, VariedSection<'a>>>, S: Into<Cow<'a, Section<'a>>>,
{ {
self.glyph_brush.queue(section) self.glyph_brush.queue(section)
} }
@ -65,7 +66,7 @@ impl<'font, H: BuildHasher> GlyphBrush<'font, H> {
custom_layout: &G, custom_layout: &G,
) where ) where
G: GlyphPositioner, G: GlyphPositioner,
S: Into<Cow<'a, VariedSection<'a>>>, S: Into<Cow<'a, Section<'a>>>,
{ {
self.glyph_brush.queue_custom_layout(section, custom_layout) self.glyph_brush.queue_custom_layout(section, custom_layout)
} }
@ -76,11 +77,11 @@ impl<'font, H: BuildHasher> GlyphBrush<'font, H> {
#[inline] #[inline]
pub fn queue_pre_positioned( pub fn queue_pre_positioned(
&mut self, &mut self,
glyphs: Vec<(PositionedGlyph<'font>, Color, FontId)>, glyphs: Vec<SectionGlyph>,
bounds: Rect<f32>, extra: Vec<Extra>,
z: f32, bounds: Rect,
) { ) {
self.glyph_brush.queue_pre_positioned(glyphs, bounds, z) self.glyph_brush.queue_pre_positioned(glyphs, extra, bounds)
} }
/// Retains the section in the cache as if it had been used in the last /// Retains the section in the cache as if it had been used in the last
@ -94,7 +95,7 @@ impl<'font, H: BuildHasher> GlyphBrush<'font, H> {
section: S, section: S,
custom_layout: &G, custom_layout: &G,
) where ) where
S: Into<Cow<'a, VariedSection<'a>>>, S: Into<Cow<'a, Section<'a>>>,
G: GlyphPositioner, G: GlyphPositioner,
{ {
self.glyph_brush self.glyph_brush
@ -109,110 +110,28 @@ impl<'font, H: BuildHasher> GlyphBrush<'font, H> {
#[inline] #[inline]
pub fn keep_cached<'a, S>(&mut self, section: S) pub fn keep_cached<'a, S>(&mut self, section: S)
where where
S: Into<Cow<'a, VariedSection<'a>>>, S: Into<Cow<'a, Section<'a>>>,
{ {
self.glyph_brush.keep_cached(section) self.glyph_brush.keep_cached(section)
} }
fn process_queued(&mut self, context: &glow::Context) {
let pipeline = &mut self.pipeline;
let mut brush_action;
loop {
brush_action = self.glyph_brush.process_queued(
|rect, tex_data| {
let offset = [rect.min.x as u16, rect.min.y as u16];
let size = [rect.width() as u16, rect.height() as u16];
pipeline.update_cache(context, offset, size, tex_data);
},
Instance::from,
);
match brush_action {
Ok(_) => break,
Err(BrushError::TextureTooSmall { suggested }) => {
// TODO: Obtain max texture dimensions
let max_image_dimension = 2048;
let (new_width, new_height) = if (suggested.0
> max_image_dimension
|| suggested.1 > max_image_dimension)
&& (self.glyph_brush.texture_dimensions().0
< max_image_dimension
|| self.glyph_brush.texture_dimensions().1
< max_image_dimension)
{
(max_image_dimension, max_image_dimension)
} else {
suggested
};
if log_enabled!(log::Level::Warn) {
warn!(
"Increasing glyph texture size {old:?} -> {new:?}. \
Consider building with `.initial_cache_size({new:?})` to avoid \
resizing",
old = self.glyph_brush.texture_dimensions(),
new = (new_width, new_height),
);
}
pipeline
.increase_cache_size(context, new_width, new_height);
self.glyph_brush.resize_texture(new_width, new_height);
}
}
}
match brush_action.unwrap() {
BrushAction::Draw(verts) => {
self.pipeline.upload(context, &verts);
}
BrushAction::ReDraw => {}
};
}
/// Returns the available fonts. /// Returns the available fonts.
/// ///
/// The `FontId` corresponds to the index of the font data. /// The `FontId` corresponds to the index of the font data.
#[inline] #[inline]
pub fn fonts(&self) -> &[Font<'_>] { pub fn fonts(&self) -> &[F] {
self.glyph_brush.fonts() self.glyph_brush.fonts()
} }
/// Adds an additional font to the one(s) initially added on build. /// Adds an additional font to the one(s) initially added on build.
/// ///
/// Returns a new [`FontId`](struct.FontId.html) to reference this font. /// Returns a new [`FontId`](struct.FontId.html) to reference this font.
pub fn add_font_bytes<'a: 'font, B: Into<SharedBytes<'a>>>( pub fn add_font(&mut self, font: F) -> FontId {
&mut self, self.glyph_brush.add_font(font)
font_data: B,
) -> FontId {
self.glyph_brush.add_font_bytes(font_data)
}
/// Adds an additional font to the one(s) initially added on build.
///
/// Returns a new [`FontId`](struct.FontId.html) to reference this font.
pub fn add_font<'a: 'font>(&mut self, font_data: Font<'a>) -> FontId {
self.glyph_brush.add_font(font_data)
} }
} }
impl<'font, H: BuildHasher> GlyphBrush<'font, H> { impl<F: Font + Sync, H: BuildHasher> GlyphBrush<F, H> {
fn new(
gl: &glow::Context,
raw_builder: glyph_brush::GlyphBrushBuilder<'font, H>,
) -> Self {
let glyph_brush = raw_builder.build();
let (cache_width, cache_height) = glyph_brush.texture_dimensions();
GlyphBrush {
pipeline: Pipeline::new(gl, cache_width, cache_height),
glyph_brush,
}
}
/// Draws all queued sections onto a render target. /// Draws all queued sections onto a render target.
/// See [`queue`](struct.GlyphBrush.html#method.queue). /// See [`queue`](struct.GlyphBrush.html#method.queue).
/// ///
@ -276,6 +195,81 @@ impl<'font, H: BuildHasher> GlyphBrush<'font, H> {
Ok(()) Ok(())
} }
fn process_queued(&mut self, context: &glow::Context) {
let pipeline = &mut self.pipeline;
let mut brush_action;
loop {
brush_action = self.glyph_brush.process_queued(
|rect, tex_data| {
let offset = [rect.min[0] as u16, rect.min[1] as u16];
let size = [rect.width() as u16, rect.height() as u16];
pipeline.update_cache(context, offset, size, tex_data);
},
Instance::from_vertex,
);
match brush_action {
Ok(_) => break,
Err(BrushError::TextureTooSmall { suggested }) => {
// TODO: Obtain max texture dimensions
let max_image_dimension = 2048;
let (new_width, new_height) = if (suggested.0
> max_image_dimension
|| suggested.1 > max_image_dimension)
&& (self.glyph_brush.texture_dimensions().0
< max_image_dimension
|| self.glyph_brush.texture_dimensions().1
< max_image_dimension)
{
(max_image_dimension, max_image_dimension)
} else {
suggested
};
if log_enabled!(log::Level::Warn) {
warn!(
"Increasing glyph texture size {old:?} -> {new:?}. \
Consider building with `.initial_cache_size({new:?})` to avoid \
resizing",
old = self.glyph_brush.texture_dimensions(),
new = (new_width, new_height),
);
}
pipeline
.increase_cache_size(context, new_width, new_height);
self.glyph_brush.resize_texture(new_width, new_height);
}
}
}
match brush_action.unwrap() {
BrushAction::Draw(verts) => {
self.pipeline.upload(context, &verts);
}
BrushAction::ReDraw => {}
};
}
}
impl<F: Font, H: BuildHasher> GlyphBrush<F, H> {
fn new(
gl: &glow::Context,
raw_builder: glyph_brush::GlyphBrushBuilder<F, H>,
) -> Self {
let glyph_brush = raw_builder.build();
let (cache_width, cache_height) = glyph_brush.texture_dimensions();
GlyphBrush {
pipeline: Pipeline::new(gl, cache_width, cache_height),
glyph_brush,
}
}
} }
/// Helper function to generate a generate a transform matrix. /// Helper function to generate a generate a transform matrix.
@ -289,42 +283,42 @@ pub fn orthographic_projection(width: u32, height: u32) -> [f32; 16] {
] ]
} }
impl<'font, H: BuildHasher> GlyphCruncher<'font> for GlyphBrush<'font, H> { impl<F: Font, H: BuildHasher> GlyphCruncher<F> for GlyphBrush<F, H> {
#[inline]
fn pixel_bounds_custom_layout<'a, S, L>(
&mut self,
section: S,
custom_layout: &L,
) -> Option<Rect<i32>>
where
L: GlyphPositioner + std::hash::Hash,
S: Into<Cow<'a, VariedSection<'a>>>,
{
self.glyph_brush
.pixel_bounds_custom_layout(section, custom_layout)
}
#[inline] #[inline]
fn glyphs_custom_layout<'a, 'b, S, L>( fn glyphs_custom_layout<'a, 'b, S, L>(
&'b mut self, &'b mut self,
section: S, section: S,
custom_layout: &L, custom_layout: &L,
) -> PositionedGlyphIter<'b, 'font> ) -> SectionGlyphIter<'b>
where where
L: GlyphPositioner + std::hash::Hash, L: GlyphPositioner + std::hash::Hash,
S: Into<Cow<'a, VariedSection<'a>>>, S: Into<Cow<'a, Section<'a>>>,
{ {
self.glyph_brush self.glyph_brush
.glyphs_custom_layout(section, custom_layout) .glyphs_custom_layout(section, custom_layout)
} }
#[inline] #[inline]
fn fonts(&self) -> &[Font<'font>] { fn glyph_bounds_custom_layout<'a, S, L>(
&mut self,
section: S,
custom_layout: &L,
) -> Option<Rect>
where
L: GlyphPositioner + std::hash::Hash,
S: Into<Cow<'a, Section<'a>>>,
{
self.glyph_brush
.glyph_bounds_custom_layout(section, custom_layout)
}
#[inline]
fn fonts(&self) -> &[F] {
self.glyph_brush.fonts() self.glyph_brush.fonts()
} }
} }
impl<H> std::fmt::Debug for GlyphBrush<'_, H> { impl<F, H> std::fmt::Debug for GlyphBrush<F, H> {
#[inline] #[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "GlyphBrush") write!(f, "GlyphBrush")

View File

@ -1,10 +1,10 @@
mod cache; mod cache;
use crate::ab_glyph::{point, Rect};
use crate::Region; use crate::Region;
use cache::Cache; use cache::Cache;
use glow::HasContext; use glow::HasContext;
use glyph_brush::rusttype::{point, Rect};
pub struct Pipeline { pub struct Pipeline {
program: <glow::Context as HasContext>::Program, program: <glow::Context as HasContext>::Program,
@ -212,19 +212,15 @@ unsafe impl bytemuck::Pod for Instance {}
impl Instance { impl Instance {
const INITIAL_AMOUNT: usize = 50_000; const INITIAL_AMOUNT: usize = 50_000;
}
impl From<glyph_brush::GlyphVertex> for Instance { pub fn from_vertex(
#[inline] glyph_brush::GlyphVertex {
fn from(vertex: glyph_brush::GlyphVertex) -> Instance {
let glyph_brush::GlyphVertex {
mut tex_coords, mut tex_coords,
pixel_coords, pixel_coords,
bounds, bounds,
color, extra,
z, }: glyph_brush::GlyphVertex,
} = vertex; ) -> Instance {
let gl_bounds = bounds; let gl_bounds = bounds;
let mut gl_rect = Rect { let mut gl_rect = Rect {
@ -262,11 +258,11 @@ impl From<glyph_brush::GlyphVertex> for Instance {
} }
Instance { Instance {
left_top: [gl_rect.min.x, gl_rect.max.y, z], left_top: [gl_rect.min.x, gl_rect.max.y, extra.z],
right_bottom: [gl_rect.max.x, gl_rect.min.y], right_bottom: [gl_rect.max.x, gl_rect.min.y],
tex_left_top: [tex_coords.min.x, tex_coords.max.y], tex_left_top: [tex_coords.min.x, tex_coords.max.y],
tex_right_bottom: [tex_coords.max.x, tex_coords.min.y], tex_right_bottom: [tex_coords.max.x, tex_coords.min.y],
color, color: extra.color,
} }
} }
} }