Refactor: create Texture struct

This commit is contained in:
Emil Ernerfeldt 2019-01-16 17:09:12 -06:00
parent 7f83876005
commit 616245c323
7 changed files with 102 additions and 87 deletions

View file

@ -1,6 +1,6 @@
# Code
* Break off example app from emigui_wasm
* Add Rect type to GuiCmd. Every thing has a bounding rectangle, even text
* Try it on iPhone
* Dynamic fonts:
* Font options (sizes)
* Read ttf via web?

View file

@ -6,7 +6,7 @@ use crate::{
style,
types::GuiInput,
widgets::*,
Frame, RawInput,
Frame, RawInput, Texture,
};
#[derive(Clone, Copy, Default)]
@ -55,7 +55,7 @@ impl Emigui {
}
}
pub fn texture(&self) -> (u16, u16, &[u8]) {
pub fn texture(&self) -> &Texture {
self.data.fonts.texture()
}

View file

@ -98,11 +98,12 @@ impl Font {
let glyph_pos = atlas_lock.allocate((glyph_width, glyph_height));
let texture = atlas_lock.texture_mut();
glyph.draw(|x, y, v| {
if v > 0.0 {
let px = glyph_pos.0 + x as usize;
let py = glyph_pos.1 + y as usize;
atlas_lock[(px, py)] = (v * 255.0).round() as u8;
texture[(px, py)] = (v * 255.0).round() as u8;
}
});
@ -271,7 +272,8 @@ impl Font {
}
pub fn debug_print_all_chars(&self) {
let atlas_lock = self.atlas.lock().unwrap();
let mut atlas_lock = self.atlas.lock().unwrap();
let texture_mut = atlas_lock.texture_mut();
let max_width = 160;
let scale = Scale::uniform(self.scale as f32);
@ -295,7 +297,7 @@ impl Font {
if let Some(uv) = glyph.uv {
for x in uv.min.0..=uv.max.0 {
for y in uv.min.1..=uv.max.1 {
let pixel = atlas_lock[(x as usize, y as usize)];
let pixel = texture_mut[(x as usize, y as usize)];
let rx = uv.offset.0 + x as i16 - uv.min.0 as i16;
let ry = uv.offset.1 + y as i16 - uv.min.1 as i16;
let px = (cursor_x + rx as f32).round();

View file

@ -3,7 +3,10 @@ use std::{
sync::{Arc, Mutex},
};
use crate::{font::Font, texture_atlas::TextureAtlas};
use crate::{
font::Font,
texture_atlas::{Texture, TextureAtlas},
};
/// TODO: rename
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize)]
@ -16,7 +19,7 @@ pub enum TextStyle {
pub struct Fonts {
fonts: BTreeMap<TextStyle, Font>,
texture: (u16, u16, Vec<u8>),
texture: Texture,
}
impl Fonts {
@ -25,27 +28,30 @@ impl Fonts {
// Make one white pixel for use for various stuff:
let pos = atlas.allocate((1, 1));
atlas[pos] = 255;
atlas.texture_mut()[pos] = 255;
let atlas = Arc::new(Mutex::new(atlas));
// TODO: figure out a way to make the wasm smaller despite including a font.
// let font_data = include_bytes!("../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE.
// let font_data = include_bytes!("../fonts/DejaVuSans.ttf");
let font_data = include_bytes!("../fonts/Roboto-Regular.ttf");
// let typeface_data = include_bytes!("../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE.
// let typeface_data = include_bytes!("../fonts/DejaVuSans.ttf");
let typeface_data = include_bytes!("../fonts/Roboto-Regular.ttf");
let mut fonts = BTreeMap::new();
fonts.insert(TextStyle::Body, Font::new(atlas.clone(), font_data, 20));
fonts.insert(TextStyle::Body, Font::new(atlas.clone(), typeface_data, 20));
fonts.insert(TextStyle::Button, fonts[&TextStyle::Body].clone());
fonts.insert(TextStyle::Heading, Font::new(atlas.clone(), font_data, 30));
fonts.insert(
TextStyle::Heading,
Font::new(atlas.clone(), typeface_data, 30),
);
let texture = atlas.lock().unwrap().clone().into_texture();
let texture = atlas.lock().unwrap().clone().texture().clone();
Fonts { fonts, texture }
}
pub fn texture(&self) -> (u16, u16, &[u8]) {
(self.texture.0, self.texture.1, &self.texture.2)
pub fn texture(&self) -> &Texture {
&self.texture
}
}

View file

@ -23,5 +23,6 @@ pub use crate::{
layout::{Align, LayoutOptions, Region},
mesher::{Frame, Vertex},
style::Style,
texture_atlas::Texture,
types::RawInput,
};

View file

@ -1,63 +1,13 @@
/// A texture pixels, used for fonts.
#[derive(Clone, Default)]
pub struct TextureAtlas {
width: usize,
height: usize,
pixels: Vec<u8>,
/// Used for when adding new rects
cursor: (usize, usize),
row_height: usize,
pub struct Texture {
/// e.g. a hash of the data. Use this to detect changes!
pub id: u64, // TODO
pub width: usize,
pub height: usize,
pub pixels: Vec<u8>,
}
impl TextureAtlas {
pub fn new(width: usize, height: usize) -> Self {
TextureAtlas {
width,
height,
pixels: vec![0; width * height],
..Default::default()
}
}
pub fn width(&self) -> usize {
self.width
}
pub fn height(&self) -> usize {
self.height
}
pub fn into_texture(self) -> (u16, u16, Vec<u8>) {
(self.width as u16, self.height as u16, self.pixels)
}
/// Returns the coordinates of where the rect ended up.
pub fn allocate(&mut self, (w, h): (usize, usize)) -> (usize, usize) {
assert!(w <= self.width);
if self.cursor.0 + w > self.width {
// New row:
self.cursor.0 = 0;
self.cursor.1 += self.row_height;
self.row_height = 0;
}
self.row_height = self.row_height.max(h);
while self.cursor.1 + self.row_height >= self.height {
self.height *= 2;
}
if self.width * self.height > self.pixels.len() {
self.pixels.resize(self.width * self.height, 0);
}
let pos = self.cursor;
self.cursor.0 += w;
(pos.0 as usize, pos.1 as usize)
}
}
impl std::ops::Index<(usize, usize)> for TextureAtlas {
impl std::ops::Index<(usize, usize)> for Texture {
type Output = u8;
fn index(&self, (x, y): (usize, usize)) -> &u8 {
@ -67,10 +17,69 @@ impl std::ops::Index<(usize, usize)> for TextureAtlas {
}
}
impl std::ops::IndexMut<(usize, usize)> for TextureAtlas {
impl std::ops::IndexMut<(usize, usize)> for Texture {
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut u8 {
assert!(x < self.width);
assert!(y < self.height);
&mut self.pixels[y * self.width + x]
}
}
/// A texture pixels, used for fonts.
#[derive(Clone, Default)]
pub struct TextureAtlas {
texture: Texture,
/// Used for when adding new rects
cursor: (usize, usize),
row_height: usize,
}
impl TextureAtlas {
pub fn new(width: usize, height: usize) -> Self {
TextureAtlas {
texture: Texture {
id: 0,
width,
height,
pixels: vec![0; width * height],
},
..Default::default()
}
}
pub fn texture(&self) -> &Texture {
&self.texture
}
pub fn texture_mut(&mut self) -> &mut Texture {
&mut self.texture
}
/// Returns the coordinates of where the rect ended up.
pub fn allocate(&mut self, (w, h): (usize, usize)) -> (usize, usize) {
assert!(w <= self.texture.width);
if self.cursor.0 + w > self.texture.width {
// New row:
self.cursor.0 = 0;
self.cursor.1 += self.row_height;
self.row_height = 0;
}
self.row_height = self.row_height.max(h);
while self.cursor.1 + self.row_height >= self.texture.height {
self.texture.height *= 2;
}
if self.texture.width * self.texture.height > self.texture.pixels.len() {
self.texture
.pixels
.resize(self.texture.width * self.texture.height, 0);
}
let pos = self.cursor;
self.cursor.0 += w;
self.texture.id += 1; // TODO: hash this ?
(pos.0 as usize, pos.1 as usize)
}
}

View file

@ -4,7 +4,7 @@ use {
web_sys::{WebGlBuffer, WebGlProgram, WebGlRenderingContext, WebGlShader, WebGlTexture},
};
use emigui::Frame;
use emigui::{Frame, Texture};
type Gl = WebGlRenderingContext;
@ -32,10 +32,7 @@ impl Painter {
)
}
pub fn new(
canvas_id: &str,
(tex_width, tex_height, pixels): (u16, u16, &[u8]),
) -> Result<Painter, JsValue> {
pub fn new(canvas_id: &str, texture: &Texture) -> Result<Painter, JsValue> {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id(canvas_id).unwrap();
let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::<web_sys::HtmlCanvasElement>()?;
@ -47,11 +44,11 @@ impl Painter {
// --------------------------------------------------------------------
let texture = gl.create_texture().unwrap();
gl.bind_texture(Gl::TEXTURE_2D, Some(&texture));
let gl_texture = gl.create_texture().unwrap();
gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture));
// TODO: remove once https://github.com/rustwasm/wasm-bindgen/issues/1005 is fixed.
let mut pixels: Vec<_> = pixels.iter().cloned().collect();
let mut pixels: Vec<_> = texture.pixels.iter().cloned().collect();
let level = 0;
let internal_format = Gl::ALPHA;
@ -62,8 +59,8 @@ impl Painter {
Gl::TEXTURE_2D,
level,
internal_format as i32,
tex_width as i32,
tex_height as i32,
texture.width as i32,
texture.height as i32,
border,
src_format,
src_type,
@ -122,13 +119,13 @@ impl Painter {
Ok(Painter {
canvas,
gl,
texture,
texture: gl_texture,
program,
index_buffer,
pos_buffer,
tc_buffer,
color_buffer,
tex_size: (tex_width, tex_height),
tex_size: (texture.width as u16, texture.height as u16),
})
}