Add borders between glyphs in the atlas; allow the atlas to be dumped in the demo
This commit is contained in:
parent
5bccf88445
commit
6ae7601283
|
@ -15,6 +15,7 @@ memmap = "0.5"
|
|||
path = "/Users/pcwalton/Source/rust-packages/compute-shader"
|
||||
|
||||
[dev-dependencies]
|
||||
image = "0.12"
|
||||
quickcheck = "0.4"
|
||||
|
||||
[dev-dependencies.glfw]
|
||||
|
|
|
@ -8,6 +8,7 @@ extern crate compute_shader;
|
|||
extern crate euclid;
|
||||
extern crate gl;
|
||||
extern crate glfw;
|
||||
extern crate image;
|
||||
extern crate memmap;
|
||||
extern crate pathfinder;
|
||||
|
||||
|
@ -29,6 +30,7 @@ use pathfinder::shaper;
|
|||
use std::env;
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::path::Path;
|
||||
|
||||
const ATLAS_SIZE: u32 = 2048;
|
||||
const WIDTH: u32 = 640;
|
||||
|
@ -47,6 +49,8 @@ static FPS_BACKGROUND_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 0.7];
|
|||
static FPS_FOREGROUND_COLOR: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
|
||||
static TEXT_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
|
||||
|
||||
static ATLAS_DUMP_FILENAME: &'static str = "lorem-ipsum-atlas.png";
|
||||
|
||||
fn main() {
|
||||
let mut glfw = glfw::init(glfw::LOG_ERRORS).unwrap();
|
||||
glfw.window_hint(WindowHint::ContextVersion(3, 3));
|
||||
|
@ -56,6 +60,7 @@ fn main() {
|
|||
|
||||
let (mut window, events) = context.expect("Couldn't create a window!");
|
||||
window.make_current();
|
||||
window.set_key_polling(true);
|
||||
window.set_scroll_polling(true);
|
||||
window.set_size_polling(true);
|
||||
window.set_framebuffer_size_polling(true);
|
||||
|
@ -155,6 +160,10 @@ fn main() {
|
|||
WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
|
||||
window.set_should_close(true)
|
||||
}
|
||||
WindowEvent::Key(Key::S, _, Action::Press, _) => {
|
||||
renderer.take_screenshot();
|
||||
println!("wrote screenshot to: {}", ATLAS_DUMP_FILENAME);
|
||||
}
|
||||
WindowEvent::Scroll(x, y) => {
|
||||
if window.get_key(Key::LeftAlt) == Action::Press ||
|
||||
window.get_key(Key::RightAlt) == Action::Press {
|
||||
|
@ -611,6 +620,36 @@ impl Renderer {
|
|||
FPS_DISPLAY_POINT_SIZE,
|
||||
&FPS_FOREGROUND_COLOR);
|
||||
}
|
||||
|
||||
fn take_screenshot(&self) {
|
||||
unsafe {
|
||||
let mut fbo = 0;
|
||||
gl::GenFramebuffers(1, &mut fbo);
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, fbo);
|
||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
|
||||
gl::COLOR_ATTACHMENT0,
|
||||
gl::TEXTURE_RECTANGLE,
|
||||
self.main_gl_texture,
|
||||
0);
|
||||
|
||||
let length = 4 * self.atlas_size.width as usize * self.atlas_size.height as usize;
|
||||
let mut pixels: Vec<u8> = vec![0; length];
|
||||
gl::ReadPixels(0, 0,
|
||||
self.atlas_size.width as GLint, self.atlas_size.height as GLint,
|
||||
gl::RGBA,
|
||||
gl::UNSIGNED_BYTE,
|
||||
pixels.as_mut_ptr() as *mut c_void);
|
||||
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
gl::DeleteFramebuffers(1, &mut fbo);
|
||||
|
||||
image::save_buffer(&Path::new(ATLAS_DUMP_FILENAME),
|
||||
&pixels,
|
||||
self.atlas_size.width,
|
||||
self.atlas_size.height,
|
||||
image::RGBA(8)).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
17
src/atlas.rs
17
src/atlas.rs
|
@ -32,12 +32,15 @@ impl Atlas {
|
|||
}
|
||||
|
||||
pub fn place(&mut self, size: &Size2D<u32>) -> Result<Point2D<u32>, ()> {
|
||||
// Add a one-pixel border to prevent bleed.
|
||||
let alloc_size = *size + Size2D::new(2, 2);
|
||||
|
||||
let chosen_index_and_rect =
|
||||
self.free_rects
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, rect)| {
|
||||
size.width <= rect.size.width && size.height <= rect.size.height
|
||||
alloc_size.width <= rect.size.width && alloc_size.height <= rect.size.height
|
||||
})
|
||||
.min_by(|&(_, a), &(_, b)| area(a).cmp(&area(b)))
|
||||
.map(|(index, rect)| (index, *rect));
|
||||
|
@ -59,16 +62,17 @@ impl Atlas {
|
|||
|
||||
// Guillotine to bottom.
|
||||
let free_below =
|
||||
Rect::new(Point2D::new(chosen_rect.origin.x, chosen_rect.origin.y + size.height),
|
||||
Size2D::new(size.width, chosen_rect.size.height - size.height));
|
||||
Rect::new(Point2D::new(chosen_rect.origin.x, chosen_rect.origin.y + alloc_size.height),
|
||||
Size2D::new(alloc_size.width, chosen_rect.size.height - alloc_size.height));
|
||||
if !free_below.is_empty() {
|
||||
self.free_rects.push(free_below);
|
||||
}
|
||||
|
||||
// Guillotine to right.
|
||||
let free_to_right =
|
||||
Rect::new(Point2D::new(chosen_rect.origin.x + size.width, chosen_rect.origin.y),
|
||||
Size2D::new(chosen_rect.size.width - size.width, chosen_rect.size.height));
|
||||
Rect::new(Point2D::new(chosen_rect.origin.x + alloc_size.width, chosen_rect.origin.y),
|
||||
Size2D::new(chosen_rect.size.width - alloc_size.width,
|
||||
chosen_rect.size.height));
|
||||
if !free_to_right.is_empty() {
|
||||
self.free_rects.push(free_to_right);
|
||||
}
|
||||
|
@ -79,7 +83,8 @@ impl Atlas {
|
|||
self.width_of_last_shelf = chosen_rect.max_x()
|
||||
}
|
||||
|
||||
Ok(chosen_rect.origin)
|
||||
let object_origin = chosen_rect.origin + Point2D::new(1, 1);
|
||||
Ok(object_origin)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Reference in New Issue