Make rects rounded and optimize PNGs

This commit is contained in:
Patrick Walton 2019-02-26 13:48:35 -08:00
parent 5c7423d59c
commit 92777c6346
16 changed files with 202 additions and 40 deletions

View File

@ -685,10 +685,7 @@ impl Options {
}
fn load_scene(input_path: &Path) -> Scene {
let usvg = Tree::from_file(input_path, &UsvgOptions::default()).unwrap();
let scene = Scene::from_tree(usvg);
println!("{} objects, {} paints", scene.objects.len(), scene.paints.len());
scene
Scene::from_tree(Tree::from_file(input_path, &UsvgOptions::default()).unwrap())
}
fn build_scene(scene: &Scene, build_options: BuildOptions, jobs: Option<usize>) -> BuiltScene {

View File

@ -12,12 +12,17 @@ use crate::Options;
use nfd::Response;
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_gl::debug::{BUTTON_HEIGHT, BUTTON_TEXT_OFFSET, BUTTON_WIDTH, DebugUI, PADDING};
use pathfinder_gl::debug::{TEXT_COLOR, WINDOW_COLOR};
use pathfinder_gl::debug::{DebugUI, PADDING, TEXT_COLOR, WINDOW_COLOR};
use pathfinder_gl::device::{Device, Texture};
use std::f32::consts::PI;
use std::path::PathBuf;
const ICON_SIZE: i32 = 48;
const BUTTON_WIDTH: i32 = PADDING * 2 + ICON_SIZE;
const BUTTON_HEIGHT: i32 = PADDING * 2 + ICON_SIZE;
const BUTTON_TEXT_OFFSET: i32 = PADDING + 36;
const SWITCH_SIZE: i32 = SWITCH_HALF_SIZE * 2 + 1;
const SWITCH_HALF_SIZE: i32 = 96;
@ -189,10 +194,10 @@ impl DemoUI {
let bottom = debug_ui.framebuffer_size().y() - PADDING;
let effects_panel_y = bottom - (BUTTON_HEIGHT + PADDING + EFFECTS_PANEL_HEIGHT);
debug_ui.draw_solid_rect(RectI32::new(Point2DI32::new(PADDING, effects_panel_y),
Point2DI32::new(EFFECTS_PANEL_WIDTH,
EFFECTS_PANEL_HEIGHT)),
WINDOW_COLOR);
debug_ui.draw_solid_rounded_rect(RectI32::new(Point2DI32::new(PADDING, effects_panel_y),
Point2DI32::new(EFFECTS_PANEL_WIDTH,
EFFECTS_PANEL_HEIGHT)),
WINDOW_COLOR);
self.gamma_correction_effect_enabled =
self.draw_effects_switch(debug_ui,
@ -228,10 +233,10 @@ impl DemoUI {
let bottom = debug_ui.framebuffer_size().y() - PADDING;
let rotate_panel_y = bottom - (BUTTON_HEIGHT + PADDING + ROTATE_PANEL_HEIGHT);
debug_ui.draw_solid_rect(RectI32::new(Point2DI32::new(ROTATE_PANEL_X, rotate_panel_y),
Point2DI32::new(ROTATE_PANEL_WIDTH,
ROTATE_PANEL_HEIGHT)),
WINDOW_COLOR);
let rotate_panel_origin = Point2DI32::new(ROTATE_PANEL_X, rotate_panel_y);
let rotate_panel_size = Point2DI32::new(ROTATE_PANEL_WIDTH, ROTATE_PANEL_HEIGHT);
debug_ui.draw_solid_rounded_rect(RectI32::new(rotate_panel_origin, rotate_panel_size),
WINDOW_COLOR);
let (widget_x, widget_y) = (ROTATE_PANEL_X + PADDING, rotate_panel_y + PADDING);
let widget_rect = RectI32::new(Point2DI32::new(widget_x, widget_y),
@ -262,8 +267,8 @@ impl DemoUI {
texture: &Texture)
-> bool {
let button_rect = RectI32::new(origin, Point2DI32::new(BUTTON_WIDTH, BUTTON_HEIGHT));
debug_ui.draw_solid_rect(button_rect, WINDOW_COLOR);
debug_ui.draw_rect_outline(button_rect, TEXT_COLOR);
debug_ui.draw_solid_rounded_rect(button_rect, WINDOW_COLOR);
debug_ui.draw_rounded_rect_outline(button_rect, TEXT_COLOR);
debug_ui.draw_texture(origin + Point2DI32::new(PADDING, PADDING), texture, TEXT_COLOR);
event.handle_mouse_down_in_rect(button_rect).is_some()
}
@ -349,17 +354,17 @@ impl DemoUI {
value = !value;
}
debug_ui.draw_solid_rect(widget_rect, WINDOW_COLOR);
debug_ui.draw_rect_outline(widget_rect, TEXT_COLOR);
debug_ui.draw_solid_rounded_rect(widget_rect, WINDOW_COLOR);
debug_ui.draw_rounded_rect_outline(widget_rect, TEXT_COLOR);
let highlight_size = Point2DI32::new(SWITCH_HALF_SIZE, BUTTON_HEIGHT);
if !value {
debug_ui.draw_solid_rect(RectI32::new(origin, highlight_size), TEXT_COLOR);
debug_ui.draw_solid_rounded_rect(RectI32::new(origin, highlight_size), TEXT_COLOR);
} else {
let x_offset = SWITCH_HALF_SIZE + 1;
debug_ui.draw_solid_rect(RectI32::new(origin + Point2DI32::new(x_offset, 0),
highlight_size),
TEXT_COLOR);
debug_ui.draw_solid_rounded_rect(RectI32::new(origin + Point2DI32::new(x_offset, 0),
highlight_size),
TEXT_COLOR);
}
value

View File

@ -37,9 +37,6 @@ const DEBUG_TEXTURE_VERTEX_SIZE: GLint = 8;
const DEBUG_SOLID_VERTEX_SIZE: GLint = 4;
pub const PADDING: i32 = 12;
pub const BUTTON_WIDTH: i32 = PADDING * 2 + ICON_SIZE;
pub const BUTTON_HEIGHT: i32 = PADDING * 2 + ICON_SIZE;
pub const BUTTON_TEXT_OFFSET: i32 = PADDING + 36;
pub static TEXT_COLOR: ColorU = ColorU { r: 255, g: 255, b: 255, a: 255 };
pub static WINDOW_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 255 - 90 };
@ -48,14 +45,18 @@ const PERF_WINDOW_WIDTH: i32 = 375;
const PERF_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 6 + PADDING + 2;
const FONT_ASCENT: i32 = 28;
const LINE_HEIGHT: i32 = 42;
const ICON_SIZE: i32 = 48;
static INVERTED_TEXT_COLOR: ColorU = ColorU { r: 0, g: 0, b: 0, a: 255 };
static FONT_JSON_FILENAME: &'static str = "debug-font.json";
static FONT_PNG_NAME: &'static str = "debug-font";
static QUAD_INDICES: [u32; 6] = [0, 1, 3, 1, 2, 3];
static CORNER_FILL_PNG_NAME: &'static str = "debug-corner-fill";
static CORNER_OUTLINE_PNG_NAME: &'static str = "debug-corner-outline";
static QUAD_INDICES: [u32; 6] = [0, 1, 3, 1, 2, 3];
static RECT_LINE_INDICES: [u32; 8] = [0, 1, 1, 2, 2, 3, 3, 0];
static OUTLINE_RECT_LINE_INDICES: [u32; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
#[derive(Deserialize)]
#[allow(dead_code)]
@ -99,7 +100,10 @@ pub struct DebugUI {
font: DebugFont,
solid_program: DebugSolidProgram,
solid_vertex_array: DebugSolidVertexArray,
font_texture: Texture,
corner_fill_texture: Texture,
corner_outline_texture: Texture,
cpu_samples: SampleBuffer<CPUSample>,
gpu_samples: SampleBuffer<GPUSample>,
@ -113,20 +117,24 @@ impl DebugUI {
let solid_program = DebugSolidProgram::new(device);
let solid_vertex_array = DebugSolidVertexArray::new(&solid_program);
solid_vertex_array.index_buffer.upload(&QUAD_INDICES,
BufferTarget::Index,
BufferUploadMode::Static);
let font_texture = device.create_texture_from_png(FONT_PNG_NAME);
let corner_fill_texture = device.create_texture_from_png(CORNER_FILL_PNG_NAME);
let corner_outline_texture = device.create_texture_from_png(CORNER_OUTLINE_PNG_NAME);
DebugUI {
framebuffer_size,
texture_program,
texture_vertex_array,
font,
solid_program,
solid_vertex_array,
font_texture,
corner_fill_texture,
corner_outline_texture,
cpu_samples: SampleBuffer::new(),
gpu_samples: SampleBuffer::new(),
}
@ -157,7 +165,7 @@ impl DebugUI {
Point2DI32::new(self.framebuffer_size.x() - PADDING - PERF_WINDOW_WIDTH,
bottom - PERF_WINDOW_HEIGHT),
Point2DI32::new(PERF_WINDOW_WIDTH, PERF_WINDOW_HEIGHT));
self.draw_solid_rect(window_rect, WINDOW_COLOR);
self.draw_solid_rounded_rect(window_rect, WINDOW_COLOR);
let origin = window_rect.origin() + Point2DI32::new(PADDING, PADDING + FONT_ASCENT);
let mean_cpu_sample = self.cpu_samples.mean();
@ -171,6 +179,7 @@ impl DebugUI {
self.draw_text(&format!("Fills: {}", mean_cpu_sample.stats.fill_count),
origin + Point2DI32::new(0, LINE_HEIGHT * 3),
false);
self.draw_text(&format!("CPU Time: {:.3} ms", duration_to_ms(mean_cpu_sample.elapsed)),
origin + Point2DI32::new(0, LINE_HEIGHT * 4),
false);
@ -196,12 +205,31 @@ impl DebugUI {
DebugSolidVertex::new(rect.lower_right()),
DebugSolidVertex::new(rect.lower_left()),
];
self.solid_vertex_array
.vertex_buffer
.upload(&vertex_data, BufferTarget::Vertex, BufferUploadMode::Dynamic);
if filled {
self.draw_solid_rects_with_vertex_data(&vertex_data, &QUAD_INDICES, color, true);
} else {
self.draw_solid_rects_with_vertex_data(&vertex_data, &RECT_LINE_INDICES, color, false);
}
}
fn draw_solid_rects_with_vertex_data(&self,
vertex_data: &[DebugSolidVertex],
index_data: &[u32],
color: ColorU,
filled: bool) {
unsafe {
gl::BindVertexArray(self.solid_vertex_array.gl_vertex_array);
}
self.solid_vertex_array
.vertex_buffer
.upload(vertex_data, BufferTarget::Vertex, BufferUploadMode::Dynamic);
self.solid_vertex_array
.index_buffer
.upload(index_data, BufferTarget::Index, BufferUploadMode::Dynamic);
unsafe {
gl::UseProgram(self.solid_program.program.gl_program);
gl::Uniform2f(self.solid_program.framebuffer_size_uniform.location,
self.framebuffer_size.x() as GLfloat,
@ -210,11 +238,8 @@ impl DebugUI {
gl::BlendEquation(gl::FUNC_ADD);
gl::BlendFunc(gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
gl::Enable(gl::BLEND);
if filled {
gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
} else {
gl::DrawArrays(gl::LINE_LOOP, 0, 4);
}
let primitive = if filled { gl::TRIANGLES } else { gl::LINES };
gl::DrawElements(primitive, index_data.len() as GLint, gl::UNSIGNED_INT, ptr::null());
gl::Disable(gl::BLEND);
}
}
@ -278,6 +303,120 @@ impl DebugUI {
next
}
pub fn draw_solid_rounded_rect(&self, rect: RectI32, color: ColorU) {
let corner_texture = self.corner_texture(true);
let corner_rects = CornerRects::new(rect, corner_texture);
self.draw_rounded_rect_corners(color, corner_texture, &corner_rects);
let solid_rect_mid = RectI32::from_points(corner_rects.upper_left.upper_right(),
corner_rects.lower_right.lower_left());
let solid_rect_left = RectI32::from_points(corner_rects.upper_left.lower_left(),
corner_rects.lower_left.upper_right());
let solid_rect_right = RectI32::from_points(corner_rects.upper_right.lower_left(),
corner_rects.lower_right.upper_right());
let vertex_data = vec![
DebugSolidVertex::new(solid_rect_mid.origin()),
DebugSolidVertex::new(solid_rect_mid.upper_right()),
DebugSolidVertex::new(solid_rect_mid.lower_right()),
DebugSolidVertex::new(solid_rect_mid.lower_left()),
DebugSolidVertex::new(solid_rect_left.origin()),
DebugSolidVertex::new(solid_rect_left.upper_right()),
DebugSolidVertex::new(solid_rect_left.lower_right()),
DebugSolidVertex::new(solid_rect_left.lower_left()),
DebugSolidVertex::new(solid_rect_right.origin()),
DebugSolidVertex::new(solid_rect_right.upper_right()),
DebugSolidVertex::new(solid_rect_right.lower_right()),
DebugSolidVertex::new(solid_rect_right.lower_left()),
];
let mut index_data = Vec::with_capacity(18);
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 0));
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 4));
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 8));
self.draw_solid_rects_with_vertex_data(&vertex_data, &index_data[0..18], color, true);
}
pub fn draw_rounded_rect_outline(&self, rect: RectI32, color: ColorU) {
let corner_texture = self.corner_texture(false);
let corner_rects = CornerRects::new(rect, corner_texture);
self.draw_rounded_rect_corners(color, corner_texture, &corner_rects);
let vertex_data = vec![
DebugSolidVertex::new(corner_rects.upper_left.upper_right()),
DebugSolidVertex::new(corner_rects.upper_right.origin()),
DebugSolidVertex::new(corner_rects.upper_right.lower_right()),
DebugSolidVertex::new(corner_rects.lower_right.upper_right()),
DebugSolidVertex::new(corner_rects.lower_left.lower_right()),
DebugSolidVertex::new(corner_rects.lower_right.lower_left()),
DebugSolidVertex::new(corner_rects.upper_left.lower_left()),
DebugSolidVertex::new(corner_rects.lower_left.origin()),
];
let index_data = &OUTLINE_RECT_LINE_INDICES;
self.draw_solid_rects_with_vertex_data(&vertex_data, index_data, color, false);
}
fn draw_rounded_rect_corners(&self,
color: ColorU,
texture: &Texture,
corner_rects: &CornerRects) {
let corner_size = texture.size;
let tex_coord_rect = RectI32::new(Point2DI32::default(), corner_size);
let vertex_data = vec![
DebugTextureVertex::new(
corner_rects.upper_left.origin(), tex_coord_rect.origin()),
DebugTextureVertex::new(
corner_rects.upper_left.upper_right(), tex_coord_rect.upper_right()),
DebugTextureVertex::new(
corner_rects.upper_left.lower_right(), tex_coord_rect.lower_right()),
DebugTextureVertex::new(
corner_rects.upper_left.lower_left(), tex_coord_rect.lower_left()),
DebugTextureVertex::new(
corner_rects.upper_right.origin(), tex_coord_rect.lower_left()),
DebugTextureVertex::new(
corner_rects.upper_right.upper_right(), tex_coord_rect.origin()),
DebugTextureVertex::new(
corner_rects.upper_right.lower_right(), tex_coord_rect.upper_right()),
DebugTextureVertex::new(
corner_rects.upper_right.lower_left(), tex_coord_rect.lower_right()),
DebugTextureVertex::new(
corner_rects.lower_left.origin(), tex_coord_rect.upper_right()),
DebugTextureVertex::new(
corner_rects.lower_left.upper_right(), tex_coord_rect.lower_right()),
DebugTextureVertex::new(
corner_rects.lower_left.lower_right(), tex_coord_rect.lower_left()),
DebugTextureVertex::new(
corner_rects.lower_left.lower_left(), tex_coord_rect.origin()),
DebugTextureVertex::new(
corner_rects.lower_right.origin(), tex_coord_rect.lower_right()),
DebugTextureVertex::new(
corner_rects.lower_right.upper_right(), tex_coord_rect.lower_left()),
DebugTextureVertex::new(
corner_rects.lower_right.lower_right(), tex_coord_rect.origin()),
DebugTextureVertex::new(
corner_rects.lower_right.lower_left(), tex_coord_rect.upper_right()),
];
let mut index_data = Vec::with_capacity(24);
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 0));
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 4));
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 8));
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 12));
self.draw_texture_with_vertex_data(&vertex_data, &index_data, texture, color);
}
fn corner_texture(&self, filled: bool) -> &Texture {
if filled { &self.corner_fill_texture } else { &self.corner_outline_texture }
}
fn draw_texture_with_vertex_data(&self,
vertex_data: &[DebugTextureVertex],
index_data: &[u32],
@ -441,8 +580,9 @@ impl DebugSolidProgram {
}
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
#[allow(dead_code)]
#[repr(C)]
struct DebugTextureVertex {
position_x: i16,
position_y: i16,
@ -463,6 +603,7 @@ impl DebugTextureVertex {
#[derive(Clone, Copy)]
#[allow(dead_code)]
#[repr(C)]
struct DebugSolidVertex {
position_x: i16,
position_y: i16,
@ -572,3 +713,22 @@ impl Div<u32> for GPUSample {
fn duration_to_ms(time: Duration) -> f64 {
time.as_secs() as f64 * 1000.0 + time.subsec_nanos() as f64 / 1000000.0
}
struct CornerRects {
upper_left: RectI32,
upper_right: RectI32,
lower_left: RectI32,
lower_right: RectI32,
}
impl CornerRects {
fn new(rect: RectI32, texture: &Texture) -> CornerRects {
let size = texture.size;
CornerRects {
upper_left: RectI32::new(rect.origin(), size),
upper_right: RectI32::new(rect.upper_right() - Point2DI32::new(size.x(), 0), size),
lower_left: RectI32::new(rect.lower_left() - Point2DI32::new(0, size.y()), size),
lower_right: RectI32::new(rect.lower_right() - size, size),
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 792 B

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 973 B

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 B

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 B

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 B

After

Width:  |  Height:  |  Size: 338 B