1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 14:20:04 -04:00

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

@@ -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)
}
}