From 753a25472672c6affe3b5f7951155dc47e5cccbb Mon Sep 17 00:00:00 2001 From: "bhmerchant@gmail.com" Date: Fri, 10 May 2019 22:57:34 -0700 Subject: [PATCH 01/28] batch alpha and solid tiles --- renderer/src/builder.rs | 6 +- renderer/src/gpu/renderer.rs | 222 +++++++++++++++++++++++++++-------- renderer/src/gpu_data.rs | 16 ++- 3 files changed, 188 insertions(+), 56 deletions(-) diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index a8c409e3..8695cee3 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -110,10 +110,10 @@ impl<'a> SceneBuilder<'a> { let path_count = self.scene.paths.len() as u32; let solid_tiles = self.z_buffer.build_solid_tiles(0..path_count); if !solid_tiles.is_empty() { - self.listener.send(RenderCommand::SolidTile(solid_tiles)); + self.listener.send(RenderCommand::AddSolidTiles(solid_tiles)); } if !alpha_tiles.is_empty() { - self.listener.send(RenderCommand::AlphaTile(alpha_tiles)); + self.listener.send(RenderCommand::AddAlphaTiles(alpha_tiles)); } } @@ -121,6 +121,8 @@ impl<'a> SceneBuilder<'a> { self.listener.send(RenderCommand::FlushFills); self.cull_alpha_tiles(&mut alpha_tiles); self.pack_alpha_tiles(alpha_tiles); + self.listener.send(RenderCommand::FlushSolidTiles); + self.listener.send(RenderCommand::FlushAlphaTiles); } } diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index e08d35d7..1a025795 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -45,6 +45,8 @@ const FILL_COLORS_TEXTURE_WIDTH: i32 = 256; const FILL_COLORS_TEXTURE_HEIGHT: i32 = 256; const MAX_FILLS_PER_BATCH: usize = 0x4000; +const MAX_ALPHA_TILES_PER_BATCH: usize = 0x4000; +const MAX_SOLID_TILES_PER_BATCH: usize = 0x4000; pub struct Renderer where @@ -87,6 +89,8 @@ where // Rendering state mask_framebuffer_cleared: bool, buffered_fills: Vec, + buffered_alpha_tiles: Vec, + buffered_solid_tiles: Vec, // Debug pub stats: RenderStats, @@ -216,6 +220,8 @@ where mask_framebuffer_cleared: false, buffered_fills: vec![], + buffered_alpha_tiles: vec![], + buffered_solid_tiles: vec![], render_mode: RenderMode::default(), use_depth: false, @@ -236,7 +242,10 @@ where pub fn render_command(&mut self, command: &RenderCommand) { match *command { - RenderCommand::Start { bounding_quad, path_count } => { + RenderCommand::Start { + bounding_quad, + path_count, + } => { if self.use_depth { self.draw_stencil(&bounding_quad); } @@ -248,17 +257,15 @@ where self.begin_composite_timer_query(); self.draw_buffered_fills(); } - RenderCommand::SolidTile(ref solid_tiles) => { - let count = solid_tiles.len(); - self.stats.solid_tile_count += count; - self.upload_solid_tiles(solid_tiles); - self.draw_solid_tiles(count as u32); + RenderCommand::AddSolidTiles(ref solid_tiles) => self.add_solid_tiles(solid_tiles), + RenderCommand::FlushSolidTiles => { + self.begin_composite_timer_query(); + self.draw_buffered_solid_tiles(); } - RenderCommand::AlphaTile(ref alpha_tiles) => { - let count = alpha_tiles.len(); - self.stats.alpha_tile_count += count; - self.upload_alpha_tiles(alpha_tiles); - self.draw_alpha_tiles(count as u32); + RenderCommand::AddAlphaTiles(ref alpha_tiles) => self.add_alpha_tiles(alpha_tiles), + RenderCommand::FlushAlphaTiles => { + self.begin_composite_timer_query(); + self.draw_buffered_alpha_tiles(); } RenderCommand::Finish { .. } => {} } @@ -270,7 +277,8 @@ where } self.end_composite_timer_query(); - self.pending_timers.push_back(mem::replace(&mut self.current_timers, RenderTimers::new())); + self.pending_timers + .push_back(mem::replace(&mut self.current_timers, RenderTimers::new())); } pub fn draw_debug_ui(&self) { @@ -304,7 +312,10 @@ where self.free_timer_queries.extend(timers.stage_0.into_iter()); self.free_timer_queries.push(timers.stage_1.unwrap()); - Some(RenderTime { stage_0: total_stage_0_time, stage_1: stage_1_time }) + Some(RenderTime { + stage_0: total_stage_0_time, + stage_1: stage_1_time, + }) } #[inline] @@ -322,7 +333,9 @@ where #[inline] pub fn set_main_framebuffer_size(&mut self, new_framebuffer_size: Point2DI32) { - self.debug_ui_presenter.ui_presenter.set_framebuffer_size(new_framebuffer_size); + self.debug_ui_presenter + .ui_presenter + .set_framebuffer_size(new_framebuffer_size); } #[inline] @@ -358,24 +371,6 @@ where .upload_to_texture(&self.fill_colors_texture, size, &fill_colors); } - fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileBatchPrimitive]) { - self.device.allocate_buffer( - &self.solid_tile_vertex_array().vertex_buffer, - BufferData::Memory(&solid_tiles), - BufferTarget::Vertex, - BufferUploadMode::Dynamic, - ); - } - - fn upload_alpha_tiles(&mut self, alpha_tiles: &[AlphaTileBatchPrimitive]) { - self.device.allocate_buffer( - &self.alpha_tile_vertex_array().vertex_buffer, - BufferData::Memory(&alpha_tiles), - BufferTarget::Vertex, - BufferUploadMode::Dynamic, - ); - } - fn clear_mask_framebuffer(&mut self) { self.device.bind_framebuffer(&self.mask_framebuffer); @@ -409,6 +404,60 @@ where self.current_timers.stage_0.push(timer_query); } + fn add_solid_tiles(&mut self, mut solid_tiles: &[SolidTileBatchPrimitive]) { + if solid_tiles.is_empty() { + return; + } + + let timer_query = self.allocate_timer_query(); + self.device.begin_timer_query(&timer_query); + + self.stats.solid_tile_count += solid_tiles.len(); + + while !solid_tiles.is_empty() { + let count = cmp::min( + solid_tiles.len(), + MAX_SOLID_TILES_PER_BATCH - self.buffered_solid_tiles.len(), + ); + self.buffered_solid_tiles + .extend_from_slice(&solid_tiles[0..count]); + solid_tiles = &solid_tiles[count..]; + if self.buffered_solid_tiles.len() == MAX_SOLID_TILES_PER_BATCH { + self.draw_buffered_solid_tiles(); + } + } + + self.device.end_timer_query(&timer_query); + self.current_timers.stage_0.push(timer_query); + } + + fn add_alpha_tiles(&mut self, mut alpha_tiles: &[AlphaTileBatchPrimitive]) { + if alpha_tiles.is_empty() { + return; + } + + let timer_query = self.allocate_timer_query(); + self.device.begin_timer_query(&timer_query); + + self.stats.alpha_tile_count += alpha_tiles.len(); + + while !alpha_tiles.is_empty() { + let count = cmp::min( + alpha_tiles.len(), + MAX_ALPHA_TILES_PER_BATCH - self.buffered_alpha_tiles.len(), + ); + self.buffered_alpha_tiles + .extend_from_slice(&alpha_tiles[0..count]); + alpha_tiles = &alpha_tiles[count..]; + if self.buffered_alpha_tiles.len() == MAX_ALPHA_TILES_PER_BATCH { + self.draw_buffered_alpha_tiles(); + } + } + + self.device.end_timer_query(&timer_query); + self.current_timers.stage_0.push(timer_query); + } + fn draw_buffered_fills(&mut self) { if self.buffered_fills.is_empty() { return; @@ -461,12 +510,24 @@ where self.buffered_fills.clear() } - fn draw_alpha_tiles(&mut self, count: u32) { - self.bind_draw_framebuffer(); + fn draw_buffered_alpha_tiles(&mut self) { + if self.buffered_alpha_tiles.is_empty() { + return; + } let alpha_tile_vertex_array = self.alpha_tile_vertex_array(); + + self.device.allocate_buffer( + &alpha_tile_vertex_array.vertex_buffer, + BufferData::Memory(&self.buffered_alpha_tiles), + BufferTarget::Vertex, + BufferUploadMode::Dynamic, + ); + let alpha_tile_program = self.alpha_tile_program(); + self.bind_draw_framebuffer(); + self.device .bind_vertex_array(&alpha_tile_vertex_array.vertex_array); self.device.use_program(&alpha_tile_program.program); @@ -534,16 +595,35 @@ where stencil: self.stencil_state(), ..RenderState::default() }; - self.device - .draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state); + debug_assert!(self.buffered_alpha_tiles.len() <= u32::MAX as usize); + self.device.draw_arrays_instanced( + Primitive::TriangleFan, + 4, + self.buffered_alpha_tiles.len() as u32, + &render_state, + ); + + self.buffered_alpha_tiles.clear(); } - fn draw_solid_tiles(&mut self, count: u32) { - self.bind_draw_framebuffer(); + fn draw_buffered_solid_tiles(&mut self) { + if self.buffered_solid_tiles.is_empty() { + return; + } let solid_tile_vertex_array = self.solid_tile_vertex_array(); + + self.device.allocate_buffer( + &solid_tile_vertex_array.vertex_buffer, + BufferData::Memory(&self.buffered_solid_tiles), + BufferTarget::Vertex, + BufferUploadMode::Dynamic, + ); + let solid_tile_program = self.solid_tile_program(); + self.bind_draw_framebuffer(); + self.device .bind_vertex_array(&solid_tile_vertex_array.vertex_array); self.device.use_program(&solid_tile_program.program); @@ -598,8 +678,15 @@ where stencil: self.stencil_state(), ..RenderState::default() }; - self.device - .draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state); + debug_assert!(self.buffered_solid_tiles.len() <= u32::MAX as usize); + self.device.draw_arrays_instanced( + Primitive::TriangleFan, + 4, + self.buffered_solid_tiles.len() as u32, + &render_state, + ); + + self.buffered_solid_tiles.clear(); } fn postprocess(&mut self) { @@ -888,7 +975,11 @@ where } fn end_composite_timer_query(&mut self) { - let query = self.current_timers.stage_1.as_ref().expect("No stage 1 timer query yet?!"); + let query = self + .current_timers + .stage_1 + .as_ref() + .expect("No stage 1 timer query yet?!"); self.device.end_timer_query(&query); } } @@ -1001,7 +1092,17 @@ where alpha_tile_program: &AlphaTileProgram, quad_vertex_positions_buffer: &D::Buffer, ) -> AlphaTileVertexArray { - let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); + let vertex_array = device.create_vertex_array(); + + let vertex_buffer = device.create_buffer(); + let vertex_buffer_data: BufferData = + BufferData::Uninitialized(MAX_ALPHA_TILES_PER_BATCH); + device.allocate_buffer( + &vertex_buffer, + vertex_buffer_data, + BufferTarget::Vertex, + BufferUploadMode::Dynamic, + ); let tess_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "TessCoord"); let tile_origin_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileOrigin"); @@ -1073,7 +1174,17 @@ where solid_tile_program: &SolidTileProgram, quad_vertex_positions_buffer: &D::Buffer, ) -> SolidTileVertexArray { - let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); + let vertex_array = device.create_vertex_array(); + + let vertex_buffer = device.create_buffer(); + let vertex_buffer_data: BufferData = + BufferData::Uninitialized(MAX_SOLID_TILES_PER_BATCH); + device.allocate_buffer( + &vertex_buffer, + vertex_buffer_data, + BufferTarget::Vertex, + BufferUploadMode::Dynamic, + ); let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord"); let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin"); @@ -1512,7 +1623,10 @@ where #[inline] pub fn full_window(window_size: Point2DI32) -> DestFramebuffer { let viewport = RectI32::new(Point2DI32::default(), window_size); - DestFramebuffer::Default { viewport, window_size } + DestFramebuffer::Default { + viewport, + window_size, + } } fn window_size(&self, device: &D) -> Point2DI32 { @@ -1575,14 +1689,23 @@ impl Div for RenderStats { } } -struct RenderTimers where D: Device { +struct RenderTimers +where + D: Device, +{ stage_0: Vec, stage_1: Option, } -impl RenderTimers where D: Device { +impl RenderTimers +where + D: Device, +{ fn new() -> RenderTimers { - RenderTimers { stage_0: vec![], stage_1: None } + RenderTimers { + stage_0: vec![], + stage_1: None, + } } } @@ -1595,7 +1718,10 @@ pub struct RenderTime { impl Default for RenderTime { #[inline] fn default() -> RenderTime { - RenderTime { stage_0: Duration::new(0, 0), stage_1: Duration::new(0, 0) } + RenderTime { + stage_0: Duration::new(0, 0), + stage_1: Duration::new(0, 0), + } } } diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index c130abd6..8a998981 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -31,8 +31,10 @@ pub enum RenderCommand { AddShaders(Vec), AddFills(Vec), FlushFills, - AlphaTile(Vec), - SolidTile(Vec), + AddAlphaTiles(Vec), + FlushAlphaTiles, + AddSolidTiles(Vec), + FlushSolidTiles, Finish { build_time: Duration }, } @@ -89,12 +91,14 @@ impl Debug for RenderCommand { } RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()), RenderCommand::FlushFills => write!(formatter, "FlushFills"), - RenderCommand::AlphaTile(ref tiles) => { - write!(formatter, "AlphaTile(x{})", tiles.len()) + RenderCommand::AddAlphaTiles(ref tiles) => { + write!(formatter, "AddAlphaTiles(x{})", tiles.len()) } - RenderCommand::SolidTile(ref tiles) => { - write!(formatter, "SolidTile(x{})", tiles.len()) + RenderCommand::FlushAlphaTiles => write!(formatter, "FlushAlphaTiles"), + RenderCommand::AddSolidTiles(ref tiles) => { + write!(formatter, "AddSolidTiles(x{})", tiles.len()) } + RenderCommand::FlushSolidTiles => write!(formatter, "FlushSolidTiles"), RenderCommand::Finish { .. } => write!(formatter, "Finish"), } } From 820a0286aab4a6edccdd46e658e258cd0b3e1338 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 13 May 2019 18:00:54 +0200 Subject: [PATCH 02/28] Fix vertex attribute configuration of alpha tiles. Fixes #134. glVertexAttribPointer takes a size as parameter which refers to the number of components and not the size in bytes of the value. The tile index was registered as a 2-components value which caused the second component to overlap with the first member of the next primitive, which was mostly fine except for the last element which would overlfow the buffer. Intel and nvidia GPUs/drivers on linux at least refuse to read the first component of this two-component value if the other component is outside of the valid range which caused the shader to get zero instead and always select the first mask tile. --- renderer/src/gpu/renderer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index e08d35d7..b355215d 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -1034,7 +1034,7 @@ where ); device.configure_int_vertex_attr( &object_attr, - 2, + 1, VertexAttrType::I16, MASK_TILE_INSTANCE_SIZE, 4, @@ -1042,7 +1042,7 @@ where ); device.configure_int_vertex_attr( &tile_index_attr, - 2, + 1, VertexAttrType::I16, MASK_TILE_INSTANCE_SIZE, 6, From f24d93819bb45edfb78f16b2d59e03edc1ecfb4a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 13 May 2019 12:17:49 -0700 Subject: [PATCH 03/28] =?UTF-8?q?Add=20arc=20building=20methods=20and=20sw?= =?UTF-8?q?itch=20the=20Moir=C3=A9=20demo=20to=20use=20them.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, stop taking points by reference in many methods, for consistency. --- Cargo.lock | 1 + canvas/src/lib.rs | 11 +++-- examples/canvas_moire/Cargo.toml | 1 + examples/canvas_moire/src/main.rs | 22 +++------- geometry/src/basic/line_segment.rs | 2 +- geometry/src/basic/transform2d.rs | 54 +++++++++++++------------ geometry/src/clip.rs | 2 +- geometry/src/outline.rs | 64 ++++++++++++++++++++++-------- geometry/src/segment.rs | 44 ++++++++++++++++---- geometry/src/stroke.rs | 34 ++++++++-------- renderer/src/builder.rs | 10 ++--- renderer/src/scene.rs | 2 +- renderer/src/tiles.rs | 3 +- text/src/lib.rs | 4 +- 14 files changed, 157 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da630ac5..fbc2bb2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,6 +180,7 @@ dependencies = [ "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", + "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 49cbd3f2..63d68222 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -97,7 +97,7 @@ impl CanvasRenderingContext2D { drop(self.scene.push_text(string, &TextStyle { size: self.current_state.font_size }, &self.current_state.font_collection, - &Transform2DF32::from_translation(&position), + &Transform2DF32::from_translation(position), TextRenderMode::Fill, HintingOptions::None, paint_id)); @@ -109,7 +109,7 @@ impl CanvasRenderingContext2D { drop(self.scene.push_text(string, &TextStyle { size: self.current_state.font_size }, &self.current_state.font_collection, - &Transform2DF32::from_translation(&position), + &Transform2DF32::from_translation(position), TextRenderMode::Stroke(self.current_state.line_width), HintingOptions::None, paint_id)); @@ -196,7 +196,7 @@ pub struct Path2D { current_contour: Contour, } -// TODO(pcwalton): `arc`, `ellipse` +// TODO(pcwalton): `ellipse` impl Path2D { #[inline] pub fn new() -> Path2D { @@ -230,6 +230,11 @@ impl Path2D { self.current_contour.push_cubic(ctrl0, ctrl1, to); } + #[inline] + pub fn arc(&mut self, center: Point2DF32, radius: f32, start_angle: f32, end_angle: f32) { + self.current_contour.push_arc(center, radius, start_angle, end_angle); + } + pub fn rect(&mut self, rect: RectF32) { self.flush_current_contour(); self.current_contour.push_endpoint(rect.origin()); diff --git a/examples/canvas_moire/Cargo.toml b/examples/canvas_moire/Cargo.toml index 0bab187d..c8b9b4b7 100644 --- a/examples/canvas_moire/Cargo.toml +++ b/examples/canvas_moire/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] gl = "0.6" +pretty_env_logger = "0.3" sdl2 = "0.32" sdl2-sys = "0.32" diff --git a/examples/canvas_moire/src/main.rs b/examples/canvas_moire/src/main.rs index 61b02e51..cf58250a 100644 --- a/examples/canvas_moire/src/main.rs +++ b/examples/canvas_moire/src/main.rs @@ -21,6 +21,7 @@ use pathfinder_renderer::options::RenderOptions; use sdl2::event::Event; use sdl2::keyboard::Keycode; use sdl2::video::GLProfile; +use std::f32::consts::PI; use std::f32; const VELOCITY: f32 = 0.02; @@ -36,6 +37,8 @@ const CIRCLE_THICKNESS: f32 = 16.0; const COLOR_CYCLE_SPEED: f32 = 0.0025; fn main() { + pretty_env_logger::init(); + // Set up SDL2. let sdl_context = sdl2::init().unwrap(); let video = sdl_context.video().unwrap(); @@ -150,27 +153,14 @@ impl MoireRenderer { } fn draw_circles(&self, canvas: &mut CanvasRenderingContext2D, center: Point2DF32) { + let center = center.scale(self.device_pixel_ratio); for index in 0..CIRCLE_COUNT { + let radius = (index + 1) as f32 * CIRCLE_SPACING * self.device_pixel_ratio; let mut path = Path2D::new(); - self.add_circle_subpath(&mut path, - center.scale(self.device_pixel_ratio), - index as f32 * CIRCLE_SPACING * self.device_pixel_ratio); + path.arc(center, radius, 0.0, PI * 2.0); canvas.stroke_path(path); } } - - fn add_circle_subpath(&self, path: &mut Path2D, center: Point2DF32, radius: f32) { - path.move_to(center + Point2DF32::new(0.0, -radius)); - path.quadratic_curve_to(center + Point2DF32::new(radius, -radius), - center + Point2DF32::new(radius, 0.0)); - path.quadratic_curve_to(center + Point2DF32::new(radius, radius), - center + Point2DF32::new(0.0, radius)); - path.quadratic_curve_to(center + Point2DF32::new(-radius, radius), - center + Point2DF32::new(-radius, 0.0)); - path.quadratic_curve_to(center + Point2DF32::new(-radius, -radius), - center + Point2DF32::new(0.0, -radius)); - path.close_path(); - } } struct ColorGradient([ColorF; 5]); diff --git a/geometry/src/basic/line_segment.rs b/geometry/src/basic/line_segment.rs index 3657ded9..9976fd38 100644 --- a/geometry/src/basic/line_segment.rs +++ b/geometry/src/basic/line_segment.rs @@ -20,7 +20,7 @@ pub struct LineSegmentF32(pub F32x4); impl LineSegmentF32 { #[inline] - pub fn new(from: &Point2DF32, to: &Point2DF32) -> LineSegmentF32 { + pub fn new(from: Point2DF32, to: Point2DF32) -> LineSegmentF32 { LineSegmentF32(from.0.concat_xy_xy(to.0)) } diff --git a/geometry/src/basic/transform2d.rs b/geometry/src/basic/transform2d.rs index 112b4779..72430551 100644 --- a/geometry/src/basic/transform2d.rs +++ b/geometry/src/basic/transform2d.rs @@ -10,6 +10,7 @@ //! 2D affine transforms. +use crate::basic::line_segment::LineSegmentF32; use crate::basic::point::Point2DF32; use crate::basic::rect::RectF32; use crate::basic::transform3d::Transform3DF32; @@ -24,13 +25,13 @@ pub struct Matrix2x2F32(pub F32x4); impl Default for Matrix2x2F32 { #[inline] fn default() -> Matrix2x2F32 { - Self::from_scale(&Point2DF32::splat(1.0)) + Self::from_scale(Point2DF32::splat(1.0)) } } impl Matrix2x2F32 { #[inline] - pub fn from_scale(scale: &Point2DF32) -> Matrix2x2F32 { + pub fn from_scale(scale: Point2DF32) -> Matrix2x2F32 { Matrix2x2F32(F32x4::new(scale.x(), 0.0, 0.0, scale.y())) } @@ -66,7 +67,7 @@ impl Matrix2x2F32 { } #[inline] - pub fn transform_point(&self, point: &Point2DF32) -> Point2DF32 { + pub fn transform_point(&self, point: Point2DF32) -> Point2DF32 { let halves = self.0 * point.0.xxyy(); Point2DF32(halves + halves.zwzw()) } @@ -118,13 +119,13 @@ pub struct Transform2DF32 { impl Default for Transform2DF32 { #[inline] fn default() -> Transform2DF32 { - Self::from_scale(&Point2DF32::splat(1.0)) + Self::from_scale(Point2DF32::splat(1.0)) } } impl Transform2DF32 { #[inline] - pub fn from_scale(scale: &Point2DF32) -> Transform2DF32 { + pub fn from_scale(scale: Point2DF32) -> Transform2DF32 { Transform2DF32 { matrix: Matrix2x2F32::from_scale(scale), vector: Point2DF32::default(), @@ -140,11 +141,8 @@ impl Transform2DF32 { } #[inline] - pub fn from_translation(vector: &Point2DF32) -> Transform2DF32 { - Transform2DF32 { - matrix: Matrix2x2F32::default(), - vector: *vector, - } + pub fn from_translation(vector: Point2DF32) -> Transform2DF32 { + Transform2DF32 { matrix: Matrix2x2F32::default(), vector } } #[inline] @@ -154,10 +152,8 @@ impl Transform2DF32 { translation: Point2DF32, ) -> Transform2DF32 { let rotation = Transform2DF32::from_rotation(theta); - let translation = Transform2DF32::from_translation(&translation); - Transform2DF32::from_scale(&scale) - .post_mul(&rotation) - .post_mul(&translation) + let translation = Transform2DF32::from_translation(translation); + Transform2DF32::from_scale(scale).post_mul(&rotation).post_mul(&translation) } #[inline] @@ -169,16 +165,22 @@ impl Transform2DF32 { } #[inline] - pub fn transform_point(&self, point: &Point2DF32) -> Point2DF32 { + pub fn transform_point(&self, point: Point2DF32) -> Point2DF32 { self.matrix.transform_point(point) + self.vector } + #[inline] + pub fn transform_line_segment(&self, line_segment: &LineSegmentF32) -> LineSegmentF32 { + LineSegmentF32::new(self.transform_point(line_segment.from()), + self.transform_point(line_segment.to())) + } + #[inline] pub fn transform_rect(&self, rect: &RectF32) -> RectF32 { - let upper_left = self.transform_point(&rect.origin()); - let upper_right = self.transform_point(&rect.upper_right()); - let lower_left = self.transform_point(&rect.lower_left()); - let lower_right = self.transform_point(&rect.lower_right()); + let upper_left = self.transform_point(rect.origin()); + let upper_right = self.transform_point(rect.upper_right()); + let lower_left = self.transform_point(rect.lower_left()); + let lower_right = self.transform_point(rect.lower_right()); let min_point = upper_left.min(upper_right).min(lower_left).min(lower_right); let max_point = upper_left.max(upper_right).max(lower_left).max(lower_right); RectF32::from_points(min_point, max_point) @@ -187,7 +189,7 @@ impl Transform2DF32 { #[inline] pub fn post_mul(&self, other: &Transform2DF32) -> Transform2DF32 { let matrix = self.matrix.post_mul(&other.matrix); - let vector = other.transform_point(&self.vector); + let vector = other.transform_point(self.vector); Transform2DF32 { matrix, vector } } @@ -243,7 +245,7 @@ impl Transform2DF32 { #[inline] pub fn post_translate(&self, vector: Point2DF32) -> Transform2DF32 { - self.post_mul(&Transform2DF32::from_translation(&vector)) + self.post_mul(&Transform2DF32::from_translation(vector)) } #[inline] @@ -253,7 +255,7 @@ impl Transform2DF32 { #[inline] pub fn post_scale(&self, scale: Point2DF32) -> Transform2DF32 { - self.post_mul(&Transform2DF32::from_scale(&scale)) + self.post_mul(&Transform2DF32::from_scale(scale)) } /// Returns the translation part of this matrix. @@ -303,18 +305,18 @@ where if !segment.is_none() { segment .baseline - .set_from(&self.transform.transform_point(&segment.baseline.from())); + .set_from(&self.transform.transform_point(segment.baseline.from())); segment .baseline - .set_to(&self.transform.transform_point(&segment.baseline.to())); + .set_to(&self.transform.transform_point(segment.baseline.to())); if !segment.is_line() { segment .ctrl - .set_from(&self.transform.transform_point(&segment.ctrl.from())); + .set_from(&self.transform.transform_point(segment.ctrl.from())); if !segment.is_quadratic() { segment .ctrl - .set_to(&self.transform.transform_point(&segment.ctrl.to())); + .set_to(&self.transform.transform_point(segment.ctrl.to())); } } } diff --git a/geometry/src/clip.rs b/geometry/src/clip.rs index d15f63c3..315b8bd9 100644 --- a/geometry/src/clip.rs +++ b/geometry/src/clip.rs @@ -325,7 +325,7 @@ impl ContourPolygonClipper { Some(prev) => *prev, }; for &next in &clip_polygon { - self.clip_against(Edge(LineSegmentF32::new(&prev, &next))); + self.clip_against(Edge(LineSegmentF32::new(prev, next))); prev = next; } diff --git a/geometry/src/outline.rs b/geometry/src/outline.rs index 9a5f3c93..7b5e3699 100644 --- a/geometry/src/outline.rs +++ b/geometry/src/outline.rs @@ -19,6 +19,7 @@ use crate::clip::{self, ContourPolygonClipper, ContourRectClipper}; use crate::dilation::ContourDilator; use crate::orientation::Orientation; use crate::segment::{Segment, SegmentFlags, SegmentKind}; +use std::f32::consts::FRAC_PI_2; use std::fmt::{self, Debug, Formatter}; use std::mem; @@ -292,7 +293,10 @@ impl Contour { // TODO(pcwalton): SIMD. #[inline] - pub(crate) fn push_point(&mut self, point: Point2DF32, flags: PointFlags, update_bounds: bool) { + pub(crate) fn push_point(&mut self, + point: Point2DF32, + flags: PointFlags, + update_bounds: bool) { debug_assert!(!point.x().is_nan() && !point.y().is_nan()); if update_bounds { @@ -354,6 +358,37 @@ impl Contour { self.push_point(segment.baseline.to(), PointFlags::empty(), update_bounds); } + pub fn push_arc(&mut self, center: Point2DF32, radius: f32, start_angle: f32, end_angle: f32) { + let scale = Transform2DF32::from_scale(Point2DF32::splat(radius)); + let translation = Transform2DF32::from_translation(center); + + let (mut angle, mut first_segment) = (start_angle, true); + while angle < end_angle { + let sweep_angle = f32::min(FRAC_PI_2, end_angle - angle); + let mut segment = Segment::arc(sweep_angle); + let rotation = Transform2DF32::from_rotation(angle); + segment = segment.transform(&scale.post_mul(&rotation).post_mul(&translation)); + + /* + println!("angle={} start_angle={} end_angle={} sweep_angle={} segment={:?}", + angle, + start_angle, + end_angle, + sweep_angle, + segment); + */ + + if first_segment { + self.push_full_segment(&segment, true); + first_segment = false; + } else { + self.push_segment(segment, true); + } + + angle += sweep_angle; + } + } + #[inline] pub fn segment_after(&self, point_index: u32) -> Segment { debug_assert!(self.point_is_endpoint(point_index)); @@ -388,8 +423,8 @@ impl Contour { pub fn hull_segment_after(&self, prev_point_index: u32) -> LineSegmentF32 { let next_point_index = self.next_point_index_of(prev_point_index); LineSegmentF32::new( - &self.points[prev_point_index as usize], - &self.points[next_point_index as usize], + self.points[prev_point_index as usize], + self.points[next_point_index as usize], ) } @@ -455,7 +490,7 @@ impl Contour { pub fn transform(&mut self, transform: &Transform2DF32) { for (point_index, point) in self.points.iter_mut().enumerate() { - *point = transform.transform_point(point); + *point = transform.transform_point(*point); union_rect(&mut self.bounds, *point, point_index == 0); } } @@ -522,8 +557,8 @@ impl Contour { point_index }; let baseline = LineSegmentF32::new( - &contour.points[last_endpoint_index as usize], - &contour.points[position_index as usize], + contour.points[last_endpoint_index as usize], + contour.points[position_index as usize], ); let point_count = point_index - last_endpoint_index + 1; if point_count == 3 { @@ -531,13 +566,13 @@ impl Contour { let ctrl_position = &contour.points[ctrl_point_index]; handle_cubic( self, - Segment::quadratic(&baseline, &ctrl_position).to_cubic(), + Segment::quadratic(&baseline, *ctrl_position).to_cubic(), ); } else if point_count == 4 { let first_ctrl_point_index = last_endpoint_index as usize + 1; let ctrl_position_0 = &contour.points[first_ctrl_point_index + 0]; let ctrl_position_1 = &contour.points[first_ctrl_point_index + 1]; - let ctrl = LineSegmentF32::new(&ctrl_position_0, &ctrl_position_1); + let ctrl = LineSegmentF32::new(*ctrl_position_0, *ctrl_position_1); handle_cubic(self, Segment::cubic(&baseline, &ctrl)); } @@ -723,24 +758,21 @@ impl<'a> Iterator for ContourIter<'a> { if self.index == contour.len() { let point1 = contour.position_of(0); self.index += 1; - return Some(Segment::line(&LineSegmentF32::new(&point0, &point1))); + return Some(Segment::line(&LineSegmentF32::new(point0, point1))); } let point1_index = self.index; self.index += 1; let point1 = contour.position_of(point1_index); if contour.point_is_endpoint(point1_index) { - return Some(Segment::line(&LineSegmentF32::new(&point0, &point1))); + return Some(Segment::line(&LineSegmentF32::new(point0, point1))); } let point2_index = self.index; let point2 = contour.position_of(point2_index); self.index += 1; if contour.point_is_endpoint(point2_index) { - return Some(Segment::quadratic( - &LineSegmentF32::new(&point0, &point2), - &point1, - )); + return Some(Segment::quadratic(&LineSegmentF32::new(point0, point2), point1)); } let point3_index = self.index; @@ -748,8 +780,8 @@ impl<'a> Iterator for ContourIter<'a> { self.index += 1; debug_assert!(contour.point_is_endpoint(point3_index)); return Some(Segment::cubic( - &LineSegmentF32::new(&point0, &point3), - &LineSegmentF32::new(&point1, &point2), + &LineSegmentF32::new(point0, point3), + &LineSegmentF32::new(point1, point2), )); } } diff --git a/geometry/src/segment.rs b/geometry/src/segment.rs index 3334d1b0..6fdc28eb 100644 --- a/geometry/src/segment.rs +++ b/geometry/src/segment.rs @@ -12,8 +12,10 @@ use crate::basic::line_segment::LineSegmentF32; use crate::basic::point::Point2DF32; +use crate::basic::transform2d::Transform2DF32; use crate::util::{self, EPSILON}; use pathfinder_simd::default::F32x4; +use std::f32::consts::SQRT_2; const MAX_NEWTON_ITERATIONS: u32 = 32; @@ -47,10 +49,10 @@ impl Segment { } #[inline] - pub fn quadratic(baseline: &LineSegmentF32, ctrl: &Point2DF32) -> Segment { + pub fn quadratic(baseline: &LineSegmentF32, ctrl: Point2DF32) -> Segment { Segment { baseline: *baseline, - ctrl: LineSegmentF32::new(ctrl, &Point2DF32::default()), + ctrl: LineSegmentF32::new(ctrl, Point2DF32::default()), kind: SegmentKind::Quadratic, flags: SegmentFlags::empty(), } @@ -66,6 +68,24 @@ impl Segment { } } + /// Approximates an unit-length arc with a cubic Bézier curve. + /// + /// The maximum supported `sweep_angle` is π/2 (i.e. 90°). + pub fn arc(sweep_angle: f32) -> Segment { + // Aleksas Riškus, "Approximation of a Cubic Bézier Curve by Circular Arcs and Vice Versa" + // 2006. + // + // https://pdfs.semanticscholar.org/1639/0db1a470bd13fe428e0896671a9a5745070a.pdf + let phi = 0.5 * sweep_angle; + let p0 = Point2DF32::new(f32::cos(phi), f32::sin(phi)); + let p3 = p0.scale_xy(Point2DF32::new(1.0, -1.0)); + let p1 = p0 - p3.yx().scale(K); + let p2 = p3 + p0.yx().scale(K); + return Segment::cubic(&LineSegmentF32::new(p3, p0), &LineSegmentF32::new(p2, p1)); + + const K: f32 = 4.0 / 3.0 * (SQRT_2 - 1.0); + } + #[inline] pub fn as_line_segment(&self) -> LineSegmentF32 { debug_assert!(self.is_line()); @@ -109,7 +129,7 @@ impl Segment { let mut new_segment = *self; let p1_2 = self.ctrl.from() + self.ctrl.from(); new_segment.ctrl = - LineSegmentF32::new(&(self.baseline.from() + p1_2), &(p1_2 + self.baseline.to())) + LineSegmentF32::new(self.baseline.from() + p1_2, p1_2 + self.baseline.to()) .scale(1.0 / 3.0); new_segment.kind = SegmentKind::Cubic; new_segment @@ -176,6 +196,16 @@ impl Segment { self.to_cubic().as_cubic_segment().sample(t) } } + + #[inline] + pub fn transform(self, transform: &Transform2DF32) -> Segment { + Segment { + baseline: transform.transform_line_segment(&self.baseline), + ctrl: transform.transform_line_segment(&self.ctrl), + kind: self.kind, + flags: self.flags, + } + } } #[derive(Clone, Copy, Debug, PartialEq)] @@ -215,16 +245,16 @@ impl<'s> CubicSegment<'s> { let (baseline0, ctrl0, baseline1, ctrl1); if t <= 0.0 { let from = &self.0.baseline.from(); - baseline0 = LineSegmentF32::new(from, from); - ctrl0 = LineSegmentF32::new(from, from); + baseline0 = LineSegmentF32::new(*from, *from); + ctrl0 = LineSegmentF32::new(*from, *from); baseline1 = self.0.baseline; ctrl1 = self.0.ctrl; } else if t >= 1.0 { let to = &self.0.baseline.to(); baseline0 = self.0.baseline; ctrl0 = self.0.ctrl; - baseline1 = LineSegmentF32::new(to, to); - ctrl1 = LineSegmentF32::new(to, to); + baseline1 = LineSegmentF32::new(*to, *to); + ctrl1 = LineSegmentF32::new(*to, *to); } else { let tttt = F32x4::splat(t); diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index 1a1959a8..0420b601 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -118,51 +118,51 @@ impl Offset for Segment { } if self.is_quadratic() { - let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from()); - let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to()); + let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.from()); + let mut segment_1 = LineSegmentF32::new(self.ctrl.from(), self.baseline.to()); segment_0 = segment_0.offset(distance); segment_1 = segment_1.offset(distance); let ctrl = match segment_0.intersection_t(&segment_1) { Some(t) => segment_0.sample(t), None => segment_0.to().lerp(segment_1.from(), 0.5), }; - let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to()); - return Segment::quadratic(&baseline, &ctrl); + let baseline = LineSegmentF32::new(segment_0.from(), segment_1.to()); + return Segment::quadratic(&baseline, ctrl); } debug_assert!(self.is_cubic()); if self.baseline.from() == self.ctrl.from() { - let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.to()); - let mut segment_1 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to()); + let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.to()); + let mut segment_1 = LineSegmentF32::new(self.ctrl.to(), self.baseline.to()); segment_0 = segment_0.offset(distance); segment_1 = segment_1.offset(distance); let ctrl = match segment_0.intersection_t(&segment_1) { Some(t) => segment_0.sample(t), None => segment_0.to().lerp(segment_1.from(), 0.5), }; - let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to()); - let ctrl = LineSegmentF32::new(&segment_0.from(), &ctrl); + let baseline = LineSegmentF32::new(segment_0.from(), segment_1.to()); + let ctrl = LineSegmentF32::new(segment_0.from(), ctrl); return Segment::cubic(&baseline, &ctrl); } if self.ctrl.to() == self.baseline.to() { - let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from()); - let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to()); + let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.from()); + let mut segment_1 = LineSegmentF32::new(self.ctrl.from(), self.baseline.to()); segment_0 = segment_0.offset(distance); segment_1 = segment_1.offset(distance); let ctrl = match segment_0.intersection_t(&segment_1) { Some(t) => segment_0.sample(t), None => segment_0.to().lerp(segment_1.from(), 0.5), }; - let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to()); - let ctrl = LineSegmentF32::new(&ctrl, &segment_1.to()); + let baseline = LineSegmentF32::new(segment_0.from(), segment_1.to()); + let ctrl = LineSegmentF32::new(ctrl, segment_1.to()); return Segment::cubic(&baseline, &ctrl); } - let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from()); - let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.ctrl.to()); - let mut segment_2 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to()); + let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.from()); + let mut segment_1 = LineSegmentF32::new(self.ctrl.from(), self.ctrl.to()); + let mut segment_2 = LineSegmentF32::new(self.ctrl.to(), self.baseline.to()); segment_0 = segment_0.offset(distance); segment_1 = segment_1.offset(distance); segment_2 = segment_2.offset(distance); @@ -176,8 +176,8 @@ impl Offset for Segment { segment_1.to().lerp(segment_2.from(), 0.5), ), }; - let baseline = LineSegmentF32::new(&segment_0.from(), &segment_2.to()); - let ctrl = LineSegmentF32::new(&ctrl_0, &ctrl_1); + let baseline = LineSegmentF32::new(segment_0.from(), segment_2.to()); + let ctrl = LineSegmentF32::new(ctrl_0, ctrl_1); Segment::cubic(&baseline, &ctrl) } diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 8695cee3..e0a94b55 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -236,9 +236,9 @@ impl BuiltObject { let right = Point2DF32::new(right, tile_origin_y); let segment = if winding < 0 { - LineSegmentF32::new(&left, &right) + LineSegmentF32::new(left, right) } else { - LineSegmentF32::new(&right, &left) + LineSegmentF32::new(right, left) }; debug!( @@ -300,14 +300,14 @@ impl BuiltObject { let point = Point2DF32::new(x, segment.solve_y_for_x(x)); if !winding { fill_to = point; - segment = LineSegmentF32::new(&point, &segment.to()); + segment = LineSegmentF32::new(point, segment.to()); } else { fill_from = point; - segment = LineSegmentF32::new(&segment.from(), &point); + segment = LineSegmentF32::new(segment.from(), point); } } - let fill_segment = LineSegmentF32::new(&fill_from, &fill_to); + let fill_segment = LineSegmentF32::new(fill_from, fill_to); let fill_tile_coords = Point2DI32::new(subsegment_tile_x, tile_y); self.add_fill(builder, &fill_segment, fill_tile_coords); } diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 2e3549ef..b06af40c 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -129,7 +129,7 @@ impl Scene { }; if options.subpixel_aa_enabled { transform = transform - .post_mul(&Transform2DF32::from_scale(&Point2DF32::new(3.0, 1.0))) + .post_mul(&Transform2DF32::from_scale(Point2DF32::new(3.0, 1.0))) } outline.transform(&transform); } diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 81880898..0dd99eb1 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -434,8 +434,7 @@ impl ActiveEdge { // If necessary, draw initial line. if self.crossing.y() < segment.baseline.min_y() { let first_line_segment = - LineSegmentF32::new(&self.crossing, &segment.baseline.upper_point()) - .orient(winding); + LineSegmentF32::new(self.crossing, segment.baseline.upper_point()).orient(winding); if self .process_line_segment(&first_line_segment, builder, built_object, tile_y) .is_some() diff --git a/text/src/lib.rs b/text/src/lib.rs index f210f4bc..f3dd8f23 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -93,7 +93,7 @@ impl SceneExt for Scene { let scale = style.size / (font.metrics().units_per_em as f32); let scale = Point2DF32::new(scale, -scale); let transform = - Transform2DF32::from_scale(&scale).post_mul(transform).post_translate(offset); + Transform2DF32::from_scale(scale).post_mul(transform).post_translate(offset); self.push_glyph(font, glyph.glyph_id, &transform, @@ -147,7 +147,7 @@ impl OutlinePathBuilder { } fn convert_point(&self, point: Point2D) -> Point2DF32 { - self.transform.transform_point(&Point2DF32::new(point.x, point.y)) + self.transform.transform_point(Point2DF32::new(point.x, point.y)) } } From c09ef3ae7cabbe4816f2074df3f8b9c3a03c0351 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 13 May 2019 18:19:10 -0700 Subject: [PATCH 04/28] Fix SVG and demo compilation errors --- demo/common/src/camera.rs | 2 +- svg/src/lib.rs | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/demo/common/src/camera.rs b/demo/common/src/camera.rs index cbd6559e..2121d8bd 100644 --- a/demo/common/src/camera.rs +++ b/demo/common/src/camera.rs @@ -56,7 +56,7 @@ impl Camera { let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 * scale_factor_for_view_box(view_box); let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5); - Camera::TwoD(Transform2DF32::from_scale(&Point2DF32::splat(scale)).post_translate(origin)) + Camera::TwoD(Transform2DF32::from_scale(Point2DF32::splat(scale)).post_translate(origin)) } fn new_3d(mode: Mode, view_box: RectF32, viewport_size: Point2DI32) -> Camera { diff --git a/svg/src/lib.rs b/svg/src/lib.rs index 90f5a172..249bb8fe 100644 --- a/svg/src/lib.rs +++ b/svg/src/lib.rs @@ -313,8 +313,7 @@ where } UsvgPathSegment::LineTo { x, y } => { let to = Point2DF32::new(x as f32, y as f32); - let mut segment = - Segment::line(&LineSegmentF32::new(&self.last_subpath_point, &to)); + let mut segment = Segment::line(&LineSegmentF32::new(self.last_subpath_point, to)); if self.just_moved { segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH); } @@ -334,8 +333,8 @@ where let ctrl1 = Point2DF32::new(x2 as f32, y2 as f32); let to = Point2DF32::new(x as f32, y as f32); let mut segment = Segment::cubic( - &LineSegmentF32::new(&self.last_subpath_point, &to), - &LineSegmentF32::new(&ctrl0, &ctrl1), + &LineSegmentF32::new(self.last_subpath_point, to), + &LineSegmentF32::new(ctrl0, ctrl1), ); if self.just_moved { segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH); @@ -346,8 +345,8 @@ where } UsvgPathSegment::ClosePath => { let mut segment = Segment::line(&LineSegmentF32::new( - &self.last_subpath_point, - &self.first_subpath_point, + self.last_subpath_point, + self.first_subpath_point, )); segment.flags.insert(SegmentFlags::CLOSES_SUBPATH); self.just_moved = false; From d5a12e0e9fbb416a3279454912c868a09f29c121 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 13 May 2019 18:20:21 -0700 Subject: [PATCH 05/28] Revert "batch alpha and solid tiles" This reverts commit 753a25472672c6affe3b5f7951155dc47e5cccbb. --- renderer/src/builder.rs | 6 +- renderer/src/gpu/renderer.rs | 222 ++++++++--------------------------- renderer/src/gpu_data.rs | 16 +-- 3 files changed, 56 insertions(+), 188 deletions(-) diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index e0a94b55..86818da6 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -110,10 +110,10 @@ impl<'a> SceneBuilder<'a> { let path_count = self.scene.paths.len() as u32; let solid_tiles = self.z_buffer.build_solid_tiles(0..path_count); if !solid_tiles.is_empty() { - self.listener.send(RenderCommand::AddSolidTiles(solid_tiles)); + self.listener.send(RenderCommand::SolidTile(solid_tiles)); } if !alpha_tiles.is_empty() { - self.listener.send(RenderCommand::AddAlphaTiles(alpha_tiles)); + self.listener.send(RenderCommand::AlphaTile(alpha_tiles)); } } @@ -121,8 +121,6 @@ impl<'a> SceneBuilder<'a> { self.listener.send(RenderCommand::FlushFills); self.cull_alpha_tiles(&mut alpha_tiles); self.pack_alpha_tiles(alpha_tiles); - self.listener.send(RenderCommand::FlushSolidTiles); - self.listener.send(RenderCommand::FlushAlphaTiles); } } diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 02c5b815..b355215d 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -45,8 +45,6 @@ const FILL_COLORS_TEXTURE_WIDTH: i32 = 256; const FILL_COLORS_TEXTURE_HEIGHT: i32 = 256; const MAX_FILLS_PER_BATCH: usize = 0x4000; -const MAX_ALPHA_TILES_PER_BATCH: usize = 0x4000; -const MAX_SOLID_TILES_PER_BATCH: usize = 0x4000; pub struct Renderer where @@ -89,8 +87,6 @@ where // Rendering state mask_framebuffer_cleared: bool, buffered_fills: Vec, - buffered_alpha_tiles: Vec, - buffered_solid_tiles: Vec, // Debug pub stats: RenderStats, @@ -220,8 +216,6 @@ where mask_framebuffer_cleared: false, buffered_fills: vec![], - buffered_alpha_tiles: vec![], - buffered_solid_tiles: vec![], render_mode: RenderMode::default(), use_depth: false, @@ -242,10 +236,7 @@ where pub fn render_command(&mut self, command: &RenderCommand) { match *command { - RenderCommand::Start { - bounding_quad, - path_count, - } => { + RenderCommand::Start { bounding_quad, path_count } => { if self.use_depth { self.draw_stencil(&bounding_quad); } @@ -257,15 +248,17 @@ where self.begin_composite_timer_query(); self.draw_buffered_fills(); } - RenderCommand::AddSolidTiles(ref solid_tiles) => self.add_solid_tiles(solid_tiles), - RenderCommand::FlushSolidTiles => { - self.begin_composite_timer_query(); - self.draw_buffered_solid_tiles(); + RenderCommand::SolidTile(ref solid_tiles) => { + let count = solid_tiles.len(); + self.stats.solid_tile_count += count; + self.upload_solid_tiles(solid_tiles); + self.draw_solid_tiles(count as u32); } - RenderCommand::AddAlphaTiles(ref alpha_tiles) => self.add_alpha_tiles(alpha_tiles), - RenderCommand::FlushAlphaTiles => { - self.begin_composite_timer_query(); - self.draw_buffered_alpha_tiles(); + RenderCommand::AlphaTile(ref alpha_tiles) => { + let count = alpha_tiles.len(); + self.stats.alpha_tile_count += count; + self.upload_alpha_tiles(alpha_tiles); + self.draw_alpha_tiles(count as u32); } RenderCommand::Finish { .. } => {} } @@ -277,8 +270,7 @@ where } self.end_composite_timer_query(); - self.pending_timers - .push_back(mem::replace(&mut self.current_timers, RenderTimers::new())); + self.pending_timers.push_back(mem::replace(&mut self.current_timers, RenderTimers::new())); } pub fn draw_debug_ui(&self) { @@ -312,10 +304,7 @@ where self.free_timer_queries.extend(timers.stage_0.into_iter()); self.free_timer_queries.push(timers.stage_1.unwrap()); - Some(RenderTime { - stage_0: total_stage_0_time, - stage_1: stage_1_time, - }) + Some(RenderTime { stage_0: total_stage_0_time, stage_1: stage_1_time }) } #[inline] @@ -333,9 +322,7 @@ where #[inline] pub fn set_main_framebuffer_size(&mut self, new_framebuffer_size: Point2DI32) { - self.debug_ui_presenter - .ui_presenter - .set_framebuffer_size(new_framebuffer_size); + self.debug_ui_presenter.ui_presenter.set_framebuffer_size(new_framebuffer_size); } #[inline] @@ -371,6 +358,24 @@ where .upload_to_texture(&self.fill_colors_texture, size, &fill_colors); } + fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileBatchPrimitive]) { + self.device.allocate_buffer( + &self.solid_tile_vertex_array().vertex_buffer, + BufferData::Memory(&solid_tiles), + BufferTarget::Vertex, + BufferUploadMode::Dynamic, + ); + } + + fn upload_alpha_tiles(&mut self, alpha_tiles: &[AlphaTileBatchPrimitive]) { + self.device.allocate_buffer( + &self.alpha_tile_vertex_array().vertex_buffer, + BufferData::Memory(&alpha_tiles), + BufferTarget::Vertex, + BufferUploadMode::Dynamic, + ); + } + fn clear_mask_framebuffer(&mut self) { self.device.bind_framebuffer(&self.mask_framebuffer); @@ -404,60 +409,6 @@ where self.current_timers.stage_0.push(timer_query); } - fn add_solid_tiles(&mut self, mut solid_tiles: &[SolidTileBatchPrimitive]) { - if solid_tiles.is_empty() { - return; - } - - let timer_query = self.allocate_timer_query(); - self.device.begin_timer_query(&timer_query); - - self.stats.solid_tile_count += solid_tiles.len(); - - while !solid_tiles.is_empty() { - let count = cmp::min( - solid_tiles.len(), - MAX_SOLID_TILES_PER_BATCH - self.buffered_solid_tiles.len(), - ); - self.buffered_solid_tiles - .extend_from_slice(&solid_tiles[0..count]); - solid_tiles = &solid_tiles[count..]; - if self.buffered_solid_tiles.len() == MAX_SOLID_TILES_PER_BATCH { - self.draw_buffered_solid_tiles(); - } - } - - self.device.end_timer_query(&timer_query); - self.current_timers.stage_0.push(timer_query); - } - - fn add_alpha_tiles(&mut self, mut alpha_tiles: &[AlphaTileBatchPrimitive]) { - if alpha_tiles.is_empty() { - return; - } - - let timer_query = self.allocate_timer_query(); - self.device.begin_timer_query(&timer_query); - - self.stats.alpha_tile_count += alpha_tiles.len(); - - while !alpha_tiles.is_empty() { - let count = cmp::min( - alpha_tiles.len(), - MAX_ALPHA_TILES_PER_BATCH - self.buffered_alpha_tiles.len(), - ); - self.buffered_alpha_tiles - .extend_from_slice(&alpha_tiles[0..count]); - alpha_tiles = &alpha_tiles[count..]; - if self.buffered_alpha_tiles.len() == MAX_ALPHA_TILES_PER_BATCH { - self.draw_buffered_alpha_tiles(); - } - } - - self.device.end_timer_query(&timer_query); - self.current_timers.stage_0.push(timer_query); - } - fn draw_buffered_fills(&mut self) { if self.buffered_fills.is_empty() { return; @@ -510,24 +461,12 @@ where self.buffered_fills.clear() } - fn draw_buffered_alpha_tiles(&mut self) { - if self.buffered_alpha_tiles.is_empty() { - return; - } + fn draw_alpha_tiles(&mut self, count: u32) { + self.bind_draw_framebuffer(); let alpha_tile_vertex_array = self.alpha_tile_vertex_array(); - - self.device.allocate_buffer( - &alpha_tile_vertex_array.vertex_buffer, - BufferData::Memory(&self.buffered_alpha_tiles), - BufferTarget::Vertex, - BufferUploadMode::Dynamic, - ); - let alpha_tile_program = self.alpha_tile_program(); - self.bind_draw_framebuffer(); - self.device .bind_vertex_array(&alpha_tile_vertex_array.vertex_array); self.device.use_program(&alpha_tile_program.program); @@ -595,35 +534,16 @@ where stencil: self.stencil_state(), ..RenderState::default() }; - debug_assert!(self.buffered_alpha_tiles.len() <= u32::MAX as usize); - self.device.draw_arrays_instanced( - Primitive::TriangleFan, - 4, - self.buffered_alpha_tiles.len() as u32, - &render_state, - ); - - self.buffered_alpha_tiles.clear(); + self.device + .draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state); } - fn draw_buffered_solid_tiles(&mut self) { - if self.buffered_solid_tiles.is_empty() { - return; - } + fn draw_solid_tiles(&mut self, count: u32) { + self.bind_draw_framebuffer(); let solid_tile_vertex_array = self.solid_tile_vertex_array(); - - self.device.allocate_buffer( - &solid_tile_vertex_array.vertex_buffer, - BufferData::Memory(&self.buffered_solid_tiles), - BufferTarget::Vertex, - BufferUploadMode::Dynamic, - ); - let solid_tile_program = self.solid_tile_program(); - self.bind_draw_framebuffer(); - self.device .bind_vertex_array(&solid_tile_vertex_array.vertex_array); self.device.use_program(&solid_tile_program.program); @@ -678,15 +598,8 @@ where stencil: self.stencil_state(), ..RenderState::default() }; - debug_assert!(self.buffered_solid_tiles.len() <= u32::MAX as usize); - self.device.draw_arrays_instanced( - Primitive::TriangleFan, - 4, - self.buffered_solid_tiles.len() as u32, - &render_state, - ); - - self.buffered_solid_tiles.clear(); + self.device + .draw_arrays_instanced(Primitive::TriangleFan, 4, count, &render_state); } fn postprocess(&mut self) { @@ -975,11 +888,7 @@ where } fn end_composite_timer_query(&mut self) { - let query = self - .current_timers - .stage_1 - .as_ref() - .expect("No stage 1 timer query yet?!"); + let query = self.current_timers.stage_1.as_ref().expect("No stage 1 timer query yet?!"); self.device.end_timer_query(&query); } } @@ -1092,17 +1001,7 @@ where alpha_tile_program: &AlphaTileProgram, quad_vertex_positions_buffer: &D::Buffer, ) -> AlphaTileVertexArray { - let vertex_array = device.create_vertex_array(); - - let vertex_buffer = device.create_buffer(); - let vertex_buffer_data: BufferData = - BufferData::Uninitialized(MAX_ALPHA_TILES_PER_BATCH); - device.allocate_buffer( - &vertex_buffer, - vertex_buffer_data, - BufferTarget::Vertex, - BufferUploadMode::Dynamic, - ); + let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); let tess_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "TessCoord"); let tile_origin_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileOrigin"); @@ -1174,17 +1073,7 @@ where solid_tile_program: &SolidTileProgram, quad_vertex_positions_buffer: &D::Buffer, ) -> SolidTileVertexArray { - let vertex_array = device.create_vertex_array(); - - let vertex_buffer = device.create_buffer(); - let vertex_buffer_data: BufferData = - BufferData::Uninitialized(MAX_SOLID_TILES_PER_BATCH); - device.allocate_buffer( - &vertex_buffer, - vertex_buffer_data, - BufferTarget::Vertex, - BufferUploadMode::Dynamic, - ); + let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord"); let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin"); @@ -1623,10 +1512,7 @@ where #[inline] pub fn full_window(window_size: Point2DI32) -> DestFramebuffer { let viewport = RectI32::new(Point2DI32::default(), window_size); - DestFramebuffer::Default { - viewport, - window_size, - } + DestFramebuffer::Default { viewport, window_size } } fn window_size(&self, device: &D) -> Point2DI32 { @@ -1689,23 +1575,14 @@ impl Div for RenderStats { } } -struct RenderTimers -where - D: Device, -{ +struct RenderTimers where D: Device { stage_0: Vec, stage_1: Option, } -impl RenderTimers -where - D: Device, -{ +impl RenderTimers where D: Device { fn new() -> RenderTimers { - RenderTimers { - stage_0: vec![], - stage_1: None, - } + RenderTimers { stage_0: vec![], stage_1: None } } } @@ -1718,10 +1595,7 @@ pub struct RenderTime { impl Default for RenderTime { #[inline] fn default() -> RenderTime { - RenderTime { - stage_0: Duration::new(0, 0), - stage_1: Duration::new(0, 0), - } + RenderTime { stage_0: Duration::new(0, 0), stage_1: Duration::new(0, 0) } } } diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 8a998981..c130abd6 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -31,10 +31,8 @@ pub enum RenderCommand { AddShaders(Vec), AddFills(Vec), FlushFills, - AddAlphaTiles(Vec), - FlushAlphaTiles, - AddSolidTiles(Vec), - FlushSolidTiles, + AlphaTile(Vec), + SolidTile(Vec), Finish { build_time: Duration }, } @@ -91,14 +89,12 @@ impl Debug for RenderCommand { } RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()), RenderCommand::FlushFills => write!(formatter, "FlushFills"), - RenderCommand::AddAlphaTiles(ref tiles) => { - write!(formatter, "AddAlphaTiles(x{})", tiles.len()) + RenderCommand::AlphaTile(ref tiles) => { + write!(formatter, "AlphaTile(x{})", tiles.len()) } - RenderCommand::FlushAlphaTiles => write!(formatter, "FlushAlphaTiles"), - RenderCommand::AddSolidTiles(ref tiles) => { - write!(formatter, "AddSolidTiles(x{})", tiles.len()) + RenderCommand::SolidTile(ref tiles) => { + write!(formatter, "SolidTile(x{})", tiles.len()) } - RenderCommand::FlushSolidTiles => write!(formatter, "FlushSolidTiles"), RenderCommand::Finish { .. } => write!(formatter, "Finish"), } } From 89ca998fa8cd71ff068cb852568fcfd38c3b05d7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 13 May 2019 18:29:33 -0700 Subject: [PATCH 06/28] Add a convenience method for creating a scene proxy with an empty scene. This makes animation rendering loops a bit easier for users. --- Cargo.lock | 1 - demo/common/src/lib.rs | 2 +- examples/canvas_minimal/src/main.rs | 2 +- examples/canvas_moire/Cargo.toml | 1 - examples/canvas_moire/src/main.rs | 19 +++++-------------- examples/canvas_text/src/main.rs | 2 +- geometry/src/outline.rs | 14 ++++++-------- renderer/src/concurrent/scene_proxy.rs | 7 ++++++- 8 files changed, 20 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbc2bb2f..da630ac5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,7 +180,6 @@ dependencies = [ "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", - "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/demo/common/src/lib.rs b/demo/common/src/lib.rs index 22134b0c..147eef59 100644 --- a/demo/common/src/lib.rs +++ b/demo/common/src/lib.rs @@ -143,7 +143,7 @@ impl DemoApp where W: Window { viewport.size()); let camera = Camera::new(options.mode, scene_metadata.view_box, viewport.size()); - let scene_proxy = SceneProxy::new(built_svg.scene, executor); + let scene_proxy = SceneProxy::from_scene(built_svg.scene, executor); let ground_program = GroundProgram::new(&renderer.device, resources); let ground_vertex_array = GroundVertexArray::new(&renderer.device, diff --git a/examples/canvas_minimal/src/main.rs b/examples/canvas_minimal/src/main.rs index 449fdd54..815ca75f 100644 --- a/examples/canvas_minimal/src/main.rs +++ b/examples/canvas_minimal/src/main.rs @@ -74,7 +74,7 @@ fn main() { canvas.stroke_path(path); // Render the canvas to screen. - let scene = SceneProxy::new(canvas.into_scene(), RayonExecutor); + let scene = SceneProxy::from_scene(canvas.into_scene(), RayonExecutor); scene.build_and_render(&mut renderer, RenderOptions::default()); window.gl_swap_window(); diff --git a/examples/canvas_moire/Cargo.toml b/examples/canvas_moire/Cargo.toml index c8b9b4b7..0bab187d 100644 --- a/examples/canvas_moire/Cargo.toml +++ b/examples/canvas_moire/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" [dependencies] gl = "0.6" -pretty_env_logger = "0.3" sdl2 = "0.32" sdl2-sys = "0.32" diff --git a/examples/canvas_moire/src/main.rs b/examples/canvas_moire/src/main.rs index cf58250a..f5f2c0d5 100644 --- a/examples/canvas_moire/src/main.rs +++ b/examples/canvas_moire/src/main.rs @@ -37,8 +37,6 @@ const CIRCLE_THICKNESS: f32 = 16.0; const COLOR_CYCLE_SPEED: f32 = 0.0025; fn main() { - pretty_env_logger::init(); - // Set up SDL2. let sdl_context = sdl2::init().unwrap(); let video = sdl_context.video().unwrap(); @@ -87,7 +85,7 @@ fn main() { struct MoireRenderer { renderer: Renderer, - scene: Option, + scene: SceneProxy, frame: i32, window_size: Point2DI32, drawable_size: Point2DI32, @@ -100,7 +98,7 @@ impl MoireRenderer { -> MoireRenderer { MoireRenderer { renderer, - scene: None, + scene: SceneProxy::new(RayonExecutor), frame: 0, window_size, drawable_size, @@ -138,16 +136,9 @@ impl MoireRenderer { self.draw_circles(&mut canvas, outer_center); self.draw_circles(&mut canvas, inner_center); - // Build scene if necessary. - // TODO(pcwalton): Allow the user to build an empty scene proxy so they don't have to do this. - match self.scene { - None => self.scene = Some(SceneProxy::new(canvas.into_scene(), RayonExecutor)), - Some(ref mut scene) => scene.replace_scene(canvas.into_scene()), - } - - // Render the scene. - self.scene.as_mut().unwrap().build_and_render(&mut self.renderer, - RenderOptions::default()); + // Build and render scene. + self.scene.replace_scene(canvas.into_scene()); + self.scene.build_and_render(&mut self.renderer, RenderOptions::default()); self.frame += 1; } diff --git a/examples/canvas_text/src/main.rs b/examples/canvas_text/src/main.rs index db0a455e..7490b499 100644 --- a/examples/canvas_text/src/main.rs +++ b/examples/canvas_text/src/main.rs @@ -62,7 +62,7 @@ fn main() { canvas.stroke_text("Goodbye Pathfinder!", Point2DF32::new(32.0, 96.0)); // Render the canvas to screen. - let scene = SceneProxy::new(canvas.into_scene(), RayonExecutor); + let scene = SceneProxy::from_scene(canvas.into_scene(), RayonExecutor); scene.build_and_render(&mut renderer, RenderOptions::default()); window.gl_swap_window(); diff --git a/geometry/src/outline.rs b/geometry/src/outline.rs index 7b5e3699..71fa6856 100644 --- a/geometry/src/outline.rs +++ b/geometry/src/outline.rs @@ -369,14 +369,12 @@ impl Contour { let rotation = Transform2DF32::from_rotation(angle); segment = segment.transform(&scale.post_mul(&rotation).post_mul(&translation)); - /* - println!("angle={} start_angle={} end_angle={} sweep_angle={} segment={:?}", - angle, - start_angle, - end_angle, - sweep_angle, - segment); - */ + debug!("angle={} start_angle={} end_angle={} sweep_angle={} segment={:?}", + angle, + start_angle, + end_angle, + sweep_angle, + segment); if first_segment { self.push_full_segment(&segment, true); diff --git a/renderer/src/concurrent/scene_proxy.rs b/renderer/src/concurrent/scene_proxy.rs index 52534cae..cefb7dcc 100644 --- a/renderer/src/concurrent/scene_proxy.rs +++ b/renderer/src/concurrent/scene_proxy.rs @@ -36,7 +36,12 @@ pub struct SceneProxy { } impl SceneProxy { - pub fn new(scene: Scene, executor: E) -> SceneProxy where E: Executor + Send + 'static { + pub fn new(executor: E) -> SceneProxy where E: Executor + Send + 'static { + SceneProxy::from_scene(Scene::new(), executor) + } + + pub fn from_scene(scene: Scene, executor: E) -> SceneProxy + where E: Executor + Send + 'static { let (main_to_worker_sender, main_to_worker_receiver) = mpsc::channel(); thread::spawn(move || scene_thread(scene, executor, main_to_worker_receiver)); SceneProxy { sender: main_to_worker_sender } From c7382a8b2c146609c94e0bc9732925b36be8ebeb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 13 May 2019 18:40:25 -0700 Subject: [PATCH 07/28] Add affine transform support to the canvas implementation --- canvas/src/lib.rs | 36 ++++++++++++++++++++++++++++++++---- geometry/src/outline.rs | 8 ++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 63d68222..300e6049 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -94,10 +94,12 @@ impl CanvasRenderingContext2D { pub fn fill_text(&mut self, string: &str, position: Point2DF32) { // TODO(pcwalton): Report errors. let paint_id = self.scene.push_paint(&self.current_state.fill_paint); + let transform = Transform2DF32::from_translation(position).post_mul(&self.current_state + .transform); drop(self.scene.push_text(string, &TextStyle { size: self.current_state.font_size }, &self.current_state.font_collection, - &Transform2DF32::from_translation(position), + &transform, TextRenderMode::Fill, HintingOptions::None, paint_id)); @@ -106,10 +108,12 @@ impl CanvasRenderingContext2D { pub fn stroke_text(&mut self, string: &str, position: Point2DF32) { // TODO(pcwalton): Report errors. let paint_id = self.scene.push_paint(&self.current_state.stroke_paint); + let transform = Transform2DF32::from_translation(position).post_mul(&self.current_state + .transform); drop(self.scene.push_text(string, &TextStyle { size: self.current_state.font_size }, &self.current_state.font_collection, - &Transform2DF32::from_translation(position), + &transform, TextRenderMode::Stroke(self.current_state.line_width), HintingOptions::None, paint_id)); @@ -139,12 +143,14 @@ impl CanvasRenderingContext2D { self.current_state.font_size = new_font_size; } - // Paths + // Drawing paths #[inline] pub fn fill_path(&mut self, path: Path2D) { + let mut outline = path.into_outline(); + outline.transform(&self.current_state.transform); let paint_id = self.scene.push_paint(&self.current_state.fill_paint); - self.scene.push_path(PathObject::new(path.into_outline(), paint_id, String::new())) + self.scene.push_path(PathObject::new(outline, paint_id, String::new())) } #[inline] @@ -153,9 +159,29 @@ impl CanvasRenderingContext2D { let stroke_width = f32::max(self.current_state.line_width, HAIRLINE_STROKE_WIDTH); let mut stroke_to_fill = OutlineStrokeToFill::new(path.into_outline(), stroke_width); stroke_to_fill.offset(); + stroke_to_fill.outline.transform(&self.current_state.transform); self.scene.push_path(PathObject::new(stroke_to_fill.outline, paint_id, String::new())) } + // Transformations + + #[inline] + pub fn current_transform(&self) -> Transform2DF32 { + self.current_state.transform + } + + #[inline] + pub fn set_current_transform(&mut self, new_transform: &Transform2DF32) { + self.current_state.transform = *new_transform; + } + + #[inline] + pub fn reset_transform(&mut self) { + self.current_state.transform = Transform2DF32::default(); + } + + // The canvas state + #[inline] pub fn save(&mut self) { self.saved_states.push(self.current_state.clone()); @@ -171,6 +197,7 @@ impl CanvasRenderingContext2D { #[derive(Clone)] pub struct State { + transform: Transform2DF32, font_collection: Arc, font_size: f32, fill_paint: Paint, @@ -181,6 +208,7 @@ pub struct State { impl State { fn default(default_font_collection: Arc) -> State { State { + transform: Transform2DF32::default(), font_collection: default_font_collection, font_size: DEFAULT_FONT_SIZE, fill_paint: Paint { color: ColorU::black() }, diff --git a/geometry/src/outline.rs b/geometry/src/outline.rs index 71fa6856..241fd3d5 100644 --- a/geometry/src/outline.rs +++ b/geometry/src/outline.rs @@ -127,6 +127,10 @@ impl Outline { } pub fn transform(&mut self, transform: &Transform2DF32) { + if transform.is_identity() { + return; + } + let mut new_bounds = None; for contour in &mut self.contours { contour.transform(transform); @@ -487,6 +491,10 @@ impl Contour { } pub fn transform(&mut self, transform: &Transform2DF32) { + if transform.is_identity() { + return; + } + for (point_index, point) in self.points.iter_mut().enumerate() { *point = transform.transform_point(*point); union_rect(&mut self.bounds, *point, point_index == 0); From 7518fa65c0fb4ca519540514accf70a502161547 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 13 May 2019 18:47:19 -0700 Subject: [PATCH 08/28] Update dependencies --- Cargo.lock | 503 ++++++++++++++++--------------- canvas/Cargo.toml | 2 +- examples/canvas_text/src/main.rs | 3 +- text/Cargo.toml | 2 +- 4 files changed, 259 insertions(+), 251 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da630ac5..04c6960e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,7 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.6.10" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -28,7 +28,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rusttype 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rusttype 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -44,7 +44,7 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -59,8 +59,8 @@ dependencies = [ name = "area-lut" version = "0.2.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -91,9 +91,9 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -103,15 +103,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -119,8 +119,8 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -166,8 +166,8 @@ dependencies = [ "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", - "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -180,8 +180,8 @@ dependencies = [ "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", - "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -194,13 +194,13 @@ dependencies = [ "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", - "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.29" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -210,7 +210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -218,8 +218,8 @@ name = "cgl" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -234,14 +234,14 @@ dependencies = [ [[package]] name = "clap" -version = "2.32.0" +version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -256,10 +256,10 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.35" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -272,7 +272,7 @@ dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -281,7 +281,7 @@ name = "color-backtrace" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -292,12 +292,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "combine" -version = "3.6.7" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -313,7 +313,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -329,7 +329,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -340,15 +340,15 @@ dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crc32fast" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -375,7 +375,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -388,7 +388,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -396,7 +396,7 @@ name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -423,8 +423,8 @@ dependencies = [ "pathfinder_gpu 0.1.0", "pathfinder_simd 0.3.0", "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -432,9 +432,9 @@ name = "dirs" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -456,10 +456,10 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -468,12 +468,12 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "khronos 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "either" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -484,7 +484,7 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -496,21 +496,22 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "error-chain" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "euclid" -version = "0.19.5" +version = "0.19.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -522,9 +523,9 @@ name = "euclid_macros" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -532,7 +533,7 @@ name = "expat-sys" version = "2.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -541,7 +542,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -550,9 +551,9 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -588,19 +589,19 @@ dependencies = [ "core-text 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -621,7 +622,7 @@ name = "freetype" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -644,7 +645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "generate-gamma-lut" version = "0.1.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -698,7 +699,7 @@ dependencies = [ [[package]] name = "gleam" -version = "0.6.16" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -716,12 +717,12 @@ dependencies = [ "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -739,7 +740,7 @@ name = "harfbuzz-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -754,7 +755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -774,7 +775,7 @@ dependencies = [ "gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -784,7 +785,7 @@ dependencies = [ [[package]] name = "image" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -792,8 +793,7 @@ dependencies = [ "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "png 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -809,12 +809,12 @@ name = "itertools" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -822,9 +822,9 @@ name = "jemalloc-sys" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -833,7 +833,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -842,8 +842,8 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "combine 3.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -902,17 +902,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" +version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libflate" -version = "0.1.20" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -920,8 +920,8 @@ name = "libloading" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -954,16 +954,16 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lyon_geom" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -972,7 +972,7 @@ name = "lyon_path" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lyon_geom 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lyon_geom 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -985,7 +985,7 @@ name = "malloc_buf" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -993,7 +993,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1006,8 +1006,8 @@ name = "memmap" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1015,8 +1015,8 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1038,9 +1038,9 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1061,12 +1061,12 @@ dependencies = [ [[package]] name = "num-derive" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1114,9 +1114,14 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "objc" version = "0.2.6" @@ -1163,11 +1168,11 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1192,16 +1197,16 @@ dependencies = [ "pathfinder_geometry 0.3.0", "pathfinder_renderer 0.1.0", "pathfinder_text 0.1.0", - "skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e)", + "skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=a89e9ca99e0d6736ea1b7754517f4df14fd96a2b)", ] [[package]] name = "pathfinder_demo" version = "0.1.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", @@ -1222,8 +1227,8 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_simd 0.3.0", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1232,7 +1237,7 @@ name = "pathfinder_gl" version = "0.1.0" dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_gpu 0.1.0", @@ -1245,7 +1250,7 @@ dependencies = [ name = "pathfinder_gpu" version = "0.1.0" dependencies = [ - "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_simd 0.3.0", "rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1287,8 +1292,8 @@ dependencies = [ "pathfinder_ui 0.1.0", "quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1313,12 +1318,12 @@ dependencies = [ name = "pathfinder_text" version = "0.1.0" dependencies = [ - "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_renderer 0.1.0", - "skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e)", + "skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=a89e9ca99e0d6736ea1b7754517f4df14fd96a2b)", ] [[package]] @@ -1329,9 +1334,9 @@ dependencies = [ "pathfinder_geometry 0.3.0", "pathfinder_gpu 0.1.0", "pathfinder_simd 0.3.0", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1373,7 +1378,7 @@ dependencies = [ [[package]] name = "png" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1394,7 +1399,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.27" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1418,10 +1423,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1431,9 +1436,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1442,16 +1447,16 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1502,12 +1507,12 @@ dependencies = [ [[package]] name = "rand_jitter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1517,10 +1522,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1546,7 +1551,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1557,13 +1562,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rctree" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1576,7 +1581,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.51" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1584,7 +1589,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1595,7 +1600,7 @@ dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1612,12 +1617,12 @@ dependencies = [ [[package]] name = "regex" -version = "1.1.0" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1629,7 +1634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex-syntax" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1654,7 +1659,7 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1672,7 +1677,7 @@ dependencies = [ [[package]] name = "rusttype" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1683,12 +1688,7 @@ dependencies = [ [[package]] name = "ryu" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "safe-transmute" -version = "0.10.1" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1716,23 +1716,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "sdl2" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sdl2-sys" -version = "0.32.5" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1750,27 +1751,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.88" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.88" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1778,7 +1779,7 @@ name = "servo-fontconfig" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "servo-fontconfig-sys 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1797,7 +1798,7 @@ name = "servo-freetype-sys" version = "4.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1807,7 +1808,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1823,12 +1824,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "skribo" version = "0.0.1" -source = "git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e#f759c2d2c188b668bce998179f03b6319835353e" +source = "git+https://github.com/linebender/skribo.git?rev=a89e9ca99e0d6736ea1b7754517f4df14fd96a2b#a89e9ca99e0d6736ea1b7754517f4df14fd96a2b" dependencies = [ - "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "harfbuzz-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1873,7 +1875,7 @@ dependencies = [ [[package]] name = "strsim" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1906,11 +1908,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.26" +version = "0.15.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1919,9 +1921,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1932,7 +1934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1945,17 +1947,18 @@ dependencies = [ [[package]] name = "termion" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "textwrap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1967,7 +1970,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1991,9 +1994,9 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2038,10 +2041,10 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lyon_geom 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rctree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lyon_geom 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rctree 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "svgdom 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2061,6 +2064,11 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -2072,7 +2080,7 @@ version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2083,7 +2091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-commons 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-scanner 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2116,8 +2124,8 @@ name = "wayland-scanner" version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2137,7 +2145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2159,7 +2167,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2172,7 +2180,7 @@ name = "wincolor" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2182,19 +2190,19 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "smithay-client-toolkit 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2204,7 +2212,7 @@ version = "2.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2234,7 +2242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" -"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" "checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e" "checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" @@ -2244,31 +2252,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5fc969a8ce2c9c0c4b0429bb8431544f6658283c8326ba5ff8c762b75369335" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" +"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" "checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" +"checksum cmake 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "d9fc5523427cb1451da064f7db483d18bf8957e471baabf140ff683c37a86536" "checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b" "checksum color-backtrace 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "90242aff9b6439332beb77ee416126367adcd6376b0dc80b39250e7debdd913d" "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" -"checksum combine 3.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d2623b3542b48f4427e15ddd4995186decb594ebbd70271463886584b4a114b9" +"checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9" "checksum core-text 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d95a72b5e50e549969dd88eff3047495fe5b8c6f028635442c2b708be707e669" -"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" @@ -2280,11 +2288,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b92dfd5c2f75260cbf750572f95d387e7ca0ba5e3fbe9e1a33f23025be020f" "checksum dwrote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30a998e9ff70cd208ccdc4f864e998688bf61d7b897dccec8e17a884d17358bf" "checksum egl 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a373bc9844200b1ff15bd1b245931d1c20d09d06e4ec09f361171f29a4b0752d" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" -"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a7698bdda3d7444a79d33bdc96e8b518d44ea3ff101d8492a6ca1207b886ea" +"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" +"checksum euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7a4719a544a67ed3fc33784c2bd2c6581663dfe83b719a6ae05c6dabc3b51c73" "checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15" "checksum expat-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -2304,17 +2312,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604" "checksum gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39a23d5e872a275135d66895d954269cf5e8661d234eb1c2480f4ce0d586acbd" "checksum gl_generator 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "75d69f914b49d9ff32fdf394cbd798f8c716d74fd19f9cc29da3e99797b2a78d" -"checksum gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5" +"checksum gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7f46fd8874e043ffac0d638ed1567a2584f7814f6d72b4db37ab1689004a26c4" "checksum glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "535c6eda58adbb227604b2db10a022ffd6339d7ea3e970f338e7d98aeb24fcc3" "checksum harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46f7426266a5ece3e49eae6f48e602c0f8c39917354a847eac9c06437dcde8da" "checksum harfbuzz-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e1042ab0b3e7bc1ff64f7f5935778b644ff2194a1cae5ec52167127d3fd23961" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a" -"checksum image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "52fb0666a1273dac46f9725aa4859bcd5595fc3554cf3495051b4de8db745e7d" +"checksum image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "293e54ce142a936a39da748ba8178ae6aa1914b82d846a4278f11590c89bf116" "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0cd42ac65f758063fea55126b0148b1ce0a6354ff78e07a4d6806bc65c4ab3" "checksum jni 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "294eca097d1dc0bf59de5ab9f7eafa5f77129e9f6464c957ed3ddeb705fb4292" @@ -2326,14 +2334,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" -"checksum libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "54d1ddf9c52870243c5689d7638d888331c1116aa5b398f3ba1acfa7d8758ca1" +"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" +"checksum libflate 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c52384aeb22d0ce82a10d8ddf35f7fb4717d1b23eac5b94cd38d2050fb53766a" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum lyon_geom 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2b60eaa9061c87affcd671e88289ce6971324269ec6548b677e02624ef3ef63c" +"checksum lyon_geom 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0ea0ba5f8d2d91d6d895aca54d1ec0d84ddfa4826f33fbfe8abb39f08f9e4153" "checksum lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9dc8e0746b7cca11960b602f7fe037bb067746a01eab4aa502fed1494544843" "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" @@ -2346,13 +2354,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" -"checksum num-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d9fe8fcafd1b86a37ce8a1cfa15ae504817e0c8c2e7ad42767371461ac1d316d" +"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" "checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d" "checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" @@ -2364,12 +2373,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b" -"checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9" +"checksum png 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63daf481fdd0defa2d1d2be15c674fbfa1b0fd71882c303a91f9a79b3252c359" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" -"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4537d3e4edf73a15dd059b75bed1c292d17d3ea7517f583cebe716794fcf816" -"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -2378,61 +2387,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" -"checksum rctree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1817e0f0056f95bce0d6ab1a5be62ca24bd756b5547c20637ef47cc9a2065f4b" +"checksum rctree 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da0b3901505c2faa2390e27188078852eb3ed0dd9176e2153f403cdcdd18e0e7" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum roxmltree 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02660467d0c2da1b6276042501aee6e15ec5b8ff59423243f185b294cd53acf3" "checksum rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86de9443c1a5618e0d51bbd8eb6227ead9916446eb8952575a70d1ef7e00209" -"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rusttype 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3926a2057b315b3e8bca6d1cec1e97f19436a8f9127621cd538cda9c96a38b" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e" +"checksum rusttype 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "25951e85bb2647960969f72c559392245a5bd07446a589390bf427dda31cdc4a" +"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebf85f207d42e4da59fa31fff977be5ff0b224873506c4bd70cc1c94b331593" -"checksum sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e82803e85c2e6178d28886cef25b2c53afc2eecaeff739f2247f23ed3352e6c1" +"checksum sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d051a07231e303f5f719da78cb6f7394f6d5b54f733aef5b0b447804a83edd7b" +"checksum sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)" = "34e71125077d297d57e4c1acfe8981b5bdfbf5a20e7b589abfdcb33bf1127f86" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" -"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4" -"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" +"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" +"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9" "checksum servo-fontconfig-sys 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b46d201addcfbd25c1798ad1281d98c40743824e0b0f1e611bd3d5d0d31a7b8d" "checksum servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4ccb6d0d32d277d3ef7dea86203d8210945eb7a45fba89dd445b3595dd0dfc" "checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" "checksum simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "135685097a85a64067df36e28a243e94a94f76d829087ce0be34eeb014260c0e" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e)" = "" +"checksum skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=a89e9ca99e0d6736ea1b7754517f4df14fd96a2b)" = "" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum smithay-client-toolkit 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4899558362a65589b53313935099835acf999740915e134dff20cca7c6a28b" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum stb_truetype 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "69b7df505db8e81d54ff8be4693421e5b543e08214bd8d99eb761fcb4d5668ba" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum svgdom 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a9b53b3ed152fc6b871f7232a8772c640567fd25d056941450637ecba32924d" "checksum svgtypes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c43c25e6de7264024b5e351eb0c342039eb5acf51f2e9d0099bbd324b661453b" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -2447,6 +2455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e77d1e6887f07ea2e5d79a3d7d03a875e62d3746334a909b5035d779d849a523" @@ -2455,7 +2464,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum wayland-scanner 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "63bc5efa7dcdb8f04d2e5d1571c0d0577fc47076d133d68e056bdb299f1b60e2" "checksum wayland-sys 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e76af81a601b84d400744f85f083381daa77ac01f6c8711e57e662dc3a35d69d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" diff --git a/canvas/Cargo.toml b/canvas/Cargo.toml index 0bd17dcb..0ca7b922 100644 --- a/canvas/Cargo.toml +++ b/canvas/Cargo.toml @@ -18,4 +18,4 @@ path = "../text" [dependencies.skribo] git = "https://github.com/linebender/skribo.git" -rev = "f759c2d2c188b668bce998179f03b6319835353e" +rev = "a89e9ca99e0d6736ea1b7754517f4df14fd96a2b" diff --git a/examples/canvas_text/src/main.rs b/examples/canvas_text/src/main.rs index 7490b499..8894e776 100644 --- a/examples/canvas_text/src/main.rs +++ b/examples/canvas_text/src/main.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use pathfinder_canvas::{CanvasRenderingContext2D, Path2D}; +use pathfinder_canvas::CanvasRenderingContext2D; use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; -use pathfinder_geometry::basic::rect::RectF32; use pathfinder_geometry::color::ColorF; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::FilesystemResourceLoader; diff --git a/text/Cargo.toml b/text/Cargo.toml index 5661db29..352e801f 100644 --- a/text/Cargo.toml +++ b/text/Cargo.toml @@ -17,4 +17,4 @@ path = "../renderer" [dependencies.skribo] git = "https://github.com/linebender/skribo.git" -rev = "f759c2d2c188b668bce998179f03b6319835353e" +rev = "a89e9ca99e0d6736ea1b7754517f4df14fd96a2b" From 376a1c716545e1ae4e088bc9909a2a4e0bd616a9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 14 May 2019 11:33:52 -0700 Subject: [PATCH 09/28] Rename "fill colors" to "paint" in preparation for gradients and images --- renderer/src/builder.rs | 2 +- renderer/src/gpu/renderer.rs | 104 ++++++++----------- renderer/src/gpu_data.rs | 14 ++- renderer/src/scene.rs | 29 +++--- resources/shaders/tile_alpha_vertex.inc.glsl | 4 +- resources/shaders/tile_monochrome.inc.glsl | 6 +- resources/shaders/tile_multicolor.inc.glsl | 12 +-- resources/shaders/tile_solid_vertex.inc.glsl | 4 +- 8 files changed, 83 insertions(+), 92 deletions(-) diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 86818da6..85060bd5 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -59,7 +59,7 @@ impl<'a> SceneBuilder<'a> { let path_count = self.scene.paths.len(); self.listener.send(RenderCommand::Start { bounding_quad, path_count }); - self.listener.send(RenderCommand::AddShaders(self.scene.build_shaders())); + self.listener.send(RenderCommand::AddPaintData(self.scene.build_paint_data())); let effective_view_box = self.scene.effective_view_box(self.built_options); let alpha_tiles = executor.flatten_into_vector(path_count, |path_index| { diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index b355215d..f6c20bed 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -9,10 +9,10 @@ // except according to those terms. use crate::gpu::debug::DebugUIPresenter; -use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive}; +use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive, PaintData}; use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive}; use crate::post::DefringingKernel; -use crate::scene::ObjectShader; +use crate::scene::{PAINT_TEXTURE_HEIGHT, PAINT_TEXTURE_WIDTH}; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use pathfinder_geometry::basic::point::{Point2DI32, Point3DF32}; use pathfinder_geometry::basic::rect::RectI32; @@ -41,9 +41,6 @@ const FILL_INSTANCE_SIZE: usize = 8; const SOLID_TILE_INSTANCE_SIZE: usize = 6; const MASK_TILE_INSTANCE_SIZE: usize = 8; -const FILL_COLORS_TEXTURE_WIDTH: i32 = 256; -const FILL_COLORS_TEXTURE_HEIGHT: i32 = 256; - const MAX_FILLS_PER_BATCH: usize = 0x4000; pub struct Renderer @@ -68,7 +65,7 @@ where quad_vertex_positions_buffer: D::Buffer, fill_vertex_array: FillVertexArray, mask_framebuffer: D::Framebuffer, - fill_colors_texture: D::Texture, + paint_texture: D::Texture, // Postprocessing shader postprocess_source_framebuffer: Option, @@ -171,9 +168,8 @@ where device.create_texture(TextureFormat::R16F, mask_framebuffer_size); let mask_framebuffer = device.create_framebuffer(mask_framebuffer_texture); - let fill_colors_size = - Point2DI32::new(FILL_COLORS_TEXTURE_WIDTH, FILL_COLORS_TEXTURE_HEIGHT); - let fill_colors_texture = device.create_texture(TextureFormat::RGBA8, fill_colors_size); + let paint_size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT); + let paint_texture = device.create_texture(TextureFormat::RGBA8, paint_size); let window_size = dest_framebuffer.window_size(&device); let debug_ui_presenter = DebugUIPresenter::new(&device, resources, window_size); @@ -195,7 +191,7 @@ where quad_vertex_positions_buffer, fill_vertex_array, mask_framebuffer, - fill_colors_texture, + paint_texture, postprocess_source_framebuffer: None, postprocess_program, @@ -242,7 +238,7 @@ where } self.stats.path_count = path_count; } - RenderCommand::AddShaders(ref shaders) => self.upload_shaders(shaders), + RenderCommand::AddPaintData(ref paint_data) => self.upload_paint_data(paint_data), RenderCommand::AddFills(ref fills) => self.add_fills(fills), RenderCommand::FlushFills => { self.begin_composite_timer_query(); @@ -345,17 +341,8 @@ where &self.quad_vertex_positions_buffer } - fn upload_shaders(&mut self, shaders: &[ObjectShader]) { - let size = Point2DI32::new(FILL_COLORS_TEXTURE_WIDTH, FILL_COLORS_TEXTURE_HEIGHT); - let mut fill_colors = vec![0; size.x() as usize * size.y() as usize * 4]; - for (shader_index, shader) in shaders.iter().enumerate() { - fill_colors[shader_index * 4 + 0] = shader.fill_color.r; - fill_colors[shader_index * 4 + 1] = shader.fill_color.g; - fill_colors[shader_index * 4 + 2] = shader.fill_color.b; - fill_colors[shader_index * 4 + 3] = shader.fill_color.a; - } - self.device - .upload_to_texture(&self.fill_colors_texture, size, &fill_colors); + fn upload_paint_data(&mut self, paint_data: &PaintData) { + self.device.upload_to_texture(&self.paint_texture, paint_data.size, &paint_data.texels); } fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileBatchPrimitive]) { @@ -493,32 +480,27 @@ where match self.render_mode { RenderMode::Multicolor => { - self.device.bind_texture(&self.fill_colors_texture, 1); + self.device.bind_texture(&self.paint_texture, 1); self.device.set_uniform( - &self - .alpha_multicolor_tile_program - .fill_colors_texture_uniform, + &self.alpha_multicolor_tile_program.paint_texture_uniform, UniformData::TextureUnit(1), ); self.device.set_uniform( - &self - .alpha_multicolor_tile_program - .fill_colors_texture_size_uniform, + &self.alpha_multicolor_tile_program.paint_texture_size_uniform, UniformData::Vec2( - I32x4::new(FILL_COLORS_TEXTURE_WIDTH, FILL_COLORS_TEXTURE_HEIGHT, 0, 0) - .to_f32x4(), + I32x4::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT, 0, 0).to_f32x4() ), ); } RenderMode::Monochrome { .. } if self.postprocessing_needed() => { self.device.set_uniform( - &self.alpha_monochrome_tile_program.fill_color_uniform, + &self.alpha_monochrome_tile_program.color_uniform, UniformData::Vec4(F32x4::splat(1.0)), ); } RenderMode::Monochrome { fg_color, .. } => { self.device.set_uniform( - &self.alpha_monochrome_tile_program.fill_color_uniform, + &self.alpha_monochrome_tile_program.color_uniform, UniformData::Vec4(fg_color.0), ); } @@ -558,32 +540,32 @@ where match self.render_mode { RenderMode::Multicolor => { - self.device.bind_texture(&self.fill_colors_texture, 0); + self.device.bind_texture(&self.paint_texture, 0); self.device.set_uniform( &self .solid_multicolor_tile_program - .fill_colors_texture_uniform, + .paint_texture_uniform, UniformData::TextureUnit(0), ); self.device.set_uniform( &self .solid_multicolor_tile_program - .fill_colors_texture_size_uniform, + .paint_texture_size_uniform, UniformData::Vec2( - I32x4::new(FILL_COLORS_TEXTURE_WIDTH, FILL_COLORS_TEXTURE_HEIGHT, 0, 0) + I32x4::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT, 0, 0) .to_f32x4(), ), ); } RenderMode::Monochrome { .. } if self.postprocessing_needed() => { self.device.set_uniform( - &self.solid_monochrome_tile_program.fill_color_uniform, + &self.solid_monochrome_tile_program.color_uniform, UniformData::Vec4(F32x4::splat(1.0)), ); } RenderMode::Monochrome { fg_color, .. } => { self.device.set_uniform( - &self.solid_monochrome_tile_program.fill_color_uniform, + &self.solid_monochrome_tile_program.color_uniform, UniformData::Vec4(fg_color.0), ); } @@ -1177,8 +1159,8 @@ where D: Device, { solid_tile_program: SolidTileProgram, - fill_colors_texture_uniform: D::Uniform, - fill_colors_texture_size_uniform: D::Uniform, + paint_texture_uniform: D::Uniform, + paint_texture_size_uniform: D::Uniform, } impl SolidTileMulticolorProgram @@ -1187,14 +1169,14 @@ where { fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileMulticolorProgram { let solid_tile_program = SolidTileProgram::new(device, "tile_solid_multicolor", resources); - let fill_colors_texture_uniform = - device.get_uniform(&solid_tile_program.program, "FillColorsTexture"); - let fill_colors_texture_size_uniform = - device.get_uniform(&solid_tile_program.program, "FillColorsTextureSize"); + let paint_texture_uniform = + device.get_uniform(&solid_tile_program.program, "PaintTexture"); + let paint_texture_size_uniform = + device.get_uniform(&solid_tile_program.program, "PaintTextureSize"); SolidTileMulticolorProgram { solid_tile_program, - fill_colors_texture_uniform, - fill_colors_texture_size_uniform, + paint_texture_uniform, + paint_texture_size_uniform, } } } @@ -1204,7 +1186,7 @@ where D: Device, { solid_tile_program: SolidTileProgram, - fill_color_uniform: D::Uniform, + color_uniform: D::Uniform, } impl SolidTileMonochromeProgram @@ -1213,10 +1195,10 @@ where { fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileMonochromeProgram { let solid_tile_program = SolidTileProgram::new(device, "tile_solid_monochrome", resources); - let fill_color_uniform = device.get_uniform(&solid_tile_program.program, "FillColor"); + let color_uniform = device.get_uniform(&solid_tile_program.program, "Color"); SolidTileMonochromeProgram { solid_tile_program, - fill_color_uniform, + color_uniform, } } } @@ -1265,8 +1247,8 @@ where D: Device, { alpha_tile_program: AlphaTileProgram, - fill_colors_texture_uniform: D::Uniform, - fill_colors_texture_size_uniform: D::Uniform, + paint_texture_uniform: D::Uniform, + paint_texture_size_uniform: D::Uniform, } impl AlphaTileMulticolorProgram @@ -1275,14 +1257,14 @@ where { fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileMulticolorProgram { let alpha_tile_program = AlphaTileProgram::new(device, "tile_alpha_multicolor", resources); - let fill_colors_texture_uniform = - device.get_uniform(&alpha_tile_program.program, "FillColorsTexture"); - let fill_colors_texture_size_uniform = - device.get_uniform(&alpha_tile_program.program, "FillColorsTextureSize"); + let paint_texture_uniform = + device.get_uniform(&alpha_tile_program.program, "PaintTexture"); + let paint_texture_size_uniform = + device.get_uniform(&alpha_tile_program.program, "PaintTextureSize"); AlphaTileMulticolorProgram { alpha_tile_program, - fill_colors_texture_uniform, - fill_colors_texture_size_uniform, + paint_texture_uniform, + paint_texture_size_uniform, } } } @@ -1292,7 +1274,7 @@ where D: Device, { alpha_tile_program: AlphaTileProgram, - fill_color_uniform: D::Uniform, + color_uniform: D::Uniform, } impl AlphaTileMonochromeProgram @@ -1301,10 +1283,10 @@ where { fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileMonochromeProgram { let alpha_tile_program = AlphaTileProgram::new(device, "tile_alpha_monochrome", resources); - let fill_color_uniform = device.get_uniform(&alpha_tile_program.program, "FillColor"); + let color_uniform = device.get_uniform(&alpha_tile_program.program, "Color"); AlphaTileMonochromeProgram { alpha_tile_program, - fill_color_uniform, + color_uniform, } } } diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index c130abd6..55ecb7f8 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -11,9 +11,9 @@ //! Packed data ready to be sent to the GPU. use crate::options::BoundingQuad; -use crate::scene::ObjectShader; use crate::tile_map::DenseTileMap; use pathfinder_geometry::basic::line_segment::{LineSegmentU4, LineSegmentU8}; +use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::rect::RectF32; use std::fmt::{Debug, Formatter, Result as DebugResult}; use std::time::Duration; @@ -28,7 +28,7 @@ pub(crate) struct BuiltObject { pub enum RenderCommand { Start { path_count: usize, bounding_quad: BoundingQuad }, - AddShaders(Vec), + AddPaintData(PaintData), AddFills(Vec), FlushFills, AlphaTile(Vec), @@ -36,6 +36,12 @@ pub enum RenderCommand { Finish { build_time: Duration }, } +#[derive(Clone, Debug)] +pub struct PaintData { + pub size: Point2DI32, + pub texels: Vec, +} + #[derive(Clone, Copy, Debug)] pub struct FillObjectPrimitive { pub px: LineSegmentU4, @@ -84,8 +90,8 @@ impl Debug for RenderCommand { fn fmt(&self, formatter: &mut Formatter) -> DebugResult { match *self { RenderCommand::Start { .. } => write!(formatter, "Start"), - RenderCommand::AddShaders(ref shaders) => { - write!(formatter, "AddShaders(x{})", shaders.len()) + RenderCommand::AddPaintData(ref paint_data) => { + write!(formatter, "AddPaintData({}x{})", paint_data.size.x(), paint_data.size.y()) } RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()), RenderCommand::FlushFills => write!(formatter, "FlushFills"), diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index b06af40c..7d4916f4 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -12,16 +12,20 @@ use crate::builder::SceneBuilder; use crate::concurrent::executor::Executor; +use crate::gpu_data::PaintData; use crate::options::{PreparedRenderOptions, PreparedRenderTransform}; use crate::options::{RenderCommandListener, RenderOptions}; use hashbrown::HashMap; -use pathfinder_geometry::basic::point::Point2DF32; +use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; use pathfinder_geometry::basic::rect::RectF32; use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::Outline; use std::io::{self, Write}; +pub const PAINT_TEXTURE_WIDTH: i32 = 256; +pub const PAINT_TEXTURE_HEIGHT: i32 = 256; + #[derive(Clone)] pub struct Scene { pub(crate) paths: Vec, @@ -85,13 +89,17 @@ impl Scene { self.view_box = new_view_box; } - pub fn build_shaders(&self) -> Vec { - self.paths - .iter() - .map(|path_object| { - ObjectShader { fill_color: self.paints[path_object.paint.0 as usize].color } - }) - .collect() + pub fn build_paint_data(&self) -> PaintData { + let size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT); + let mut texels = vec![0; size.x() as usize * size.y() as usize * 4]; + for (path_object_index, path_object) in self.paths.iter().enumerate() { + let paint = &self.paints[path_object.paint.0 as usize]; + texels[path_object_index * 4 + 0] = paint.color.r; + texels[path_object_index * 4 + 1] = paint.color.g; + texels[path_object_index * 4 + 2] = paint.color.b; + texels[path_object_index * 4 + 3] = paint.color.a; + } + PaintData { size, texels } } pub(crate) fn apply_render_options( @@ -234,8 +242,3 @@ pub struct Paint { #[derive(Clone, Copy, PartialEq, Debug)] pub struct PaintId(pub u16); - -#[derive(Clone, Copy, Debug, Default)] -pub struct ObjectShader { - pub fill_color: ColorU, -} diff --git a/resources/shaders/tile_alpha_vertex.inc.glsl b/resources/shaders/tile_alpha_vertex.inc.glsl index c339f926..f9e7e5ba 100644 --- a/resources/shaders/tile_alpha_vertex.inc.glsl +++ b/resources/shaders/tile_alpha_vertex.inc.glsl @@ -23,7 +23,7 @@ out vec2 vTexCoord; out float vBackdrop; out vec4 vColor; -vec4 getFillColor(uint object); +vec4 getColor(uint object); vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); @@ -39,7 +39,7 @@ void computeVaryings() { vTexCoord = texCoord / uStencilTextureSize; vBackdrop = float(aBackdrop); - vColor = getFillColor(aObject); + vColor = getColor(aObject); gl_Position = vec4(position, 0.0, 1.0); } diff --git a/resources/shaders/tile_monochrome.inc.glsl b/resources/shaders/tile_monochrome.inc.glsl index b8d255fc..632c7694 100644 --- a/resources/shaders/tile_monochrome.inc.glsl +++ b/resources/shaders/tile_monochrome.inc.glsl @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -uniform vec4 uFillColor; +uniform vec4 uColor; -vec4 getFillColor(uint object) { - return uFillColor; +vec4 getColor(uint object) { + return uColor; } diff --git a/resources/shaders/tile_multicolor.inc.glsl b/resources/shaders/tile_multicolor.inc.glsl index a66a3f56..4c4f65dd 100644 --- a/resources/shaders/tile_multicolor.inc.glsl +++ b/resources/shaders/tile_multicolor.inc.glsl @@ -8,15 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -uniform sampler2D uFillColorsTexture; -uniform vec2 uFillColorsTextureSize; +uniform sampler2D uPaintTexture; +uniform vec2 uPaintTextureSize; -vec2 computeFillColorTexCoord(uint object, vec2 textureSize) { +vec2 computePaintTexCoord(uint object, vec2 textureSize) { uint width = uint(textureSize.x); return (vec2(float(object % width), float(object / width)) + vec2(0.5)) / textureSize; } -vec4 getFillColor(uint object) { - vec2 colorTexCoord = computeFillColorTexCoord(object, uFillColorsTextureSize); - return texture(uFillColorsTexture, colorTexCoord); +vec4 getColor(uint object) { + vec2 colorTexCoord = computePaintTexCoord(object, uPaintTextureSize); + return texture(uPaintTexture, colorTexCoord); } diff --git a/resources/shaders/tile_solid_vertex.inc.glsl b/resources/shaders/tile_solid_vertex.inc.glsl index 3c56f2d5..a0eea554 100644 --- a/resources/shaders/tile_solid_vertex.inc.glsl +++ b/resources/shaders/tile_solid_vertex.inc.glsl @@ -18,12 +18,12 @@ in uint aObject; out vec4 vColor; -vec4 getFillColor(uint object); +vec4 getColor(uint object); void computeVaryings() { vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0); - vColor = getFillColor(aObject); + vColor = getColor(aObject); gl_Position = vec4(position, 0.0, 1.0); } From a54378f931574baff4bef27eac665afc0eb64d20 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 14 May 2019 11:38:48 -0700 Subject: [PATCH 10/28] Make the paint texture dynamically-sized on the GPU side --- renderer/src/gpu/renderer.rs | 36 ++++++++++++++++++++---------------- renderer/src/scene.rs | 4 ++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index f6c20bed..bd34980f 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -12,7 +12,6 @@ use crate::gpu::debug::DebugUIPresenter; use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive, PaintData}; use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive}; use crate::post::DefringingKernel; -use crate::scene::{PAINT_TEXTURE_HEIGHT, PAINT_TEXTURE_WIDTH}; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use pathfinder_geometry::basic::point::{Point2DI32, Point3DF32}; use pathfinder_geometry::basic::rect::RectI32; @@ -65,7 +64,7 @@ where quad_vertex_positions_buffer: D::Buffer, fill_vertex_array: FillVertexArray, mask_framebuffer: D::Framebuffer, - paint_texture: D::Texture, + paint_texture: Option, // Postprocessing shader postprocess_source_framebuffer: Option, @@ -168,9 +167,6 @@ where device.create_texture(TextureFormat::R16F, mask_framebuffer_size); let mask_framebuffer = device.create_framebuffer(mask_framebuffer_texture); - let paint_size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT); - let paint_texture = device.create_texture(TextureFormat::RGBA8, paint_size); - let window_size = dest_framebuffer.window_size(&device); let debug_ui_presenter = DebugUIPresenter::new(&device, resources, window_size); @@ -191,7 +187,7 @@ where quad_vertex_positions_buffer, fill_vertex_array, mask_framebuffer, - paint_texture, + paint_texture: None, postprocess_source_framebuffer: None, postprocess_program, @@ -342,7 +338,18 @@ where } fn upload_paint_data(&mut self, paint_data: &PaintData) { - self.device.upload_to_texture(&self.paint_texture, paint_data.size, &paint_data.texels); + match self.paint_texture { + Some(ref paint_texture) if + self.device.texture_size(paint_texture) == paint_data.size => {} + _ => { + let texture = self.device.create_texture(TextureFormat::RGBA8, paint_data.size); + self.paint_texture = Some(texture) + } + } + + self.device.upload_to_texture(self.paint_texture.as_ref().unwrap(), + paint_data.size, + &paint_data.texels); } fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileBatchPrimitive]) { @@ -480,16 +487,15 @@ where match self.render_mode { RenderMode::Multicolor => { - self.device.bind_texture(&self.paint_texture, 1); + let paint_texture = self.paint_texture.as_ref().unwrap(); + self.device.bind_texture(paint_texture, 1); self.device.set_uniform( &self.alpha_multicolor_tile_program.paint_texture_uniform, UniformData::TextureUnit(1), ); self.device.set_uniform( &self.alpha_multicolor_tile_program.paint_texture_size_uniform, - UniformData::Vec2( - I32x4::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT, 0, 0).to_f32x4() - ), + UniformData::Vec2(self.device.texture_size(paint_texture).0.to_f32x4()) ); } RenderMode::Monochrome { .. } if self.postprocessing_needed() => { @@ -540,7 +546,8 @@ where match self.render_mode { RenderMode::Multicolor => { - self.device.bind_texture(&self.paint_texture, 0); + let paint_texture = self.paint_texture.as_ref().unwrap(); + self.device.bind_texture(paint_texture, 0); self.device.set_uniform( &self .solid_multicolor_tile_program @@ -551,10 +558,7 @@ where &self .solid_multicolor_tile_program .paint_texture_size_uniform, - UniformData::Vec2( - I32x4::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT, 0, 0) - .to_f32x4(), - ), + UniformData::Vec2(self.device.texture_size(paint_texture).0.to_f32x4()) ); } RenderMode::Monochrome { .. } if self.postprocessing_needed() => { diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 7d4916f4..79100553 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -23,8 +23,8 @@ use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::Outline; use std::io::{self, Write}; -pub const PAINT_TEXTURE_WIDTH: i32 = 256; -pub const PAINT_TEXTURE_HEIGHT: i32 = 256; +const PAINT_TEXTURE_WIDTH: i32 = 256; +const PAINT_TEXTURE_HEIGHT: i32 = 256; #[derive(Clone)] pub struct Scene { From 7a02b78b3d4bf894c1fe3ff6c04d4cc3d58e6f84 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 14 May 2019 14:28:21 -0700 Subject: [PATCH 11/28] Explicitly specify color texture coordinates for alpha and solid tiles. This is groundwork for gradients and images. This commit also refactors the interface for vertex attributes to use named parameters (via structs), for clarity. --- demo/common/src/device.rs | 11 +- gl/src/lib.rs | 60 ++-- gpu/src/lib.rs | 37 ++- renderer/src/gpu/renderer.rs | 288 +++++++++++-------- renderer/src/gpu_data.rs | 4 + renderer/src/lib.rs | 1 + renderer/src/paint.rs | 37 +++ renderer/src/scene.rs | 26 +- renderer/src/tiles.rs | 9 +- renderer/src/z_buffer.rs | 25 +- resources/shaders/tile_alpha_vertex.inc.glsl | 9 +- resources/shaders/tile_monochrome.inc.glsl | 2 +- resources/shaders/tile_multicolor.inc.glsl | 10 +- resources/shaders/tile_solid_vertex.inc.glsl | 5 +- ui/src/lib.rs | 48 ++-- 15 files changed, 333 insertions(+), 239 deletions(-) create mode 100644 renderer/src/paint.rs diff --git a/demo/common/src/device.rs b/demo/common/src/device.rs index ccd0b877..17b14e9a 100644 --- a/demo/common/src/device.rs +++ b/demo/common/src/device.rs @@ -11,7 +11,7 @@ //! GPU rendering code specifically for the demo. use pathfinder_gpu::resources::ResourceLoader; -use pathfinder_gpu::{BufferTarget, Device, VertexAttrType}; +use pathfinder_gpu::{BufferTarget, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; pub struct GroundProgram where @@ -67,7 +67,14 @@ where device.bind_vertex_array(&vertex_array); device.use_program(&ground_program.program); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr(&position_attr, 2, VertexAttrType::U8, false, 0, 0, 0); + device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U8, + stride: 0, + offset: 0, + divisor: 0, + }); GroundVertexArray { vertex_array } } diff --git a/gl/src/lib.rs b/gl/src/lib.rs index 5522083e..cb4e002a 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -18,7 +18,8 @@ use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::rect::RectI32; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearParams}; use pathfinder_gpu::{DepthFunc, Device, Primitive, RenderState, ShaderKind, StencilFunc}; -use pathfinder_gpu::{TextureFormat, UniformData, VertexAttrType}; +use pathfinder_gpu::{TextureFormat, UniformData, VertexAttrClass}; +use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_simd::default::F32x4; use rustache::{HashBuilder, Render}; use std::ffi::CString; @@ -327,40 +328,33 @@ impl Device for GLDevice { } } - fn configure_float_vertex_attr(&self, - attr: &GLVertexAttr, - size: usize, - attr_type: VertexAttrType, - normalized: bool, - stride: usize, - offset: usize, - divisor: u32) { + fn configure_vertex_attr(&self, attr: &GLVertexAttr, descriptor: &VertexAttrDescriptor) { unsafe { - gl::VertexAttribPointer(attr.attr, - size as GLint, - attr_type.to_gl_type(), - if normalized { gl::TRUE } else { gl::FALSE }, - stride as GLint, - offset as *const GLvoid); ck(); - gl::VertexAttribDivisor(attr.attr, divisor); ck(); - gl::EnableVertexAttribArray(attr.attr); ck(); - } - } + let attr_type = descriptor.attr_type.to_gl_type(); + match descriptor.class { + VertexAttrClass::Float | VertexAttrClass::FloatNorm => { + let normalized = if descriptor.class == VertexAttrClass::FloatNorm { + gl::TRUE + } else { + gl::FALSE + }; + gl::VertexAttribPointer(attr.attr, + descriptor.size as GLint, + attr_type, + normalized, + descriptor.stride as GLint, + descriptor.offset as *const GLvoid); ck(); + } + VertexAttrClass::Int => { + gl::VertexAttribIPointer(attr.attr, + descriptor.size as GLint, + attr_type, + descriptor.stride as GLint, + descriptor.offset as *const GLvoid); ck(); + } + } - fn configure_int_vertex_attr(&self, - attr: &GLVertexAttr, - size: usize, - attr_type: VertexAttrType, - stride: usize, - offset: usize, - divisor: u32) { - unsafe { - gl::VertexAttribIPointer(attr.attr, - size as GLint, - attr_type.to_gl_type(), - stride as GLint, - offset as *const GLvoid); ck(); - gl::VertexAttribDivisor(attr.attr, divisor); ck(); + gl::VertexAttribDivisor(attr.attr, descriptor.divisor); ck(); gl::EnableVertexAttribArray(attr.attr); ck(); } } diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index 7282eab1..ec418cee 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -52,25 +52,7 @@ pub trait Device { fn get_vertex_attr(&self, program: &Self::Program, name: &str) -> Self::VertexAttr; fn get_uniform(&self, program: &Self::Program, name: &str) -> Self::Uniform; fn use_program(&self, program: &Self::Program); - fn configure_float_vertex_attr( - &self, - attr: &Self::VertexAttr, - size: usize, - attr_type: VertexAttrType, - normalized: bool, - stride: usize, - offset: usize, - divisor: u32, - ); - fn configure_int_vertex_attr( - &self, - attr: &Self::VertexAttr, - size: usize, - attr_type: VertexAttrType, - stride: usize, - offset: usize, - divisor: u32, - ); + fn configure_vertex_attr(&self, attr: &Self::VertexAttr, descriptor: &VertexAttrDescriptor); fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData); fn create_framebuffer(&self, texture: Self::Texture) -> Self::Framebuffer; fn create_buffer(&self) -> Self::Buffer; @@ -340,6 +322,23 @@ impl UniformData { } } +#[derive(Clone, Copy, Debug)] +pub struct VertexAttrDescriptor { + pub size: usize, + pub class: VertexAttrClass, + pub attr_type: VertexAttrType, + pub stride: usize, + pub offset: usize, + pub divisor: u32, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum VertexAttrClass { + Float, + FloatNorm, + Int, +} + fn load_shader_include(resources: &dyn ResourceLoader, include_name: &str) -> String { let resource = resources .slurp(&format!("shaders/{}.inc.glsl", include_name)) diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index bd34980f..96a5dc55 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -20,7 +20,8 @@ use pathfinder_geometry::color::ColorF; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearParams}; use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderState, StencilFunc}; -use pathfinder_gpu::{StencilState, TextureFormat, UniformData, VertexAttrType}; +use pathfinder_gpu::{StencilState, TextureFormat, UniformData, VertexAttrClass}; +use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_simd::default::{F32x4, I32x4}; use std::cmp; use std::collections::VecDeque; @@ -37,8 +38,8 @@ const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * 256; // TODO(pcwalton): Replace with `mem::size_of` calls? const FILL_INSTANCE_SIZE: usize = 8; -const SOLID_TILE_INSTANCE_SIZE: usize = 6; -const MASK_TILE_INSTANCE_SIZE: usize = 8; +const SOLID_TILE_INSTANCE_SIZE: usize = 10; +const MASK_TILE_INSTANCE_SIZE: usize = 12; const MAX_FILLS_PER_BATCH: usize = 0x4000; @@ -918,55 +919,57 @@ where device.bind_vertex_array(&vertex_array); device.use_program(&fill_program.program); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr(&tess_coord_attr, 2, VertexAttrType::U8, false, 0, 0, 0); + device.configure_vertex_attr(&tess_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U8, + stride: 0, + offset: 0, + divisor: 0, + }); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); - device.configure_int_vertex_attr( - &from_px_attr, - 1, - VertexAttrType::U8, - FILL_INSTANCE_SIZE, - 0, - 1, - ); - device.configure_int_vertex_attr( - &to_px_attr, - 1, - VertexAttrType::U8, - FILL_INSTANCE_SIZE, - 1, - 1, - ); - device.configure_float_vertex_attr( - &from_subpx_attr, - 2, - VertexAttrType::U8, - true, - FILL_INSTANCE_SIZE, - 2, - 1, - ); - device.configure_float_vertex_attr( - &to_subpx_attr, - 2, - VertexAttrType::U8, - true, - FILL_INSTANCE_SIZE, - 4, - 1, - ); - device.configure_int_vertex_attr( - &tile_index_attr, - 1, - VertexAttrType::U16, - FILL_INSTANCE_SIZE, - 6, - 1, - ); + device.configure_vertex_attr(&from_px_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::U8, + stride: FILL_INSTANCE_SIZE, + offset: 0, + divisor: 1, + }); + device.configure_vertex_attr(&to_px_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::U8, + stride: FILL_INSTANCE_SIZE, + offset: 1, + divisor: 1, + }); + device.configure_vertex_attr(&from_subpx_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U8, + stride: FILL_INSTANCE_SIZE, + offset: 2, + divisor: 1, + }); + device.configure_vertex_attr(&to_subpx_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U8, + stride: FILL_INSTANCE_SIZE, + offset: 4, + divisor: 1, + }); + device.configure_vertex_attr(&tile_index_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::U16, + stride: FILL_INSTANCE_SIZE, + offset: 6, + divisor: 1, + }); - FillVertexArray { - vertex_array, - vertex_buffer, - } + FillVertexArray { vertex_array, vertex_buffer } } } @@ -994,51 +997,65 @@ where let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop"); let object_attr = device.get_vertex_attr(&alpha_tile_program.program, "Object"); let tile_index_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileIndex"); + let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, + "ColorTexCoord"); // NB: The object must be of type `I16`, not `U16`, to work around a macOS Radeon // driver bug. device.bind_vertex_array(&vertex_array); device.use_program(&alpha_tile_program.program); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr(&tess_coord_attr, 2, VertexAttrType::U8, false, 0, 0, 0); + device.configure_vertex_attr(&tess_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U8, + stride: 0, + offset: 0, + divisor: 0, + }); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); - device.configure_int_vertex_attr( - &tile_origin_attr, - 3, - VertexAttrType::U8, - MASK_TILE_INSTANCE_SIZE, - 0, - 1, - ); - device.configure_int_vertex_attr( - &backdrop_attr, - 1, - VertexAttrType::I8, - MASK_TILE_INSTANCE_SIZE, - 3, - 1, - ); - device.configure_int_vertex_attr( - &object_attr, - 1, - VertexAttrType::I16, - MASK_TILE_INSTANCE_SIZE, - 4, - 1, - ); - device.configure_int_vertex_attr( - &tile_index_attr, - 1, - VertexAttrType::I16, - MASK_TILE_INSTANCE_SIZE, - 6, - 1, - ); + device.configure_vertex_attr(&tile_origin_attr, &VertexAttrDescriptor { + size: 3, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::U8, + stride: MASK_TILE_INSTANCE_SIZE, + offset: 0, + divisor: 1, + }); + device.configure_vertex_attr(&backdrop_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::I8, + stride: MASK_TILE_INSTANCE_SIZE, + offset: 3, + divisor: 1, + }); + device.configure_vertex_attr(&object_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::I16, + stride: MASK_TILE_INSTANCE_SIZE, + offset: 4, + divisor: 1, + }); + device.configure_vertex_attr(&tile_index_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::I16, + stride: MASK_TILE_INSTANCE_SIZE, + offset: 6, + divisor: 1, + }); + device.configure_vertex_attr(&color_tex_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U16, + stride: MASK_TILE_INSTANCE_SIZE, + offset: 8, + divisor: 1, + }); - AlphaTileVertexArray { - vertex_array, - vertex_buffer, - } + AlphaTileVertexArray { vertex_array, vertex_buffer } } } @@ -1064,36 +1081,49 @@ where let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord"); let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin"); let object_attr = device.get_vertex_attr(&solid_tile_program.program, "Object"); + let color_tex_coord_attr = device.get_vertex_attr(&solid_tile_program.program, + "ColorTexCoord"); // NB: The object must be of type short, not unsigned short, to work around a macOS // Radeon driver bug. device.bind_vertex_array(&vertex_array); device.use_program(&solid_tile_program.program); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr(&tess_coord_attr, 2, VertexAttrType::U8, false, 0, 0, 0); + device.configure_vertex_attr(&tess_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U8, + stride: 0, + offset: 0, + divisor: 0, + }); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr( - &tile_origin_attr, - 2, - VertexAttrType::I16, - false, - SOLID_TILE_INSTANCE_SIZE, - 0, - 1, - ); - device.configure_int_vertex_attr( - &object_attr, - 1, - VertexAttrType::I16, - SOLID_TILE_INSTANCE_SIZE, - 4, - 1, - ); + device.configure_vertex_attr(&tile_origin_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::I16, + stride: SOLID_TILE_INSTANCE_SIZE, + offset: 0, + divisor: 1, + }); + device.configure_vertex_attr(&color_tex_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U16, + stride: SOLID_TILE_INSTANCE_SIZE, + offset: 4, + divisor: 1, + }); + device.configure_vertex_attr(&object_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::I16, + stride: SOLID_TILE_INSTANCE_SIZE, + offset: 8, + divisor: 1, + }); - SolidTileVertexArray { - vertex_array, - vertex_buffer, - } + SolidTileVertexArray { vertex_array, vertex_buffer } } } @@ -1361,7 +1391,14 @@ where device.bind_vertex_array(&vertex_array); device.use_program(&postprocess_program.program); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr(&position_attr, 2, VertexAttrType::U8, false, 0, 0, 0); + device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U8, + stride: 0, + offset: 0, + divisor: 0, + }); PostprocessVertexArray { vertex_array } } @@ -1404,20 +1441,16 @@ where device.bind_vertex_array(&vertex_array); device.use_program(&stencil_program.program); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr( - &position_attr, - 3, - VertexAttrType::F32, - false, - 4 * 4, - 0, - 0, - ); + device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor { + size: 3, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::F32, + stride: 4 * 4, + offset: 0, + divisor: 0, + }); - StencilVertexArray { - vertex_array, - vertex_buffer, - } + StencilVertexArray { vertex_array, vertex_buffer } } } @@ -1473,7 +1506,14 @@ where device.bind_vertex_array(&vertex_array); device.use_program(&reprojection_program.program); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_float_vertex_attr(&position_attr, 2, VertexAttrType::U8, false, 0, 0, 0); + device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U8, + stride: 0, + offset: 0, + divisor: 0, + }); ReprojectionVertexArray { vertex_array } } diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 55ecb7f8..48520986 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -72,6 +72,8 @@ pub struct FillBatchPrimitive { pub struct SolidTileBatchPrimitive { pub tile_x: i16, pub tile_y: i16, + pub origin_u: u16, + pub origin_v: u16, pub object_index: u16, } @@ -84,6 +86,8 @@ pub struct AlphaTileBatchPrimitive { pub backdrop: i8, pub object_index: u16, pub tile_index: u16, + pub origin_u: u16, + pub origin_v: u16, } impl Debug for RenderCommand { diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 803e5e13..0f80405e 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -17,6 +17,7 @@ pub mod concurrent; pub mod gpu; pub mod gpu_data; pub mod options; +pub mod paint; pub mod post; pub mod scene; diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs new file mode 100644 index 00000000..306c5312 --- /dev/null +++ b/renderer/src/paint.rs @@ -0,0 +1,37 @@ +// pathfinder/renderer/src/paint.rs +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::gpu_data::PaintData; +use crate::scene::Scene; +use pathfinder_geometry::basic::point::Point2DI32; + +const PAINT_TEXTURE_WIDTH: i32 = 256; +const PAINT_TEXTURE_HEIGHT: i32 = 256; + +impl Scene { + pub fn build_paint_data(&self) -> PaintData { + let size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT); + let mut texels = vec![0; size.x() as usize * size.y() as usize * 4]; + for (path_object_index, path_object) in self.paths.iter().enumerate() { + let paint = &self.paints[path_object.paint().0 as usize]; + texels[path_object_index * 4 + 0] = paint.color.r; + texels[path_object_index * 4 + 1] = paint.color.g; + texels[path_object_index * 4 + 2] = paint.color.b; + texels[path_object_index * 4 + 3] = paint.color.a; + } + PaintData { size, texels } + } +} + +pub(crate) fn object_index_to_paint_coords(object_index: u16) -> Point2DI32 { + let tex_coords = Point2DI32::new(object_index as i32 % PAINT_TEXTURE_WIDTH, + object_index as i32 / PAINT_TEXTURE_WIDTH); + tex_coords.scale(256) + Point2DI32::new(128, 128) +} diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 79100553..8497575e 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -12,24 +12,20 @@ use crate::builder::SceneBuilder; use crate::concurrent::executor::Executor; -use crate::gpu_data::PaintData; use crate::options::{PreparedRenderOptions, PreparedRenderTransform}; use crate::options::{RenderCommandListener, RenderOptions}; use hashbrown::HashMap; -use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; +use pathfinder_geometry::basic::point::Point2DF32; use pathfinder_geometry::basic::rect::RectF32; use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::Outline; use std::io::{self, Write}; -const PAINT_TEXTURE_WIDTH: i32 = 256; -const PAINT_TEXTURE_HEIGHT: i32 = 256; - #[derive(Clone)] pub struct Scene { pub(crate) paths: Vec, - paints: Vec, + pub(crate) paints: Vec, paint_cache: HashMap, bounds: RectF32, view_box: RectF32, @@ -89,19 +85,6 @@ impl Scene { self.view_box = new_view_box; } - pub fn build_paint_data(&self) -> PaintData { - let size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT); - let mut texels = vec![0; size.x() as usize * size.y() as usize * 4]; - for (path_object_index, path_object) in self.paths.iter().enumerate() { - let paint = &self.paints[path_object.paint.0 as usize]; - texels[path_object_index * 4 + 0] = paint.color.r; - texels[path_object_index * 4 + 1] = paint.color.g; - texels[path_object_index * 4 + 2] = paint.color.b; - texels[path_object_index * 4 + 3] = paint.color.a; - } - PaintData { size, texels } - } - pub(crate) fn apply_render_options( &self, original_outline: &Outline, @@ -233,6 +216,11 @@ impl PathObject { pub fn outline(&self) -> &Outline { &self.outline } + + #[inline] + pub(crate) fn paint(&self) -> PaintId { + self.paint + } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 0dd99eb1..a09be5b4 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -10,6 +10,7 @@ use crate::builder::SceneBuilder; use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive}; +use crate::paint; use crate::sorted_vector::SortedVector; use pathfinder_geometry::basic::line_segment::LineSegmentF32; use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; @@ -114,11 +115,14 @@ impl<'a> Tiler<'a> { continue; } + let origin_uv = paint::object_index_to_paint_coords(self.object_index); + let alpha_tile = AlphaTileBatchPrimitive::new( tile_coords, tile.backdrop, self.object_index, tile.alpha_tile_index as u16, + origin_uv, ); self.built_object.alpha_tiles.push(alpha_tile); @@ -521,7 +525,8 @@ impl AlphaTileBatchPrimitive { fn new(tile_coords: Point2DI32, backdrop: i8, object_index: u16, - tile_index: u16) + tile_index: u16, + origin_uv: Point2DI32) -> AlphaTileBatchPrimitive { AlphaTileBatchPrimitive { tile_x_lo: (tile_coords.x() & 0xff) as u8, @@ -530,6 +535,8 @@ impl AlphaTileBatchPrimitive { backdrop, object_index, tile_index, + origin_u: origin_uv.x() as u16, + origin_v: origin_uv.y() as u16, } } diff --git a/renderer/src/z_buffer.rs b/renderer/src/z_buffer.rs index a523bd9e..4a70865a 100644 --- a/renderer/src/z_buffer.rs +++ b/renderer/src/z_buffer.rs @@ -11,6 +11,7 @@ //! Software occlusion culling. use crate::gpu_data::SolidTileBatchPrimitive; +use crate::paint; use crate::tile_map::DenseTileMap; use crate::tiles; use pathfinder_geometry::basic::point::Point2DI32; @@ -67,13 +68,27 @@ impl ZBuffer { if object_index < object_range.start || object_index >= object_range.end { continue; } - solid_tiles.push(SolidTileBatchPrimitive { - tile_x: (tile_coords.x() + self.buffer.rect.min_x()) as i16, - tile_y: (tile_coords.y() + self.buffer.rect.min_y()) as i16, - object_index: object_index as u16, - }); + + let origin_uv = paint::object_index_to_paint_coords(object_index as u16); + + solid_tiles.push(SolidTileBatchPrimitive::new(tile_coords + self.buffer.rect.origin(), + object_index as u16, + origin_uv)); } solid_tiles } } + +impl SolidTileBatchPrimitive { + fn new(tile_coords: Point2DI32, object_index: u16, origin_uv: Point2DI32) + -> SolidTileBatchPrimitive { + SolidTileBatchPrimitive { + tile_x: tile_coords.x() as i16, + tile_y: tile_coords.y() as i16, + object_index: object_index, + origin_u: origin_uv.x() as u16, + origin_v: origin_uv.y() as u16, + } + } +} diff --git a/resources/shaders/tile_alpha_vertex.inc.glsl b/resources/shaders/tile_alpha_vertex.inc.glsl index f9e7e5ba..9a13b146 100644 --- a/resources/shaders/tile_alpha_vertex.inc.glsl +++ b/resources/shaders/tile_alpha_vertex.inc.glsl @@ -23,7 +23,7 @@ out vec2 vTexCoord; out float vBackdrop; out vec4 vColor; -vec4 getColor(uint object); +vec4 getColor(); vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); @@ -35,11 +35,12 @@ void computeVaryings() { vec2 origin = vec2(aTileOrigin.xy) + vec2(aTileOrigin.z & 15u, aTileOrigin.z >> 4u) * 256.0; vec2 pixelPosition = (origin + aTessCoord) * uTileSize + uViewBoxOrigin; vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0); - vec2 texCoord = computeTileOffset(aTileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize; + vec2 maskTexCoordOrigin = computeTileOffset(aTileIndex, uStencilTextureSize.x); + vec2 maskTexCoord = maskTexCoordOrigin + aTessCoord * uTileSize; - vTexCoord = texCoord / uStencilTextureSize; + vTexCoord = maskTexCoord / uStencilTextureSize; vBackdrop = float(aBackdrop); - vColor = getColor(aObject); + vColor = getColor(); gl_Position = vec4(position, 0.0, 1.0); } diff --git a/resources/shaders/tile_monochrome.inc.glsl b/resources/shaders/tile_monochrome.inc.glsl index 632c7694..7b10b25b 100644 --- a/resources/shaders/tile_monochrome.inc.glsl +++ b/resources/shaders/tile_monochrome.inc.glsl @@ -10,6 +10,6 @@ uniform vec4 uColor; -vec4 getColor(uint object) { +vec4 getColor() { return uColor; } diff --git a/resources/shaders/tile_multicolor.inc.glsl b/resources/shaders/tile_multicolor.inc.glsl index 4c4f65dd..a374bbee 100644 --- a/resources/shaders/tile_multicolor.inc.glsl +++ b/resources/shaders/tile_multicolor.inc.glsl @@ -11,12 +11,8 @@ uniform sampler2D uPaintTexture; uniform vec2 uPaintTextureSize; -vec2 computePaintTexCoord(uint object, vec2 textureSize) { - uint width = uint(textureSize.x); - return (vec2(float(object % width), float(object / width)) + vec2(0.5)) / textureSize; -} +in vec2 aColorTexCoord; -vec4 getColor(uint object) { - vec2 colorTexCoord = computePaintTexCoord(object, uPaintTextureSize); - return texture(uPaintTexture, colorTexCoord); +vec4 getColor() { + return texture(uPaintTexture, aColorTexCoord); } diff --git a/resources/shaders/tile_solid_vertex.inc.glsl b/resources/shaders/tile_solid_vertex.inc.glsl index a0eea554..04aa3109 100644 --- a/resources/shaders/tile_solid_vertex.inc.glsl +++ b/resources/shaders/tile_solid_vertex.inc.glsl @@ -18,12 +18,13 @@ in uint aObject; out vec4 vColor; -vec4 getColor(uint object); +vec4 getColor(); void computeVaryings() { vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0); - vColor = getColor(aObject); + vColor = getColor(); + //vColor = vec4(1.0, 0.0, 0.0, 1.0); gl_Position = vec4(position, 0.0, 1.0); } diff --git a/ui/src/lib.rs b/ui/src/lib.rs index c7796d5d..eaff03be 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -22,7 +22,8 @@ use pathfinder_geometry::basic::rect::RectI32; use pathfinder_geometry::color::ColorU; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, Device, Primitive}; -use pathfinder_gpu::{RenderState, UniformData, VertexAttrType}; +use pathfinder_gpu::{RenderState, UniformData, VertexAttrClass}; +use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_simd::default::F32x4; use serde_json; use std::mem; @@ -591,20 +592,22 @@ impl DebugTextureVertexArray where D: Device { device.use_program(&debug_texture_program.program); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&index_buffer, BufferTarget::Index); - device.configure_float_vertex_attr(&position_attr, - 2, - VertexAttrType::U16, - false, - DEBUG_TEXTURE_VERTEX_SIZE, - 0, - 0); - device.configure_float_vertex_attr(&tex_coord_attr, - 2, - VertexAttrType::U16, - false, - DEBUG_TEXTURE_VERTEX_SIZE, - 4, - 0); + device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U16, + stride: DEBUG_TEXTURE_VERTEX_SIZE, + offset: 0, + divisor: 0, + }); + device.configure_vertex_attr(&tex_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U16, + stride: DEBUG_TEXTURE_VERTEX_SIZE, + offset: 4, + divisor: 0, + }); DebugTextureVertexArray { vertex_array, vertex_buffer, index_buffer } } @@ -626,13 +629,14 @@ impl DebugSolidVertexArray where D: Device { device.use_program(&debug_solid_program.program); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&index_buffer, BufferTarget::Index); - device.configure_float_vertex_attr(&position_attr, - 2, - VertexAttrType::U16, - false, - DEBUG_SOLID_VERTEX_SIZE, - 0, - 0); + device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Float, + attr_type: VertexAttrType::U16, + stride: DEBUG_SOLID_VERTEX_SIZE, + offset: 0, + divisor: 0, + }); DebugSolidVertexArray { vertex_array, vertex_buffer, index_buffer } } From 86f5bdb44a848a4aaa53f23dfc399e5f9585d814 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 14 May 2019 15:21:15 -0700 Subject: [PATCH 12/28] Store paints in the paint texture indexed by paint ID, not object index --- renderer/src/builder.rs | 5 +++-- renderer/src/paint.rs | 19 +++++++++---------- renderer/src/tiles.rs | 6 +++++- renderer/src/z_buffer.rs | 6 ++++-- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 85060bd5..dd95ea46 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -81,8 +81,9 @@ impl<'a> SceneBuilder<'a> { ) -> Vec { let path_object = &scene.paths[path_index]; let outline = scene.apply_render_options(path_object.outline(), built_options); + let paint_id = path_object.paint(); - let mut tiler = Tiler::new(self, &outline, view_box, path_index as u16); + let mut tiler = Tiler::new(self, &outline, view_box, paint_id, path_index as u16); tiler.generate_tiles(); self.listener.send(RenderCommand::AddFills(tiler.built_object.fills)); @@ -108,7 +109,7 @@ impl<'a> SceneBuilder<'a> { fn pack_alpha_tiles(&mut self, alpha_tiles: Vec) { let path_count = self.scene.paths.len() as u32; - let solid_tiles = self.z_buffer.build_solid_tiles(0..path_count); + let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths, 0..path_count); if !solid_tiles.is_empty() { self.listener.send(RenderCommand::SolidTile(solid_tiles)); } diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs index 306c5312..9777e5b8 100644 --- a/renderer/src/paint.rs +++ b/renderer/src/paint.rs @@ -9,7 +9,7 @@ // except according to those terms. use crate::gpu_data::PaintData; -use crate::scene::Scene; +use crate::scene::{PaintId, Scene}; use pathfinder_geometry::basic::point::Point2DI32; const PAINT_TEXTURE_WIDTH: i32 = 256; @@ -19,19 +19,18 @@ impl Scene { pub fn build_paint_data(&self) -> PaintData { let size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT); let mut texels = vec![0; size.x() as usize * size.y() as usize * 4]; - for (path_object_index, path_object) in self.paths.iter().enumerate() { - let paint = &self.paints[path_object.paint().0 as usize]; - texels[path_object_index * 4 + 0] = paint.color.r; - texels[path_object_index * 4 + 1] = paint.color.g; - texels[path_object_index * 4 + 2] = paint.color.b; - texels[path_object_index * 4 + 3] = paint.color.a; + for (paint_index, paint) in self.paints.iter().enumerate() { + texels[paint_index * 4 + 0] = paint.color.r; + texels[paint_index * 4 + 1] = paint.color.g; + texels[paint_index * 4 + 2] = paint.color.b; + texels[paint_index * 4 + 3] = paint.color.a; } PaintData { size, texels } } } -pub(crate) fn object_index_to_paint_coords(object_index: u16) -> Point2DI32 { - let tex_coords = Point2DI32::new(object_index as i32 % PAINT_TEXTURE_WIDTH, - object_index as i32 / PAINT_TEXTURE_WIDTH); +pub(crate) fn paint_id_to_tex_coords(paint_id: PaintId) -> Point2DI32 { + let tex_coords = Point2DI32::new(paint_id.0 as i32 % PAINT_TEXTURE_WIDTH, + paint_id.0 as i32 / PAINT_TEXTURE_WIDTH); tex_coords.scale(256) + Point2DI32::new(128, 128) } diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index a09be5b4..cfceb05f 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -11,6 +11,7 @@ use crate::builder::SceneBuilder; use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive}; use crate::paint; +use crate::scene::PaintId; use crate::sorted_vector::SortedVector; use pathfinder_geometry::basic::line_segment::LineSegmentF32; use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; @@ -30,6 +31,7 @@ pub(crate) struct Tiler<'a> { builder: &'a SceneBuilder<'a>, outline: &'a Outline, pub built_object: BuiltObject, + paint_id: PaintId, object_index: u16, point_queue: SortedVector, @@ -43,6 +45,7 @@ impl<'a> Tiler<'a> { builder: &'a SceneBuilder<'a>, outline: &'a Outline, view_box: RectF32, + paint_id: PaintId, object_index: u16, ) -> Tiler<'a> { let bounds = outline @@ -55,6 +58,7 @@ impl<'a> Tiler<'a> { builder, outline, built_object, + paint_id, object_index, point_queue: SortedVector::new(), @@ -115,7 +119,7 @@ impl<'a> Tiler<'a> { continue; } - let origin_uv = paint::object_index_to_paint_coords(self.object_index); + let origin_uv = paint::paint_id_to_tex_coords(self.paint_id); let alpha_tile = AlphaTileBatchPrimitive::new( tile_coords, diff --git a/renderer/src/z_buffer.rs b/renderer/src/z_buffer.rs index 4a70865a..36ffbb75 100644 --- a/renderer/src/z_buffer.rs +++ b/renderer/src/z_buffer.rs @@ -12,6 +12,7 @@ use crate::gpu_data::SolidTileBatchPrimitive; use crate::paint; +use crate::scene::PathObject; use crate::tile_map::DenseTileMap; use crate::tiles; use pathfinder_geometry::basic::point::Point2DI32; @@ -55,7 +56,8 @@ impl ZBuffer { } } - pub fn build_solid_tiles(&self, object_range: Range) -> Vec { + pub fn build_solid_tiles(&self, paths: &[PathObject], object_range: Range) + -> Vec { let mut solid_tiles = vec![]; for tile_index in 0..self.buffer.data.len() { let depth = self.buffer.data[tile_index].load(AtomicOrdering::Relaxed); @@ -69,7 +71,7 @@ impl ZBuffer { continue; } - let origin_uv = paint::object_index_to_paint_coords(object_index as u16); + let origin_uv = paint::paint_id_to_tex_coords(paths[object_index as usize].paint()); solid_tiles.push(SolidTileBatchPrimitive::new(tile_coords + self.buffer.rect.origin(), object_index as u16, From 25a6c33a1a38e62e3c96c553dd570545833f10ba Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 14 May 2019 15:22:50 -0700 Subject: [PATCH 13/28] Remove the object index attribute from the shaders, since it's now unused --- renderer/src/gpu/renderer.rs | 18 ------------------ resources/shaders/tile_alpha_vertex.inc.glsl | 1 - resources/shaders/tile_solid_vertex.inc.glsl | 1 - 3 files changed, 20 deletions(-) diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 96a5dc55..f7ed599d 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -995,7 +995,6 @@ where let tess_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "TessCoord"); let tile_origin_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileOrigin"); let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop"); - let object_attr = device.get_vertex_attr(&alpha_tile_program.program, "Object"); let tile_index_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileIndex"); let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "ColorTexCoord"); @@ -1030,14 +1029,6 @@ where offset: 3, divisor: 1, }); - device.configure_vertex_attr(&object_attr, &VertexAttrDescriptor { - size: 1, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::I16, - stride: MASK_TILE_INSTANCE_SIZE, - offset: 4, - divisor: 1, - }); device.configure_vertex_attr(&tile_index_attr, &VertexAttrDescriptor { size: 1, class: VertexAttrClass::Int, @@ -1080,7 +1071,6 @@ where let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord"); let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin"); - let object_attr = device.get_vertex_attr(&solid_tile_program.program, "Object"); let color_tex_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "ColorTexCoord"); @@ -1114,14 +1104,6 @@ where offset: 4, divisor: 1, }); - device.configure_vertex_attr(&object_attr, &VertexAttrDescriptor { - size: 1, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::I16, - stride: SOLID_TILE_INSTANCE_SIZE, - offset: 8, - divisor: 1, - }); SolidTileVertexArray { vertex_array, vertex_buffer } } diff --git a/resources/shaders/tile_alpha_vertex.inc.glsl b/resources/shaders/tile_alpha_vertex.inc.glsl index 9a13b146..426b2731 100644 --- a/resources/shaders/tile_alpha_vertex.inc.glsl +++ b/resources/shaders/tile_alpha_vertex.inc.glsl @@ -16,7 +16,6 @@ uniform vec2 uViewBoxOrigin; in vec2 aTessCoord; in uvec3 aTileOrigin; in int aBackdrop; -in uint aObject; in uint aTileIndex; out vec2 vTexCoord; diff --git a/resources/shaders/tile_solid_vertex.inc.glsl b/resources/shaders/tile_solid_vertex.inc.glsl index 04aa3109..a7932c94 100644 --- a/resources/shaders/tile_solid_vertex.inc.glsl +++ b/resources/shaders/tile_solid_vertex.inc.glsl @@ -14,7 +14,6 @@ uniform vec2 uViewBoxOrigin; in vec2 aTessCoord; in vec2 aTileOrigin; -in uint aObject; out vec4 vColor; From 0deb12b3a22194e8d09f0b72809095250a5c9786 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 14 May 2019 18:09:01 -0700 Subject: [PATCH 14/28] Implement `fill-opacity` and `stroke-opacity` in SVG --- renderer/src/builder.rs | 9 ++++++++- renderer/src/paint.rs | 17 ++++++++++++++++- renderer/src/scene.rs | 9 +-------- renderer/src/tiles.rs | 23 ++++++++++++++++------- svg/src/lib.rs | 28 +++++++++++++++++----------- 5 files changed, 58 insertions(+), 28 deletions(-) diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index dd95ea46..15ac1dbe 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -82,8 +82,15 @@ impl<'a> SceneBuilder<'a> { let path_object = &scene.paths[path_index]; let outline = scene.apply_render_options(path_object.outline(), built_options); let paint_id = path_object.paint(); + let object_is_opaque = scene.paints[paint_id.0 as usize].is_opaque(); + + let mut tiler = Tiler::new(self, + &outline, + view_box, + path_index as u16, + paint_id, + object_is_opaque); - let mut tiler = Tiler::new(self, &outline, view_box, paint_id, path_index as u16); tiler.generate_tiles(); self.listener.send(RenderCommand::AddFills(tiler.built_object.fills)); diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs index 9777e5b8..be48ce88 100644 --- a/renderer/src/paint.rs +++ b/renderer/src/paint.rs @@ -9,12 +9,27 @@ // except according to those terms. use crate::gpu_data::PaintData; -use crate::scene::{PaintId, Scene}; +use crate::scene::Scene; use pathfinder_geometry::basic::point::Point2DI32; +use pathfinder_geometry::color::ColorU; const PAINT_TEXTURE_WIDTH: i32 = 256; const PAINT_TEXTURE_HEIGHT: i32 = 256; +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct Paint { + pub color: ColorU, +} + +#[derive(Clone, Copy, PartialEq, Debug)] +pub struct PaintId(pub u16); + +impl Paint { + pub(crate) fn is_opaque(&self) -> bool { + self.color.a == 255 + } +} + impl Scene { pub fn build_paint_data(&self) -> PaintData { let size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT); diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 8497575e..64479c34 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -14,6 +14,7 @@ use crate::builder::SceneBuilder; use crate::concurrent::executor::Executor; use crate::options::{PreparedRenderOptions, PreparedRenderTransform}; use crate::options::{RenderCommandListener, RenderOptions}; +use crate::paint::{Paint, PaintId}; use hashbrown::HashMap; use pathfinder_geometry::basic::point::Point2DF32; use pathfinder_geometry::basic::rect::RectF32; @@ -222,11 +223,3 @@ impl PathObject { self.paint } } - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct Paint { - pub color: ColorU, -} - -#[derive(Clone, Copy, PartialEq, Debug)] -pub struct PaintId(pub u16); diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index cfceb05f..fb2c3eaf 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -10,8 +10,7 @@ use crate::builder::SceneBuilder; use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive}; -use crate::paint; -use crate::scene::PaintId; +use crate::paint::{self, PaintId}; use crate::sorted_vector::SortedVector; use pathfinder_geometry::basic::line_segment::LineSegmentF32; use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; @@ -33,6 +32,7 @@ pub(crate) struct Tiler<'a> { pub built_object: BuiltObject, paint_id: PaintId, object_index: u16, + object_is_opaque: bool, point_queue: SortedVector, active_edges: SortedVector, @@ -45,8 +45,9 @@ impl<'a> Tiler<'a> { builder: &'a SceneBuilder<'a>, outline: &'a Outline, view_box: RectF32, - paint_id: PaintId, object_index: u16, + paint_id: PaintId, + object_is_opaque: bool, ) -> Tiler<'a> { let bounds = outline .bounds() @@ -58,8 +59,9 @@ impl<'a> Tiler<'a> { builder, outline, built_object, - paint_id, object_index, + paint_id, + object_is_opaque, point_queue: SortedVector::new(), active_edges: SortedVector::new(), @@ -112,11 +114,18 @@ impl<'a> Tiler<'a> { let tile_coords = self .built_object .local_tile_index_to_coords(tile_index as u32); + if tile.is_solid() { - if tile.backdrop != 0 { - self.builder.z_buffer.update(tile_coords, self.object_index); + // Blank tiles are always skipped. + if tile.backdrop == 0 { + continue; + } + + // If this is a solid tile, poke it into the Z-buffer and stop here. + if self.object_is_opaque { + self.builder.z_buffer.update(tile_coords, self.object_index); + continue; } - continue; } let origin_uv = paint::paint_id_to_tex_coords(self.paint_id); diff --git a/svg/src/lib.rs b/svg/src/lib.rs index 249bb8fe..bb8b89b6 100644 --- a/svg/src/lib.rs +++ b/svg/src/lib.rs @@ -21,10 +21,11 @@ use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::Outline; use pathfinder_geometry::segment::{Segment, SegmentFlags}; use pathfinder_geometry::stroke::OutlineStrokeToFill; -use pathfinder_renderer::scene::{Paint, PathObject, Scene}; +use pathfinder_renderer::paint::Paint; +use pathfinder_renderer::scene::{PathObject, Scene}; use std::fmt::{Display, Formatter, Result as FormatResult}; use std::mem; -use usvg::{Color as SvgColor, Node, NodeExt, NodeKind, Paint as UsvgPaint}; +use usvg::{Color as SvgColor, Node, NodeExt, NodeKind, Opacity, Paint as UsvgPaint}; use usvg::{PathSegment as UsvgPathSegment, Rect as UsvgRect, Transform as UsvgTransform}; use usvg::{Tree, Visibility}; @@ -114,9 +115,11 @@ impl BuiltSVG { } NodeKind::Path(ref path) if path.visibility == Visibility::Visible => { if let Some(ref fill) = path.fill { - let style = self - .scene - .push_paint(&Paint::from_svg_paint(&fill.paint, &mut self.result_flags)); + let style = self.scene.push_paint(&Paint::from_svg_paint( + &fill.paint, + fill.opacity, + &mut self.result_flags, + )); let path = UsvgPathToSegments::new(path.segments.iter().cloned()); let path = Transform2DF32PathIter::new(path, &transform); @@ -129,6 +132,7 @@ impl BuiltSVG { if let Some(ref stroke) = path.stroke { let style = self.scene.push_paint(&Paint::from_svg_paint( &stroke.paint, + stroke.opacity, &mut self.result_flags, )); let stroke_width = f32::max(stroke.width.value() as f32, HAIRLINE_STROKE_WIDTH); @@ -235,15 +239,17 @@ impl Display for BuildResultFlags { } trait PaintExt { - fn from_svg_paint(svg_paint: &UsvgPaint, result_flags: &mut BuildResultFlags) -> Self; + fn from_svg_paint(svg_paint: &UsvgPaint, opacity: Opacity, result_flags: &mut BuildResultFlags) + -> Self; } impl PaintExt for Paint { #[inline] - fn from_svg_paint(svg_paint: &UsvgPaint, result_flags: &mut BuildResultFlags) -> Paint { + fn from_svg_paint(svg_paint: &UsvgPaint, opacity: Opacity, result_flags: &mut BuildResultFlags) + -> Paint { Paint { color: match *svg_paint { - UsvgPaint::Color(color) => ColorU::from_svg_color(color), + UsvgPaint::Color(color) => ColorU::from_svg_color(color, opacity), UsvgPaint::Link(_) => { // TODO(pcwalton) result_flags.insert(BuildResultFlags::UNSUPPORTED_LINK_PAINT); @@ -358,17 +364,17 @@ where } trait ColorUExt { - fn from_svg_color(svg_color: SvgColor) -> Self; + fn from_svg_color(svg_color: SvgColor, opacity: Opacity) -> Self; } impl ColorUExt for ColorU { #[inline] - fn from_svg_color(svg_color: SvgColor) -> ColorU { + fn from_svg_color(svg_color: SvgColor, opacity: Opacity) -> ColorU { ColorU { r: svg_color.red, g: svg_color.green, b: svg_color.blue, - a: 255, + a: (opacity.value() * 255.0).round() as u8, } } } From 6eab3fa2d84bee5d25200a3a6ada44e6dd448271 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 14 May 2019 18:26:10 -0700 Subject: [PATCH 15/28] Implement `globalAlpha` for canvas --- canvas/src/lib.rs | 31 ++++++++++++++++++++++++++++--- examples/canvas_moire/src/main.rs | 1 + text/src/lib.rs | 3 ++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 300e6049..fab53053 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -20,7 +20,8 @@ use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::{Contour, Outline}; use pathfinder_geometry::stroke::OutlineStrokeToFill; -use pathfinder_renderer::scene::{Paint, PathObject, Scene}; +use pathfinder_renderer::paint::Paint; +use pathfinder_renderer::scene::{PathObject, Scene}; use pathfinder_text::{SceneExt, TextRenderMode}; use skribo::{FontCollection, FontFamily, TextStyle}; use std::default::Default; @@ -149,13 +150,18 @@ impl CanvasRenderingContext2D { pub fn fill_path(&mut self, path: Path2D) { let mut outline = path.into_outline(); outline.transform(&self.current_state.transform); - let paint_id = self.scene.push_paint(&self.current_state.fill_paint); + + let paint = self.current_state.resolve_paint(self.current_state.fill_paint); + let paint_id = self.scene.push_paint(&paint); + self.scene.push_path(PathObject::new(outline, paint_id, String::new())) } #[inline] pub fn stroke_path(&mut self, path: Path2D) { - let paint_id = self.scene.push_paint(&self.current_state.stroke_paint); + let paint = self.current_state.resolve_paint(self.current_state.stroke_paint); + let paint_id = self.scene.push_paint(&paint); + let stroke_width = f32::max(self.current_state.line_width, HAIRLINE_STROKE_WIDTH); let mut stroke_to_fill = OutlineStrokeToFill::new(path.into_outline(), stroke_width); stroke_to_fill.offset(); @@ -180,6 +186,18 @@ impl CanvasRenderingContext2D { self.current_state.transform = Transform2DF32::default(); } + // Compositing + + #[inline] + pub fn global_alpha(&self) -> f32 { + self.current_state.global_alpha + } + + #[inline] + pub fn set_global_alpha(&mut self, new_global_alpha: f32) { + self.current_state.global_alpha = new_global_alpha; + } + // The canvas state #[inline] @@ -203,6 +221,7 @@ pub struct State { fill_paint: Paint, stroke_paint: Paint, line_width: f32, + global_alpha: f32, } impl State { @@ -214,8 +233,14 @@ impl State { fill_paint: Paint { color: ColorU::black() }, stroke_paint: Paint { color: ColorU::black() }, line_width: 1.0, + global_alpha: 1.0, } } + + fn resolve_paint(&self, mut paint: Paint) -> Paint { + paint.color.a = (paint.color.a as f32 * self.global_alpha).round() as u8; + paint + } } #[derive(Clone)] diff --git a/examples/canvas_moire/src/main.rs b/examples/canvas_moire/src/main.rs index f5f2c0d5..2d0152d2 100644 --- a/examples/canvas_moire/src/main.rs +++ b/examples/canvas_moire/src/main.rs @@ -131,6 +131,7 @@ impl MoireRenderer { let mut canvas = CanvasRenderingContext2D::new(self.drawable_size.to_f32()); canvas.set_line_width(CIRCLE_THICKNESS * self.device_pixel_ratio); canvas.set_stroke_style(FillStyle::Color(foreground_color.to_u8())); + canvas.set_global_alpha(0.75); // Draw circles. self.draw_circles(&mut canvas, outer_center); diff --git a/text/src/lib.rs b/text/src/lib.rs index f3dd8f23..7b81ef2f 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -17,7 +17,8 @@ use pathfinder_geometry::basic::point::Point2DF32; use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::outline::{Contour, Outline}; use pathfinder_geometry::stroke::OutlineStrokeToFill; -use pathfinder_renderer::scene::{PaintId, PathObject, Scene}; +use pathfinder_renderer::paint::PaintId; +use pathfinder_renderer::scene::{PathObject, Scene}; use skribo::{FontCollection, Layout, TextStyle}; use std::mem; From 1b9cfa98a9ee7b405974f98c56e4ad5142f5c2a4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 16 May 2019 08:34:52 -0700 Subject: [PATCH 16/28] Stroke closed paths properly --- geometry/src/stroke.rs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index 0420b601..f9901434 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -34,17 +34,28 @@ impl OutlineStrokeToFill { #[inline] pub fn offset(&mut self) { - let mut new_bounds = None; - for contour in &mut self.outline.contours { - let input = mem::replace(contour, Contour::new()); - let mut contour_stroke_to_fill = - ContourStrokeToFill::new(input, Contour::new(), self.stroke_width * 0.5); - contour_stroke_to_fill.offset_forward(); - contour_stroke_to_fill.offset_backward(); - *contour = contour_stroke_to_fill.output; - contour.update_bounds(&mut new_bounds); + let mut new_contours = vec![]; + for input in mem::replace(&mut self.outline.contours, vec![]) { + let mut stroker = ContourStrokeToFill::new(input, + Contour::new(), + self.stroke_width * 0.5); + stroker.offset_forward(); + stroker.output.closed = stroker.input.closed; + if stroker.input.closed { + new_contours.push(stroker.output); + stroker = ContourStrokeToFill::new(stroker.input, + Contour::new(), + self.stroke_width * 0.5); + } + stroker.offset_backward(); + stroker.output.closed = stroker.input.closed; + new_contours.push(stroker.output); } + let mut new_bounds = None; + new_contours.iter().for_each(|contour| contour.update_bounds(&mut new_bounds)); + + self.outline.contours = new_contours; self.outline.bounds = new_bounds.unwrap_or_else(|| RectF32::default()); } } @@ -72,7 +83,6 @@ impl ContourStrokeToFill { } fn offset_backward(&mut self) { - // FIXME(pcwalton) let mut segments: Vec<_> = self .input .iter() From 272b63a017609cd92a46e8c132dc0f86ff38fe7b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 16 May 2019 10:43:43 -0700 Subject: [PATCH 17/28] Implement square line caps --- canvas/src/lib.rs | 21 ++++++++---- geometry/src/outline.rs | 5 +++ geometry/src/stroke.rs | 73 ++++++++++++++++++++++++++++++++++------- svg/src/lib.rs | 34 +++++++++++++++---- text/src/lib.rs | 8 ++--- 5 files changed, 112 insertions(+), 29 deletions(-) diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index fab53053..a4c2bfdf 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -19,7 +19,7 @@ use pathfinder_geometry::basic::rect::RectF32; use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::{Contour, Outline}; -use pathfinder_geometry::stroke::OutlineStrokeToFill; +use pathfinder_geometry::stroke::{LineCap, OutlineStrokeToFill, StrokeStyle}; use pathfinder_renderer::paint::Paint; use pathfinder_renderer::scene::{PathObject, Scene}; use pathfinder_text::{SceneExt, TextRenderMode}; @@ -115,7 +115,7 @@ impl CanvasRenderingContext2D { &TextStyle { size: self.current_state.font_size }, &self.current_state.font_collection, &transform, - TextRenderMode::Stroke(self.current_state.line_width), + TextRenderMode::Stroke(self.current_state.stroke_style), HintingOptions::None, paint_id)); } @@ -124,7 +124,12 @@ impl CanvasRenderingContext2D { #[inline] pub fn set_line_width(&mut self, new_line_width: f32) { - self.current_state.line_width = new_line_width + self.current_state.stroke_style.line_width = new_line_width + } + + #[inline] + pub fn set_line_cap(&mut self, new_line_cap: LineCap) { + self.current_state.stroke_style.line_cap = new_line_cap } #[inline] @@ -162,8 +167,10 @@ impl CanvasRenderingContext2D { let paint = self.current_state.resolve_paint(self.current_state.stroke_paint); let paint_id = self.scene.push_paint(&paint); - let stroke_width = f32::max(self.current_state.line_width, HAIRLINE_STROKE_WIDTH); - let mut stroke_to_fill = OutlineStrokeToFill::new(path.into_outline(), stroke_width); + let mut stroke_style = self.current_state.stroke_style; + stroke_style.line_width = f32::max(stroke_style.line_width, HAIRLINE_STROKE_WIDTH); + + let mut stroke_to_fill = OutlineStrokeToFill::new(path.into_outline(), stroke_style); stroke_to_fill.offset(); stroke_to_fill.outline.transform(&self.current_state.transform); self.scene.push_path(PathObject::new(stroke_to_fill.outline, paint_id, String::new())) @@ -220,7 +227,7 @@ pub struct State { font_size: f32, fill_paint: Paint, stroke_paint: Paint, - line_width: f32, + stroke_style: StrokeStyle, global_alpha: f32, } @@ -232,7 +239,7 @@ impl State { font_size: DEFAULT_FONT_SIZE, fill_paint: Paint { color: ColorU::black() }, stroke_paint: Paint { color: ColorU::black() }, - line_width: 1.0, + stroke_style: StrokeStyle::default(), global_alpha: 1.0, } } diff --git a/geometry/src/outline.rs b/geometry/src/outline.rs index 241fd3d5..72bcb5cb 100644 --- a/geometry/src/outline.rs +++ b/geometry/src/outline.rs @@ -267,6 +267,11 @@ impl Contour { self.points[index as usize] } + #[inline] + pub(crate) fn position_of_last(&self, index: u32) -> Point2DF32 { + self.points[self.points.len() - index as usize] + } + #[inline] pub(crate) fn last_position(&self) -> Option { self.points.last().cloned() diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index f9901434..21e5462c 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -11,6 +11,7 @@ //! Utilities for converting path strokes to fills. use crate::basic::line_segment::LineSegmentF32; +use crate::basic::point::Point2DF32; use crate::basic::rect::RectF32; use crate::outline::{Contour, Outline}; use crate::segment::Segment; @@ -20,35 +21,52 @@ const TOLERANCE: f32 = 0.01; pub struct OutlineStrokeToFill { pub outline: Outline, - pub stroke_width: f32, + pub style: StrokeStyle, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct StrokeStyle { + pub line_width: f32, + pub line_cap: LineCap, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum LineCap { + Butt, + Square, } impl OutlineStrokeToFill { #[inline] - pub fn new(outline: Outline, stroke_width: f32) -> OutlineStrokeToFill { - OutlineStrokeToFill { - outline, - stroke_width, - } + pub fn new(outline: Outline, style: StrokeStyle) -> OutlineStrokeToFill { + OutlineStrokeToFill { outline, style } } - #[inline] pub fn offset(&mut self) { let mut new_contours = vec![]; for input in mem::replace(&mut self.outline.contours, vec![]) { + let closed = input.closed; let mut stroker = ContourStrokeToFill::new(input, Contour::new(), - self.stroke_width * 0.5); + self.style.line_width * 0.5); + stroker.offset_forward(); - stroker.output.closed = stroker.input.closed; - if stroker.input.closed { + if closed { + stroker.output.closed = true; new_contours.push(stroker.output); stroker = ContourStrokeToFill::new(stroker.input, Contour::new(), - self.stroke_width * 0.5); + self.style.line_width * 0.5); + } else { + self.add_cap(&mut stroker.output); } + stroker.offset_backward(); - stroker.output.closed = stroker.input.closed; + if !closed { + self.add_cap(&mut stroker.output); + } + + stroker.output.closed = true; new_contours.push(stroker.output); } @@ -58,6 +76,25 @@ impl OutlineStrokeToFill { self.outline.contours = new_contours; self.outline.bounds = new_bounds.unwrap_or_else(|| RectF32::default()); } + + pub fn add_cap(&mut self, contour: &mut Contour) { + if self.style.line_cap == LineCap::Butt || contour.len() < 2 { + return + } + + let width = self.style.line_width; + let (p0, p1) = (contour.position_of_last(2), contour.position_of_last(1)); + let gradient = (p1 - p0).normalize(); + let offset = gradient.scale(width * 0.5); + + let p2 = p1 + offset; + let p3 = p2 + gradient.yx().scale_xy(Point2DF32::new(width, -width)); + let p4 = p3 - offset; + + contour.push_endpoint(p2); + contour.push_endpoint(p3); + contour.push_endpoint(p4); + } } struct ContourStrokeToFill { @@ -219,3 +256,15 @@ impl Offset for Segment { const SAMPLE_COUNT: u32 = 16; } } + +impl Default for StrokeStyle { + #[inline] + fn default() -> StrokeStyle { + StrokeStyle { line_width: 1.0, line_cap: LineCap::default() } + } +} + +impl Default for LineCap { + #[inline] + fn default() -> LineCap { LineCap::Butt } +} diff --git a/svg/src/lib.rs b/svg/src/lib.rs index bb8b89b6..96042555 100644 --- a/svg/src/lib.rs +++ b/svg/src/lib.rs @@ -20,14 +20,14 @@ use pathfinder_geometry::basic::transform2d::{Transform2DF32, Transform2DF32Path use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::Outline; use pathfinder_geometry::segment::{Segment, SegmentFlags}; -use pathfinder_geometry::stroke::OutlineStrokeToFill; +use pathfinder_geometry::stroke::{LineCap, OutlineStrokeToFill, StrokeStyle}; use pathfinder_renderer::paint::Paint; use pathfinder_renderer::scene::{PathObject, Scene}; use std::fmt::{Display, Formatter, Result as FormatResult}; use std::mem; -use usvg::{Color as SvgColor, Node, NodeExt, NodeKind, Opacity, Paint as UsvgPaint}; -use usvg::{PathSegment as UsvgPathSegment, Rect as UsvgRect, Transform as UsvgTransform}; -use usvg::{Tree, Visibility}; +use usvg::{Color as SvgColor, LineCap as UsvgLineCap, Node, NodeExt, NodeKind, Opacity}; +use usvg::{Paint as UsvgPaint, PathSegment as UsvgPathSegment, Rect as UsvgRect}; +use usvg::{Transform as UsvgTransform, Tree, Visibility}; const HAIRLINE_STROKE_WIDTH: f32 = 0.0333; @@ -135,12 +135,16 @@ impl BuiltSVG { stroke.opacity, &mut self.result_flags, )); - let stroke_width = f32::max(stroke.width.value() as f32, HAIRLINE_STROKE_WIDTH); + + let stroke_style = StrokeStyle { + line_width: f32::max(stroke.width.value() as f32, HAIRLINE_STROKE_WIDTH), + line_cap: LineCap::from_usvg_line_cap(stroke.linecap), + }; let path = UsvgPathToSegments::new(path.segments.iter().cloned()); let outline = Outline::from_segments(path); - let mut stroke_to_fill = OutlineStrokeToFill::new(outline, stroke_width); + let mut stroke_to_fill = OutlineStrokeToFill::new(outline, stroke_style); stroke_to_fill.offset(); let mut outline = stroke_to_fill.outline; outline.transform(&transform); @@ -378,3 +382,21 @@ impl ColorUExt for ColorU { } } } + +trait LineCapExt { + fn from_usvg_line_cap(usvg_line_cap: UsvgLineCap) -> Self; +} + +impl LineCapExt for LineCap { + #[inline] + fn from_usvg_line_cap(usvg_line_cap: UsvgLineCap) -> LineCap { + match usvg_line_cap { + UsvgLineCap::Butt => LineCap::Butt, + UsvgLineCap::Round => { + // TODO(pcwalton) + LineCap::Square + } + UsvgLineCap::Square => LineCap::Square, + } + } +} diff --git a/text/src/lib.rs b/text/src/lib.rs index 7b81ef2f..8c3d9223 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -16,7 +16,7 @@ use lyon_path::builder::{FlatPathBuilder, PathBuilder}; use pathfinder_geometry::basic::point::Point2DF32; use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::outline::{Contour, Outline}; -use pathfinder_geometry::stroke::OutlineStrokeToFill; +use pathfinder_geometry::stroke::{OutlineStrokeToFill, StrokeStyle}; use pathfinder_renderer::paint::PaintId; use pathfinder_renderer::scene::{PathObject, Scene}; use skribo::{FontCollection, Layout, TextStyle}; @@ -69,8 +69,8 @@ impl SceneExt for Scene { font.outline(glyph_id, hinting_options, &mut outline_builder)?; let mut outline = outline_builder.build(); - if let TextRenderMode::Stroke(stroke_width) = render_mode { - let mut stroke_to_fill = OutlineStrokeToFill::new(outline, stroke_width); + if let TextRenderMode::Stroke(stroke_style) = render_mode { + let mut stroke_to_fill = OutlineStrokeToFill::new(outline, stroke_style); stroke_to_fill.offset(); outline = stroke_to_fill.outline; } @@ -123,7 +123,7 @@ impl SceneExt for Scene { #[derive(Clone, Copy, PartialEq, Debug)] pub enum TextRenderMode { Fill, - Stroke(f32), + Stroke(StrokeStyle), } struct OutlinePathBuilder { From e282eb57d51ff293264ee4feaafe56e1e43ebd04 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 16 May 2019 11:10:15 -0700 Subject: [PATCH 18/28] Implement interior miter line joins (not yet endpoints) --- canvas/src/lib.rs | 7 +++- geometry/src/stroke.rs | 80 ++++++++++++++++++++++++++++++++---------- svg/src/lib.rs | 27 +++++++++++--- 3 files changed, 91 insertions(+), 23 deletions(-) diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index a4c2bfdf..01435f77 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -19,7 +19,7 @@ use pathfinder_geometry::basic::rect::RectF32; use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::{Contour, Outline}; -use pathfinder_geometry::stroke::{LineCap, OutlineStrokeToFill, StrokeStyle}; +use pathfinder_geometry::stroke::{LineCap, LineJoin, OutlineStrokeToFill, StrokeStyle}; use pathfinder_renderer::paint::Paint; use pathfinder_renderer::scene::{PathObject, Scene}; use pathfinder_text::{SceneExt, TextRenderMode}; @@ -132,6 +132,11 @@ impl CanvasRenderingContext2D { self.current_state.stroke_style.line_cap = new_line_cap } + #[inline] + pub fn set_line_join(&mut self, new_line_join: LineJoin) { + self.current_state.stroke_style.line_join = new_line_join + } + #[inline] pub fn set_fill_style(&mut self, new_fill_style: FillStyle) { self.current_state.fill_paint = new_fill_style.to_paint(); diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index 21e5462c..a8caf317 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -28,6 +28,7 @@ pub struct OutlineStrokeToFill { pub struct StrokeStyle { pub line_width: f32, pub line_cap: LineCap, + pub line_join: LineJoin, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -36,6 +37,12 @@ pub enum LineCap { Square, } +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum LineJoin { + Miter, + Bevel, +} + impl OutlineStrokeToFill { #[inline] pub fn new(outline: Outline, style: StrokeStyle) -> OutlineStrokeToFill { @@ -48,21 +55,26 @@ impl OutlineStrokeToFill { let closed = input.closed; let mut stroker = ContourStrokeToFill::new(input, Contour::new(), - self.style.line_width * 0.5); + self.style.line_width * 0.5, + self.style.line_join); stroker.offset_forward(); if closed { + // TODO(pcwalton): Line join. stroker.output.closed = true; new_contours.push(stroker.output); stroker = ContourStrokeToFill::new(stroker.input, Contour::new(), - self.style.line_width * 0.5); + self.style.line_width * 0.5, + self.style.line_join); } else { self.add_cap(&mut stroker.output); } stroker.offset_backward(); - if !closed { + if closed { + // TODO(pcwalton): Line join. + } else { self.add_cap(&mut stroker.output); } @@ -101,21 +113,18 @@ struct ContourStrokeToFill { input: Contour, output: Contour, radius: f32, + join: LineJoin, } impl ContourStrokeToFill { #[inline] - fn new(input: Contour, output: Contour, radius: f32) -> ContourStrokeToFill { - ContourStrokeToFill { - input, - output, - radius, - } + fn new(input: Contour, output: Contour, radius: f32, join: LineJoin) -> ContourStrokeToFill { + ContourStrokeToFill { input, output, radius, join } } fn offset_forward(&mut self) { for segment in self.input.iter() { - segment.offset(self.radius, &mut self.output); + segment.offset(self.radius, self.join, &mut self.output); } } @@ -127,27 +136,28 @@ impl ContourStrokeToFill { .collect(); segments.reverse(); for segment in &segments { - segment.offset(self.radius, &mut self.output); + segment.offset(self.radius, self.join, &mut self.output); } } } trait Offset { - fn offset(&self, distance: f32, contour: &mut Contour); + fn offset(&self, distance: f32, join: LineJoin, contour: &mut Contour); + fn add_to_contour(&self, join: LineJoin, contour: &mut Contour); fn offset_once(&self, distance: f32) -> Self; fn error_is_within_tolerance(&self, other: &Segment, distance: f32) -> bool; } impl Offset for Segment { - fn offset(&self, distance: f32, contour: &mut Contour) { + fn offset(&self, distance: f32, join: LineJoin, contour: &mut Contour) { if self.baseline.square_length() < TOLERANCE * TOLERANCE { - contour.push_full_segment(self, true); + self.add_to_contour(join, contour); return; } let candidate = self.offset_once(distance); if self.error_is_within_tolerance(&candidate, distance) { - contour.push_full_segment(&candidate, true); + candidate.add_to_contour(join, contour); return; } @@ -155,8 +165,33 @@ impl Offset for Segment { debug!("... PRE-SPLIT: {:?}", self); let (before, after) = self.split(0.5); debug!("... AFTER-SPLIT: {:?} {:?}", before, after); - before.offset(distance, contour); - after.offset(distance, contour); + before.offset(distance, join, contour); + after.offset(distance, join, contour); + } + + fn add_to_contour(&self, join: LineJoin, contour: &mut Contour) { + // Add join. + // TODO(pcwalton): Miter limit. + if join == LineJoin::Miter && contour.len() >= 2 { + let (p0, p1) = (contour.position_of_last(2), contour.position_of_last(1)); + let p3 = self.baseline.from(); + let p4 = if self.is_line() { + self.baseline.to() + } else { + // NB: If you change the representation of quadratic curves, you will need to + // change this. + self.ctrl.from() + }; + + let prev_tangent = LineSegmentF32::new(p0, p1); + let next_tangent = LineSegmentF32::new(p4, p3); + if let Some(prev_tangent_t) = prev_tangent.intersection_t(&next_tangent) { + contour.push_endpoint(prev_tangent.sample(prev_tangent_t)); + } + } + + // Push segment. + contour.push_full_segment(self, true); } fn offset_once(&self, distance: f32) -> Segment { @@ -260,7 +295,11 @@ impl Offset for Segment { impl Default for StrokeStyle { #[inline] fn default() -> StrokeStyle { - StrokeStyle { line_width: 1.0, line_cap: LineCap::default() } + StrokeStyle { + line_width: 1.0, + line_cap: LineCap::default(), + line_join: LineJoin::default(), + } } } @@ -268,3 +307,8 @@ impl Default for LineCap { #[inline] fn default() -> LineCap { LineCap::Butt } } + +impl Default for LineJoin { + #[inline] + fn default() -> LineJoin { LineJoin::Miter } +} diff --git a/svg/src/lib.rs b/svg/src/lib.rs index 96042555..34e739a6 100644 --- a/svg/src/lib.rs +++ b/svg/src/lib.rs @@ -20,14 +20,14 @@ use pathfinder_geometry::basic::transform2d::{Transform2DF32, Transform2DF32Path use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::Outline; use pathfinder_geometry::segment::{Segment, SegmentFlags}; -use pathfinder_geometry::stroke::{LineCap, OutlineStrokeToFill, StrokeStyle}; +use pathfinder_geometry::stroke::{LineCap, LineJoin, OutlineStrokeToFill, StrokeStyle}; use pathfinder_renderer::paint::Paint; use pathfinder_renderer::scene::{PathObject, Scene}; use std::fmt::{Display, Formatter, Result as FormatResult}; use std::mem; -use usvg::{Color as SvgColor, LineCap as UsvgLineCap, Node, NodeExt, NodeKind, Opacity}; -use usvg::{Paint as UsvgPaint, PathSegment as UsvgPathSegment, Rect as UsvgRect}; -use usvg::{Transform as UsvgTransform, Tree, Visibility}; +use usvg::{Color as SvgColor, LineCap as UsvgLineCap, LineJoin as UsvgLineJoin, Node, NodeExt}; +use usvg::{NodeKind, Opacity, Paint as UsvgPaint, PathSegment as UsvgPathSegment}; +use usvg::{Rect as UsvgRect, Transform as UsvgTransform, Tree, Visibility}; const HAIRLINE_STROKE_WIDTH: f32 = 0.0333; @@ -139,6 +139,7 @@ impl BuiltSVG { let stroke_style = StrokeStyle { line_width: f32::max(stroke.width.value() as f32, HAIRLINE_STROKE_WIDTH), line_cap: LineCap::from_usvg_line_cap(stroke.linecap), + line_join: LineJoin::from_usvg_line_join(stroke.linejoin), }; let path = UsvgPathToSegments::new(path.segments.iter().cloned()); @@ -400,3 +401,21 @@ impl LineCapExt for LineCap { } } } + +trait LineJoinExt { + fn from_usvg_line_join(usvg_line_join: UsvgLineJoin) -> Self; +} + +impl LineJoinExt for LineJoin { + #[inline] + fn from_usvg_line_join(usvg_line_join: UsvgLineJoin) -> LineJoin { + match usvg_line_join { + UsvgLineJoin::Miter => LineJoin::Miter, + UsvgLineJoin::Round => { + // TODO(pcwalton) + LineJoin::Miter + } + UsvgLineJoin::Bevel => LineJoin::Bevel, + } + } +} From cba5444f036128e7f6a775567b7ad5d049621efb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 16 May 2019 12:47:18 -0700 Subject: [PATCH 19/28] Add miter joins at endpoints --- geometry/src/stroke.rs | 51 +++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index a8caf317..8b0d9f4b 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -60,9 +60,7 @@ impl OutlineStrokeToFill { stroker.offset_forward(); if closed { - // TODO(pcwalton): Line join. - stroker.output.closed = true; - new_contours.push(stroker.output); + self.push_stroked_contour(&mut new_contours, stroker.output, true); stroker = ContourStrokeToFill::new(stroker.input, Contour::new(), self.style.line_width * 0.5, @@ -78,8 +76,7 @@ impl OutlineStrokeToFill { self.add_cap(&mut stroker.output); } - stroker.output.closed = true; - new_contours.push(stroker.output); + self.push_stroked_contour(&mut new_contours, stroker.output, closed); } let mut new_bounds = None; @@ -89,7 +86,21 @@ impl OutlineStrokeToFill { self.outline.bounds = new_bounds.unwrap_or_else(|| RectF32::default()); } - pub fn add_cap(&mut self, contour: &mut Contour) { + fn push_stroked_contour(&mut self, + new_contours: &mut Vec, + mut contour: Contour, + closed: bool) { + // Add join if necessary. + if closed && contour.needs_join(self.style.line_join) { + let (p1, p0) = (contour.position_of(1), contour.position_of(0)); + contour.add_join(self.style.line_join, &LineSegmentF32::new(p0, p1)); + } + + contour.closed = true; + new_contours.push(contour); + } + + fn add_cap(&mut self, contour: &mut Contour) { if self.style.line_cap == LineCap::Butt || contour.len() < 2 { return } @@ -170,10 +181,8 @@ impl Offset for Segment { } fn add_to_contour(&self, join: LineJoin, contour: &mut Contour) { - // Add join. - // TODO(pcwalton): Miter limit. - if join == LineJoin::Miter && contour.len() >= 2 { - let (p0, p1) = (contour.position_of_last(2), contour.position_of_last(1)); + // Add join if necessary. + if contour.needs_join(join) { let p3 = self.baseline.from(); let p4 = if self.is_line() { self.baseline.to() @@ -183,11 +192,7 @@ impl Offset for Segment { self.ctrl.from() }; - let prev_tangent = LineSegmentF32::new(p0, p1); - let next_tangent = LineSegmentF32::new(p4, p3); - if let Some(prev_tangent_t) = prev_tangent.intersection_t(&next_tangent) { - contour.push_endpoint(prev_tangent.sample(prev_tangent_t)); - } + contour.add_join(join, &LineSegmentF32::new(p4, p3)); } // Push segment. @@ -292,6 +297,22 @@ impl Offset for Segment { } } +impl Contour { + fn needs_join(&self, join: LineJoin) -> bool { + // TODO(pcwalton): Miter limit. + join == LineJoin::Miter && self.len() >= 2 + } + + fn add_join(&mut self, _: LineJoin, next_tangent: &LineSegmentF32) { + // TODO(pcwalton): Round joins. + let (p0, p1) = (self.position_of_last(2), self.position_of_last(1)); + let prev_tangent = LineSegmentF32::new(p0, p1); + if let Some(prev_tangent_t) = prev_tangent.intersection_t(&next_tangent) { + self.push_endpoint(prev_tangent.sample(prev_tangent_t)); + } + } +} + impl Default for StrokeStyle { #[inline] fn default() -> StrokeStyle { From c6fc85357976eb4c88ffd6bbef69ff7b1c13bcf7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 21 May 2019 14:49:01 -0700 Subject: [PATCH 20/28] Don't miter join on stroke endpoints. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the Moiré demo. --- geometry/src/stroke.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index 8b0d9f4b..02d6a282 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -134,8 +134,9 @@ impl ContourStrokeToFill { } fn offset_forward(&mut self) { - for segment in self.input.iter() { - segment.offset(self.radius, self.join, &mut self.output); + for (segment_index, segment) in self.input.iter().enumerate() { + let join = if segment_index == 0 { LineJoin::Bevel } else { self.join }; + segment.offset(self.radius, join, &mut self.output); } } @@ -146,8 +147,9 @@ impl ContourStrokeToFill { .map(|segment| segment.reversed()) .collect(); segments.reverse(); - for segment in &segments { - segment.offset(self.radius, self.join, &mut self.output); + for (segment_index, segment) in segments.iter().enumerate() { + let join = if segment_index == 0 { LineJoin::Bevel } else { self.join }; + segment.offset(self.radius, join, &mut self.output); } } } From 197f01d56a8da02283073bb7dd5a0a46ed2ab1f5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 21 May 2019 14:50:35 -0700 Subject: [PATCH 21/28] Write in the line segment intersection code in matrix form --- geometry/src/basic/line_segment.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/geometry/src/basic/line_segment.rs b/geometry/src/basic/line_segment.rs index 9976fd38..88c60c17 100644 --- a/geometry/src/basic/line_segment.rs +++ b/geometry/src/basic/line_segment.rs @@ -11,6 +11,7 @@ //! Line segment types, optimized with SIMD. use crate::basic::point::Point2DF32; +use crate::basic::transform2d::Matrix2x2F32; use crate::util; use pathfinder_simd::default::F32x4; use std::ops::{Add, Sub}; @@ -227,15 +228,12 @@ impl LineSegmentF32 { // http://www.cs.swan.ac.uk/~cssimon/line_intersection.html pub fn intersection_t(&self, other: &LineSegmentF32) -> Option { - let d0d1 = self.vector().0.concat_xy_xy(other.vector().0); - let offset = other.from() - self.from(); - let factors = d0d1.concat_wz_yx(offset.0); - let terms = d0d1 * factors; - let denom = terms[0] - terms[1]; - if f32::abs(denom) < EPSILON { + let p0p1 = self.vector(); + let matrix = Matrix2x2F32(other.vector().0.concat_xy_xy((-p0p1).0)); + if f32::abs(matrix.det()) < EPSILON { return None; } - return Some((terms[3] - terms[2]) / denom); + return Some(matrix.inverse().transform_point(self.from() - other.from()).y()); const EPSILON: f32 = 0.0001; } From 2131724a2a7213e4ae7958f5da19a4a10924c8fe Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 21 May 2019 20:21:46 -0700 Subject: [PATCH 22/28] Implement round line caps --- geometry/src/outline.rs | 18 +++++++++++++++--- geometry/src/stroke.rs | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/geometry/src/outline.rs b/geometry/src/outline.rs index 72bcb5cb..75c1cb1f 100644 --- a/geometry/src/outline.rs +++ b/geometry/src/outline.rs @@ -19,10 +19,12 @@ use crate::clip::{self, ContourPolygonClipper, ContourRectClipper}; use crate::dilation::ContourDilator; use crate::orientation::Orientation; use crate::segment::{Segment, SegmentFlags, SegmentKind}; -use std::f32::consts::FRAC_PI_2; +use std::f32::consts::{FRAC_PI_2, PI}; use std::fmt::{self, Debug, Formatter}; use std::mem; +const TWO_PI: f32 = PI * 2.0; + #[derive(Clone)] pub struct Outline { pub(crate) contours: Vec, @@ -367,7 +369,17 @@ impl Contour { self.push_point(segment.baseline.to(), PointFlags::empty(), update_bounds); } - pub fn push_arc(&mut self, center: Point2DF32, radius: f32, start_angle: f32, end_angle: f32) { + pub fn push_arc(&mut self, + center: Point2DF32, + radius: f32, + mut start_angle: f32, + mut end_angle: f32) { + start_angle %= TWO_PI; + end_angle %= TWO_PI; + if end_angle < start_angle { + end_angle += TWO_PI; + } + let scale = Transform2DF32::from_scale(Point2DF32::splat(radius)); let translation = Transform2DF32::from_translation(center); @@ -375,7 +387,7 @@ impl Contour { while angle < end_angle { let sweep_angle = f32::min(FRAC_PI_2, end_angle - angle); let mut segment = Segment::arc(sweep_angle); - let rotation = Transform2DF32::from_rotation(angle); + let rotation = Transform2DF32::from_rotation(sweep_angle * 0.5 + angle); segment = segment.transform(&scale.post_mul(&rotation).post_mul(&translation)); debug!("angle={} start_angle={} end_angle={} sweep_angle={} segment={:?}", diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index 02d6a282..75e51019 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -15,6 +15,8 @@ use crate::basic::point::Point2DF32; use crate::basic::rect::RectF32; use crate::outline::{Contour, Outline}; use crate::segment::Segment; +use std::f32::consts::FRAC_PI_2; +use std::f32; use std::mem; const TOLERANCE: f32 = 0.01; @@ -35,6 +37,7 @@ pub struct StrokeStyle { pub enum LineCap { Butt, Square, + Round, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -70,9 +73,7 @@ impl OutlineStrokeToFill { } stroker.offset_backward(); - if closed { - // TODO(pcwalton): Line join. - } else { + if !closed { self.add_cap(&mut stroker.output); } @@ -108,15 +109,27 @@ impl OutlineStrokeToFill { let width = self.style.line_width; let (p0, p1) = (contour.position_of_last(2), contour.position_of_last(1)); let gradient = (p1 - p0).normalize(); - let offset = gradient.scale(width * 0.5); - let p2 = p1 + offset; - let p3 = p2 + gradient.yx().scale_xy(Point2DF32::new(width, -width)); - let p4 = p3 - offset; + match self.style.line_cap { + LineCap::Butt => unreachable!(), + LineCap::Square => { + let offset = gradient.scale(width * 0.5); - contour.push_endpoint(p2); - contour.push_endpoint(p3); - contour.push_endpoint(p4); + let p2 = p1 + offset; + let p3 = p2 + gradient.yx().scale_xy(Point2DF32::new(-width, width)); + let p4 = p3 - offset; + + contour.push_endpoint(p2); + contour.push_endpoint(p3); + contour.push_endpoint(p4); + } + LineCap::Round => { + // FIXME(pcwalton): Should we really be using angles here at all? + let offset = gradient.yx().scale_xy(Point2DF32::new(-width * 0.5, width * 0.5)); + let angle = f32::atan2(gradient.y(), gradient.x()); + contour.push_arc(p1 + offset, width * 0.5, angle - FRAC_PI_2, angle + FRAC_PI_2); + } + } } } @@ -135,8 +148,10 @@ impl ContourStrokeToFill { fn offset_forward(&mut self) { for (segment_index, segment) in self.input.iter().enumerate() { + // FIXME(pcwalton): We negate the radius here so that round end caps can be drawn + // clockwise. Of course, we should just implement anticlockwise arcs to begin with... let join = if segment_index == 0 { LineJoin::Bevel } else { self.join }; - segment.offset(self.radius, join, &mut self.output); + segment.offset(-self.radius, join, &mut self.output); } } @@ -148,8 +163,10 @@ impl ContourStrokeToFill { .collect(); segments.reverse(); for (segment_index, segment) in segments.iter().enumerate() { + // FIXME(pcwalton): We negate the radius here so that round end caps can be drawn + // clockwise. Of course, we should just implement anticlockwise arcs to begin with... let join = if segment_index == 0 { LineJoin::Bevel } else { self.join }; - segment.offset(self.radius, join, &mut self.output); + segment.offset(-self.radius, join, &mut self.output); } } } From cd23d62f3dbe31802c7b9b63160cf9ee4be5e611 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 21 May 2019 20:24:04 -0700 Subject: [PATCH 23/28] =?UTF-8?q?Fix=20off-by-epsilon=20error=20in=20`push?= =?UTF-8?q?=5Farc`=20that=20was=20breaking=20the=20Moir=C3=A9=20demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- geometry/src/outline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geometry/src/outline.rs b/geometry/src/outline.rs index 75c1cb1f..7c9a5eb1 100644 --- a/geometry/src/outline.rs +++ b/geometry/src/outline.rs @@ -376,7 +376,7 @@ impl Contour { mut end_angle: f32) { start_angle %= TWO_PI; end_angle %= TWO_PI; - if end_angle < start_angle { + if end_angle <= start_angle { end_angle += TWO_PI; } From 8c4f05ce399b46d34770224427f5346c9ead6812 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 23 May 2019 18:03:09 -0700 Subject: [PATCH 24/28] Initial rudimentary Lottie parsing code --- Cargo.lock | 18 ++ Cargo.toml | 2 + examples/lottie_basic/Cargo.toml | 10 + examples/lottie_basic/src/main.rs | 23 +++ lottie/Cargo.toml | 12 ++ lottie/src/lib.rs | 313 ++++++++++++++++++++++++++++++ 6 files changed, 378 insertions(+) create mode 100644 examples/lottie_basic/Cargo.toml create mode 100644 examples/lottie_basic/src/main.rs create mode 100644 lottie/Cargo.toml create mode 100644 lottie/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 04c6960e..3a3ce277 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -957,6 +957,13 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lottie_basic" +version = "0.1.0" +dependencies = [ + "pathfinder_lottie 0.1.0", +] + [[package]] name = "lyon_geom" version = "0.12.4" @@ -1256,6 +1263,14 @@ dependencies = [ "rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pathfinder_lottie" +version = "0.1.0" +dependencies = [ + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pathfinder_magicleap_demo" version = "0.1.0" @@ -1753,6 +1768,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "serde" version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" diff --git a/Cargo.toml b/Cargo.toml index 506e2089..3163c514 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,11 @@ members = [ "examples/canvas_minimal", "examples/canvas_moire", "examples/canvas_text", + "examples/lottie_basic", "geometry", "gl", "gpu", + "lottie", "renderer", "simd", "svg", diff --git a/examples/lottie_basic/Cargo.toml b/examples/lottie_basic/Cargo.toml new file mode 100644 index 00000000..82bc984a --- /dev/null +++ b/examples/lottie_basic/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "lottie_basic" +version = "0.1.0" +authors = ["Patrick Walton "] +edition = "2018" + +[dependencies] + +[dependencies.pathfinder_lottie] +path = "../../lottie" diff --git a/examples/lottie_basic/src/main.rs b/examples/lottie_basic/src/main.rs new file mode 100644 index 00000000..58eb2a18 --- /dev/null +++ b/examples/lottie_basic/src/main.rs @@ -0,0 +1,23 @@ +// pathfinder/examples/lottie_basic/src/main.rs +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Experimental example for reading Lottie animations. This is very incomplete. + +use pathfinder_lottie::Lottie; +use std::env; +use std::fs::File; +use std::io::BufReader; + +fn main() { + let path = env::args().skip(1).next().unwrap(); + let file = BufReader::new(File::open(path).unwrap()); + let lottie = Lottie::from_reader(file).unwrap(); + println!("{:#?}", lottie); +} diff --git a/lottie/Cargo.toml b/lottie/Cargo.toml new file mode 100644 index 00000000..a7b6b262 --- /dev/null +++ b/lottie/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "pathfinder_lottie" +version = "0.1.0" +authors = ["Patrick Walton "] +edition = "2018" + +[dependencies] +serde_json = "1.0" + +[dependencies.serde] +version = "1.0" +features = ["derive"] diff --git a/lottie/src/lib.rs b/lottie/src/lib.rs new file mode 100644 index 00000000..4b062cdb --- /dev/null +++ b/lottie/src/lib.rs @@ -0,0 +1,313 @@ +// pathfinder/lottie/src/lib.rs +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Experimental support for Lottie. This is very incomplete. + +use serde::{Deserialize, Serialize}; +use serde_json::Error as JSONError; +use std::io::Read; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Lottie { + #[serde(rename = "v")] + pub version: String, + #[serde(rename = "fr")] + pub frame_rate: i64, + #[serde(rename = "ip")] + pub in_point: i64, + #[serde(rename = "op")] + pub out_point: i64, + #[serde(rename = "w")] + pub width: f64, + #[serde(rename = "h")] + pub height: f64, + #[serde(rename = "ddd")] + pub three_d: i64, + pub assets: Vec, + pub layers: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Asset {} + +// FIXME(pcwalton): Using an untagged enum is a botch here. There actually is a tag: it's just an +// integer, which `serde_json` doesn't support natively. +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum Layer { + Shape { + #[serde(rename = "ddd")] + three_d: i64, + #[serde(rename = "ind")] + index: i64, + #[serde(rename = "nm")] + name: String, + #[serde(rename = "ks")] + transform: Transform, + #[serde(rename = "ao")] + auto_orient: i64, + #[serde(rename = "ip")] + in_point: i64, + #[serde(rename = "op")] + out_point: i64, + #[serde(rename = "st")] + start_time: i64, + #[serde(rename = "bm")] + blend_mode: i64, + #[serde(rename = "sr")] + stretch: i64, + #[serde(rename = "ln")] + #[serde(default)] + layer_id: Option, + shapes: Vec, + }, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Transform { + #[serde(rename = "p")] + pub position: MultidimensionalPropertyValue, + #[serde(rename = "a")] + pub anchor_point: MultidimensionalPropertyValue, + #[serde(rename = "s")] + pub scale: MultidimensionalPropertyValue, + #[serde(rename = "r")] + pub rotation: PropertyValue, + #[serde(rename = "o")] + #[serde(default)] + pub opacity: Option, + #[serde(rename = "px")] + #[serde(default)] + pub position_x: Option, + #[serde(rename = "py")] + #[serde(default)] + pub position_y: Option, + #[serde(rename = "pz")] + #[serde(default)] + pub position_z: Option, + #[serde(rename = "sk")] + #[serde(default)] + pub skew: Option, + #[serde(rename = "sa")] + #[serde(default)] + pub skew_axis: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum PropertyValue { + Value { + #[serde(rename = "k")] + value: f32, + #[serde(rename = "x")] + #[serde(default)] + expression: Option, + #[serde(rename = "ix")] + #[serde(default)] + index: Option, + }, + KeyframedValue { + #[serde(rename = "k")] + keyframes: Vec, + #[serde(rename = "x")] + #[serde(default)] + expression: Option, + #[serde(rename = "ix")] + #[serde(default)] + index: Option, + }, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct KeyframeValue { + #[serde(rename = "s")] + #[serde(default)] + pub start: Option>, + #[serde(rename = "t")] + pub time: i64, + #[serde(rename = "i")] + #[serde(default)] + pub interpolation: Option, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct Interpolation { + pub x: f32, + pub y: f32, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct OffsetInterpolation { + pub x: Vec, + pub y: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct OffsetKeyframe { + #[serde(rename = "s")] + #[serde(default)] + pub start: Option>, + #[serde(rename = "t")] + pub time: i64, + #[serde(rename = "i")] + #[serde(default)] + pub in_value: Option, + #[serde(rename = "o")] + #[serde(default)] + pub out_value: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum MultidimensionalPropertyValue { + Value { + #[serde(rename = "k")] + value: Vec, + #[serde(rename = "x")] + #[serde(default)] + expression: Option, + #[serde(rename = "ix")] + #[serde(default)] + index: Option, + }, + KeyframedValue { + #[serde(rename = "k")] + keyframes: Vec, + #[serde(rename = "x")] + #[serde(default)] + expression: Option, + #[serde(rename = "ix")] + #[serde(default)] + index: Option, + #[serde(rename = "ti")] + #[serde(default)] + in_tangent: Option, + #[serde(rename = "to")] + #[serde(default)] + out_tangent: Option, + }, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "ty")] +pub enum Shape { + #[serde(rename = "gr")] + Group { + #[serde(rename = "it")] + items: Vec, + #[serde(rename = "nm")] + name: String, + }, + #[serde(rename = "sh")] + Shape { + #[serde(rename = "ks")] + vertices: ShapeVertices, + #[serde(rename = "d")] + #[serde(default)] + direction: Option, + }, + #[serde(rename = "fl")] + Fill { + #[serde(rename = "nm")] + #[serde(default)] + name: Option, + #[serde(rename = "o")] + #[serde(default)] + opacity: Option, + #[serde(rename = "c")] + color: MultidimensionalPropertyValue, + }, + #[serde(rename = "tr")] + Transform { + #[serde(rename = "r")] + rotation: PropertyValue, + #[serde(rename = "sk")] + skew: PropertyValue, + #[serde(rename = "sa")] + skew_axis: PropertyValue, + #[serde(rename = "p")] + position: MultidimensionalPropertyValue, + #[serde(rename = "a")] + anchor_point: MultidimensionalPropertyValue, + #[serde(rename = "s")] + scale: MultidimensionalPropertyValue, + }, + #[serde(other)] + Unimplemented, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ShapeVertices { + Shape { + #[serde(rename = "k")] + value: ShapeProperty, + #[serde(rename = "x")] + #[serde(default)] + expression: Option, + #[serde(rename = "ix")] + #[serde(default)] + index: Option, + #[serde(rename = "a")] + animated: i64, + }, + ShapeKeyframed { + #[serde(rename = "k")] + value: Vec, + #[serde(rename = "x")] + #[serde(default)] + expression: Option, + #[serde(rename = "ix")] + #[serde(default)] + index: Option, + #[serde(rename = "a")] + animated: i64, + #[serde(rename = "ti")] + #[serde(default)] + in_tangent: Vec, + #[serde(rename = "to")] + #[serde(default)] + out_tangent: Vec, + }, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ShapeProperty { + #[serde(rename = "c")] + pub closed: bool, + #[serde(rename = "i")] + pub in_points: Vec<[f32; 2]>, + #[serde(rename = "o")] + pub out_points: Vec<[f32; 2]>, + #[serde(rename = "v")] + pub vertices: Vec<[f32; 2]>, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ShapeKeyframeProperty { + #[serde(rename = "s")] + #[serde(default)] + pub start: Vec>, + #[serde(rename = "t")] + pub time: i64, + #[serde(rename = "i")] + #[serde(default)] + pub in_value: Option, + #[serde(rename = "o")] + #[serde(default)] + pub out_value: Option, +} + +impl Lottie { + #[inline] + pub fn from_reader(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } +} From 8c0415c9b9b21e349bb75d48ece1d64a546f71cc Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Fri, 24 May 2019 12:19:10 -0400 Subject: [PATCH 25/28] Remove cross method from F32x4 Silencing the following rustc warning: warning: unused variable: `other` Followup to Pull Request #152. Instead of marking `other` unused (`_other`) we can remove the method entirely. --- simd/src/scalar/mod.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/simd/src/scalar/mod.rs b/simd/src/scalar/mod.rs index 553b1780..901d0af0 100644 --- a/simd/src/scalar/mod.rs +++ b/simd/src/scalar/mod.rs @@ -173,11 +173,6 @@ impl F32x4 { pub fn concat_wz_yx(self, other: F32x4) -> F32x4 { F32x4([self[3], self[2], other[1], other[0]]) } - - #[inline] - pub fn cross(&self, other: F32x4) -> F32x4 { - unimplemented!() - } } impl Index for F32x4 { From 349c1a9cd0b611ef46ef4835f776824c3816ced1 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Fri, 24 May 2019 19:22:23 +0200 Subject: [PATCH 26/28] Update quickcheck to 0.8 This dedupes some dependencies --- Cargo.lock | 47 ++++++--------------------------------------- renderer/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a3ce277..912cbd46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -476,18 +476,6 @@ name = "either" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "env_logger" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.6.1" @@ -1305,7 +1293,7 @@ dependencies = [ "pathfinder_gpu 0.1.0", "pathfinder_simd 0.3.0", "pathfinder_ui 0.1.0", - "quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quickcheck 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1427,13 +1415,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quickcheck" -version = "0.7.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1444,18 +1432,6 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.6.5" @@ -1483,14 +1459,6 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_core" version = "0.3.1" @@ -2307,7 +2275,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum dwrote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30a998e9ff70cd208ccdc4f864e998688bf61d7b897dccec8e17a884d17358bf" "checksum egl 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a373bc9844200b1ff15bd1b245931d1c20d09d06e4ec09f361171f29a4b0752d" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7a4719a544a67ed3fc33784c2bd2c6581663dfe83b719a6ae05c6dabc3b51c73" @@ -2395,12 +2362,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4537d3e4edf73a15dd059b75bed1c292d17d3ea7517f583cebe716794fcf816" +"checksum quickcheck 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8d467b6d7a927b98d31a9d726d84da692787ae8238da3bed081fa992b30cfa8a" "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml index 45a2f50e..0a575b30 100644 --- a/renderer/Cargo.toml +++ b/renderer/Cargo.toml @@ -30,4 +30,4 @@ path = "../simd" path = "../ui" [dev-dependencies] -quickcheck = "0.7" +quickcheck = "0.8" From e04cc273eec352e3a5da1a96b3f026cbfdc676b6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 24 May 2019 17:45:19 -0700 Subject: [PATCH 27/28] Add enough C bindings to recreate `canvas_minimal` in C. Closes #12. --- .gitignore | 1 + Cargo.lock | 13 + Cargo.toml | 1 + c/Cargo.toml | 29 ++ c/include/pathfinder/pathfinder.h | 158 ++++++++ c/src/lib.rs | 360 +++++++++++++++++++ canvas/Cargo.toml | 3 + examples/c_canvas_minimal/Makefile | 47 +++ examples/c_canvas_minimal/c_canvas_minimal.c | 117 ++++++ gl/Cargo.toml | 3 + gl/src/lib.rs | 6 +- 11 files changed, 736 insertions(+), 2 deletions(-) create mode 100644 c/Cargo.toml create mode 100644 c/include/pathfinder/pathfinder.h create mode 100644 c/src/lib.rs create mode 100644 examples/c_canvas_minimal/Makefile create mode 100644 examples/c_canvas_minimal/c_canvas_minimal.c diff --git a/.gitignore b/.gitignore index 7fd32a8d..82600a0a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ target /site/package-lock.json /site/dist node_modules +/examples/c_canvas_minimal/build # Editors *.swp diff --git a/Cargo.lock b/Cargo.lock index 912cbd46..5b0b1404 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1184,6 +1184,19 @@ dependencies = [ "pathfinder_gpu 0.1.0", ] +[[package]] +name = "pathfinder_c" +version = "0.1.0" +dependencies = [ + "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_canvas 0.1.0", + "pathfinder_geometry 0.3.0", + "pathfinder_gl 0.1.0", + "pathfinder_gpu 0.1.0", + "pathfinder_renderer 0.1.0", + "pathfinder_simd 0.3.0", +] + [[package]] name = "pathfinder_canvas" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 3163c514..d477c5b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "c", "canvas", "demo/android/rust", "demo/common", diff --git a/c/Cargo.toml b/c/Cargo.toml new file mode 100644 index 00000000..7c17d4b2 --- /dev/null +++ b/c/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "pathfinder_c" +version = "0.1.0" +authors = ["Patrick Walton "] +edition = "2018" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +gl = "0.6" + +[dependencies.pathfinder_canvas] +path = "../canvas" + +[dependencies.pathfinder_geometry] +path = "../geometry" + +[dependencies.pathfinder_gl] +path = "../gl" + +[dependencies.pathfinder_gpu] +path = "../gpu" + +[dependencies.pathfinder_renderer] +path = "../renderer" + +[dependencies.pathfinder_simd] +path = "../simd" diff --git a/c/include/pathfinder/pathfinder.h b/c/include/pathfinder/pathfinder.h new file mode 100644 index 00000000..fd82dbb3 --- /dev/null +++ b/c/include/pathfinder/pathfinder.h @@ -0,0 +1,158 @@ +// pathfinder/c/include/pathfinder/pathfinder.h +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#ifndef PF_PATHFINDER_H +#define PF_PATHFINDER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Macros + +// `gl` + +#define PF_GL_VERSION_GL3 0 +#define PF_GL_VERSION_GLES3 1 + +// `gpu` + +#define PF_CLEAR_FLAGS_HAS_COLOR 0x1 +#define PF_CLEAR_FLAGS_HAS_DEPTH 0x2 +#define PF_CLEAR_FLAGS_HAS_STENCIL 0x4 +#define PF_CLEAR_FLAGS_HAS_RECT 0x8 + +// Types + +// `canvas` + +struct PFCanvas; +typedef struct PFCanvas *PFCanvasRef; +struct PFPath; +typedef struct PFPath *PFPathRef; + +// `geometry` + +struct PFColorF { + float r, g, b, a; +}; +typedef struct PFColorF PFColorF; +struct PFPoint2DF { + float x, y; +}; +typedef struct PFPoint2DF PFPoint2DF; +struct PFPoint2DI { + int32_t x, y; +}; +typedef struct PFPoint2DI PFPoint2DI; +struct PFRectF { + PFPoint2DF origin, lower_right; +}; +typedef struct PFRectF PFRectF; +struct PFRectI { + PFPoint2DI origin, lower_right; +}; +typedef struct PFRectI PFRectI; + +// `gl` + +struct PFGLDevice; +typedef struct PFGLDevice *PFGLDeviceRef; +struct PFGLDestFramebuffer; +typedef struct PFGLDestFramebuffer *PFGLDestFramebufferRef; +typedef const void *(*PFGLFunctionLoader)(const char *data, void *userdata); +struct PFGLRenderer; +typedef struct PFGLRenderer *PFGLRendererRef; +typedef uint32_t PFGLVersion; + +// `gpu` + +typedef uint8_t PFClearFlags; +struct PFClearParams { + PFColorF color; + float depth; + uint8_t stencil; + PFRectI rect; + PFClearFlags flags; +}; +typedef struct PFClearParams PFClearParams; +struct PFResourceLoader; +typedef struct PFResourceLoader *PFResourceLoaderRef; + +// `renderer` + +struct PFRenderOptions { + uint32_t placeholder; +}; +typedef struct PFRenderOptions PFRenderOptions; +struct PFScene; +typedef struct PFScene *PFSceneRef; +struct PFSceneProxy; +typedef struct PFSceneProxy *PFSceneProxyRef; + +// Functions + +// `canvas` + +PFCanvasRef PFCanvasCreate(const PFPoint2DF *size); +void PFCanvasDestroy(PFCanvasRef canvas); +PFSceneRef PFCanvasCreateScene(PFCanvasRef canvas); +void PFCanvasFillRect(PFCanvasRef canvas, const PFRectF *rect); +void PFCanvasStrokeRect(PFCanvasRef canvas, const PFRectF *rect); +void PFCanvasSetLineWidth(PFCanvasRef canvas, float new_line_width); +void PFCanvasFillPath(PFCanvasRef canvas, PFPathRef path); +void PFCanvasStrokePath(PFCanvasRef canvas, PFPathRef path); +PFPathRef PFPathCreate(); +void PFPathDestroy(PFPathRef path); +PFPathRef PFPathClone(PFPathRef path); +void PFPathMoveTo(PFPathRef path, const PFPoint2DF *to); +void PFPathLineTo(PFPathRef path, const PFPoint2DF *to); +void PFPathQuadraticCurveTo(PFPathRef path, const PFPoint2DF *ctrl, const PFPoint2DF *to); +void PFPathBezierCurveTo(PFPathRef path, + const PFPoint2DF *ctrl0, + const PFPoint2DF *ctrl1, + const PFPoint2DF *to); +void PFPathClosePath(PFPathRef path); + +// `gl` + +PFGLDestFramebufferRef PFGLDestFramebufferCreateFullWindow(const PFPoint2DI *window_size); +void PFGLDestFramebufferDestroy(PFGLDestFramebufferRef dest_framebuffer); +PFGLDeviceRef PFGLDeviceCreate(PFGLVersion version, uint32_t default_framebuffer); +void PFGLDeviceDestroy(PFGLDeviceRef device); +void PFGLDeviceClear(PFGLDeviceRef device, const PFClearParams *params); +void PFGLLoadWith(PFGLFunctionLoader loader, void *userdata); +PFGLRendererRef PFGLRendererCreate(PFGLDeviceRef device, + PFResourceLoaderRef resources, + PFGLDestFramebufferRef dest_framebuffer); +void PFGLRendererDestroy(PFGLRendererRef renderer); +/// Returns a borrowed reference to the device. +PFGLDeviceRef PFGLRendererGetDevice(PFGLRendererRef renderer); +void PFSceneProxyBuildAndRenderGL(PFSceneProxyRef scene_proxy, + PFGLRendererRef renderer, + const PFRenderOptions *options); + +// `gpu` + +PFResourceLoaderRef PFFilesystemResourceLoaderLocate(); +void PFResourceLoaderDestroy(PFResourceLoaderRef loader); + +// `renderer` + +PFSceneProxyRef PFSceneProxyCreateFromSceneAndRayonExecutor(PFSceneRef scene); +void PFSceneProxyDestroy(PFSceneProxyRef scene_proxy); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib.rs b/c/src/lib.rs new file mode 100644 index 00000000..72475994 --- /dev/null +++ b/c/src/lib.rs @@ -0,0 +1,360 @@ +// pathfinder/c/src/lib.rs +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! C bindings to Pathfinder. + +use gl; +use pathfinder_canvas::{CanvasRenderingContext2D, Path2D}; +use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; +use pathfinder_geometry::basic::rect::{RectF32, RectI32}; +use pathfinder_geometry::color::ColorF; +use pathfinder_gl::{GLDevice, GLVersion}; +use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; +use pathfinder_gpu::{ClearParams, Device}; +use pathfinder_renderer::concurrent::rayon::RayonExecutor; +use pathfinder_renderer::concurrent::scene_proxy::SceneProxy; +use pathfinder_renderer::gpu::renderer::{DestFramebuffer, Renderer}; +use pathfinder_renderer::options::RenderOptions; +use pathfinder_renderer::scene::Scene; +use pathfinder_simd::default::F32x4; +use std::ffi::CString; +use std::os::raw::{c_char, c_void}; + +// Constants + +pub const PF_CLEAR_FLAGS_HAS_COLOR: u8 = 0x1; +pub const PF_CLEAR_FLAGS_HAS_DEPTH: u8 = 0x2; +pub const PF_CLEAR_FLAGS_HAS_STENCIL: u8 = 0x4; +pub const PF_CLEAR_FLAGS_HAS_RECT: u8 = 0x8; + +// Types + +// `canvas` +pub type PFCanvasRef = *mut CanvasRenderingContext2D; +pub type PFPathRef = *mut Path2D; + +// `geometry` +#[repr(C)] +pub struct PFPoint2DF { + pub x: f32, + pub y: f32, +} +#[repr(C)] +pub struct PFPoint2DI { + pub x: i32, + pub y: i32, +} +#[repr(C)] +pub struct PFRectF { + pub origin: PFPoint2DF, + pub lower_right: PFPoint2DF, +} +#[repr(C)] +pub struct PFRectI { + pub origin: PFPoint2DI, + pub lower_right: PFPoint2DI, +} +#[repr(C)] +pub struct PFColorF { + pub r: f32, + pub g: f32, + pub b: f32, + pub a: f32, +} + +// `gl` +pub type PFGLDeviceRef = *mut GLDevice; +pub type PFGLVersion = GLVersion; +pub type PFGLFunctionLoader = extern "C" fn(name: *const c_char, userdata: *mut c_void) + -> *const c_void; +// `gpu` +pub type PFGLDestFramebufferRef = *mut DestFramebuffer; +pub type PFGLRendererRef = *mut Renderer; +// FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is +// stable? +pub type PFResourceLoaderRef = *mut Box; +#[repr(C)] +pub struct PFClearParams { + pub color: PFColorF, + pub depth: f32, + pub stencil: u8, + pub rect: PFRectI, + pub flags: PFClearFlags, +} +pub type PFClearFlags = u8; + +// `renderer` +pub type PFSceneRef = *mut Scene; +pub type PFSceneProxyRef = *mut SceneProxy; +// TODO(pcwalton) +#[repr(C)] +pub struct PFRenderOptions { + pub placeholder: u32, +} + +// `canvas` + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasCreate(size: *const PFPoint2DF) -> PFCanvasRef { + Box::into_raw(Box::new(CanvasRenderingContext2D::new((*size).to_rust()))) +} + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasDestroy(canvas: PFCanvasRef) { + drop(Box::from_raw(canvas)) +} + +/// Consumes the canvas. +#[no_mangle] +pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef { + Box::into_raw(Box::new(Box::from_raw(canvas).into_scene())) +} + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasFillRect(canvas: PFCanvasRef, rect: *const PFRectF) { + (*canvas).fill_rect((*rect).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasStrokeRect(canvas: PFCanvasRef, rect: *const PFRectF) { + (*canvas).stroke_rect((*rect).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasSetLineWidth(canvas: PFCanvasRef, new_line_width: f32) { + (*canvas).set_line_width(new_line_width) +} + +/// Consumes the path. +#[no_mangle] +pub unsafe extern "C" fn PFCanvasFillPath(canvas: PFCanvasRef, path: PFPathRef) { + (*canvas).fill_path(*Box::from_raw(path)) +} + +/// Consumes the path. +#[no_mangle] +pub unsafe extern "C" fn PFCanvasStrokePath(canvas: PFCanvasRef, path: PFPathRef) { + (*canvas).stroke_path(*Box::from_raw(path)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathCreate() -> PFPathRef { + Box::into_raw(Box::new(Path2D::new())) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathDestroy(path: PFPathRef) { + drop(Box::from_raw(path)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathClone(path: PFPathRef) -> PFPathRef { + Box::into_raw(Box::new((*path).clone())) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathMoveTo(path: PFPathRef, to: *const PFPoint2DF) { + (*path).move_to((*to).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathLineTo(path: PFPathRef, to: *const PFPoint2DF) { + (*path).line_to((*to).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathQuadraticCurveTo(path: PFPathRef, + ctrl: *const PFPoint2DF, + to: *const PFPoint2DF) { + (*path).quadratic_curve_to((*ctrl).to_rust(), (*to).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathBezierCurveTo(path: PFPathRef, + ctrl0: *const PFPoint2DF, + ctrl1: *const PFPoint2DF, + to: *const PFPoint2DF) { + (*path).bezier_curve_to((*ctrl0).to_rust(), (*ctrl1).to_rust(), (*to).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFPathClosePath(path: PFPathRef) { + (*path).close_path() +} + +// `gl` + +#[no_mangle] +pub unsafe extern "C" fn PFFilesystemResourceLoaderLocate() -> PFResourceLoaderRef { + let loader = Box::new(FilesystemResourceLoader::locate()); + Box::into_raw(Box::new(loader as Box)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFGLLoadWith(loader: PFGLFunctionLoader, userdata: *mut c_void) { + gl::load_with(|name| { + let name = CString::new(name).unwrap(); + loader(name.as_ptr(), userdata) + }); +} + +#[no_mangle] +pub unsafe extern "C" fn PFGLDeviceCreate(version: PFGLVersion, default_framebuffer: u32) + -> PFGLDeviceRef { + Box::into_raw(Box::new(GLDevice::new(version, default_framebuffer))) +} + +#[no_mangle] +pub unsafe extern "C" fn PFGLDeviceDestroy(device: PFGLDeviceRef) { + drop(Box::from_raw(device)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFGLDeviceClear(device: PFGLDeviceRef, params: *const PFClearParams) { + (*device).clear(&(*params).to_rust()) +} + +#[no_mangle] +pub unsafe extern "C" fn PFResourceLoaderDestroy(loader: PFResourceLoaderRef) { + drop(Box::from_raw(loader)) +} + +// `gpu` + +#[no_mangle] +pub unsafe extern "C" fn PFGLDestFramebufferCreateFullWindow(window_size: *const PFPoint2DI) + -> PFGLDestFramebufferRef { + Box::into_raw(Box::new(DestFramebuffer::full_window((*window_size).to_rust()))) +} + +#[no_mangle] +pub unsafe extern "C" fn PFGLDestFramebufferDestroy(dest_framebuffer: PFGLDestFramebufferRef) { + drop(Box::from_raw(dest_framebuffer)) +} + +/// Takes ownership of `device` and `dest_framebuffer`, but not `resources`. +#[no_mangle] +pub unsafe extern "C" fn PFGLRendererCreate(device: PFGLDeviceRef, + resources: PFResourceLoaderRef, + dest_framebuffer: PFGLDestFramebufferRef) + -> PFGLRendererRef { + Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device), + &**resources, + *Box::from_raw(dest_framebuffer)))) +} + +#[no_mangle] +pub unsafe extern "C" fn PFGLRendererDestroy(renderer: PFGLRendererRef) { + drop(Box::from_raw(renderer)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFGLRendererGetDevice(renderer: PFGLRendererRef) -> PFGLDeviceRef { + &mut (*renderer).device +} + +#[no_mangle] +pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef, + renderer: PFGLRendererRef, + options: *const PFRenderOptions) { + (*scene_proxy).build_and_render(&mut *renderer, (*options).to_rust()) +} + +// `renderer` + +#[no_mangle] +pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) { + drop(Box::from_raw(scene)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFSceneProxyCreateFromSceneAndRayonExecutor(scene: PFSceneRef) + -> PFSceneProxyRef { + Box::into_raw(Box::new(SceneProxy::from_scene(*Box::from_raw(scene), RayonExecutor))) +} + +#[no_mangle] +pub unsafe extern "C" fn PFSceneProxyDestroy(scene_proxy: PFSceneProxyRef) { + drop(Box::from_raw(scene_proxy)) +} + +// Helpers for `geometry` + +impl PFColorF { + #[inline] + pub fn to_rust(&self) -> ColorF { + ColorF(F32x4::new(self.r, self.g, self.b, self.a)) + } +} + +impl PFRectF { + #[inline] + pub fn to_rust(&self) -> RectF32 { + RectF32::from_points(self.origin.to_rust(), self.lower_right.to_rust()) + } +} + +impl PFRectI { + #[inline] + pub fn to_rust(&self) -> RectI32 { + RectI32::from_points(self.origin.to_rust(), self.lower_right.to_rust()) + } +} + +impl PFPoint2DF { + #[inline] + pub fn to_rust(&self) -> Point2DF32 { + Point2DF32::new(self.x, self.y) + } +} + +impl PFPoint2DI { + #[inline] + pub fn to_rust(&self) -> Point2DI32 { + Point2DI32::new(self.x, self.y) + } +} + +// Helpers for `gpu` + +impl PFClearParams { + pub fn to_rust(&self) -> ClearParams { + ClearParams { + color: if (self.flags & PF_CLEAR_FLAGS_HAS_COLOR) != 0 { + Some(self.color.to_rust()) + } else { + None + }, + rect: if (self.flags & PF_CLEAR_FLAGS_HAS_RECT) != 0 { + Some(self.rect.to_rust()) + } else { + None + }, + depth: if (self.flags & PF_CLEAR_FLAGS_HAS_DEPTH) != 0 { + Some(self.depth) + } else { + None + }, + stencil: if (self.flags & PF_CLEAR_FLAGS_HAS_STENCIL) != 0 { + Some(self.stencil) + } else { + None + }, + } + } +} + +// Helpers for `renderer` + +impl PFRenderOptions { + pub fn to_rust(&self) -> RenderOptions { + RenderOptions::default() + } +} diff --git a/canvas/Cargo.toml b/canvas/Cargo.toml index 0ca7b922..d93ac0cf 100644 --- a/canvas/Cargo.toml +++ b/canvas/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" authors = ["Patrick Walton "] edition = "2018" +[lib] +crate-type = ["rlib", "staticlib"] + [dependencies] font-kit = "0.1" diff --git a/examples/c_canvas_minimal/Makefile b/examples/c_canvas_minimal/Makefile new file mode 100644 index 00000000..35f4b9ef --- /dev/null +++ b/examples/c_canvas_minimal/Makefile @@ -0,0 +1,47 @@ +OBJ_DIR?=build +TARGET_DIR?=build +SRC_DIR?=. +RUST_TARGET_DIR?=../../target +RUST_SRC_DIR?=../../c +RUSTFLAGS?=-C target-cpu=native + +CFLAGS?=-Wall -g -I../../c/include +LIBS?=-lpathfinder_c +MKDIR?=mkdir -p +RM?=rm +CARGO?=cargo + +UNAME=$(shell uname -s) +ifeq ($(UNAME),Darwin) + # FIXME(pcwalton): Don't link against HarfBuzz!! + LIBS+=-framework OpenGL -framework CoreFoundation -framework CoreGraphics -framework CoreText + LIBS+=-lharfbuzz +else + LIBS+=-lGL +endif + +ifeq ($(DEBUG),) + CFLAGS+=-O2 + LDFLAGS?=-L$(RUST_TARGET_DIR)/release + CARGOFLAGS?=--release +else + CFLAGS+=-O0 + LDFLAGS?=-L$(RUST_TARGET_DIR)/debug + CARGOFLAGS?= +endif + +all: $(TARGET_DIR)/c_canvas_minimal + +.PHONY: clean rustlib + +$(TARGET_DIR)/c_canvas_minimal: $(OBJ_DIR)/c_canvas_minimal.o rustlib + $(MKDIR) $(TARGET_DIR) && $(CC) $(LDFLAGS) $(LIBS) `sdl2-config --libs` -o $@ $< + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c + $(MKDIR) $(OBJ_DIR) && $(CC) -c $(CFLAGS) `sdl2-config --cflags` -o $@ $< + +rustlib: + cd $(RUST_SRC_DIR) && RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build $(CARGOFLAGS) + +clean: + $(RM) -rf $(TARGET_DIR) && $(RM) -rf $(OBJ_DIR) diff --git a/examples/c_canvas_minimal/c_canvas_minimal.c b/examples/c_canvas_minimal/c_canvas_minimal.c new file mode 100644 index 00000000..9b5f3777 --- /dev/null +++ b/examples/c_canvas_minimal/c_canvas_minimal.c @@ -0,0 +1,117 @@ +// pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include +#include +#include +#include +#include +#include +#include + +static const void *LoadGLFunction(const char *name, void *userdata); +static void SDLFailed(const char *msg); + +int main(int argc, const char **argv) { + // Set up SDL2. + if (SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) + SDLFailed("Failed to initialize SDL"); + + // Make sure we have at least a GL 3.0 context. Pathfinder requires this. + if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3) != 0) + SDLFailed("Failed to set GL major version"); + if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2) != 0) + SDLFailed("Failed to set GL minor version"); + if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0) + SDLFailed("Failed to set GL profile"); + if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) != 0) + SDLFailed("Failed to make GL context double-buffered"); + + // Open a window. + SDL_Window *window = SDL_CreateWindow("Minimal canvas example (C API)", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + 640, + 480, + SDL_WINDOW_OPENGL); + if (window == NULL) + SDLFailed("Failed to create SDL window"); + + // Create the GL context, and make it current. + SDL_GLContext gl_context = SDL_GL_CreateContext(window); + if (gl_context == NULL) + SDLFailed("Failed to create GL context"); + + // Put the window on screen. + SDL_ShowWindow(window); + + // Create a Pathfinder renderer. + PFGLLoadWith(LoadGLFunction, NULL); + PFGLDestFramebufferRef dest_framebuffer = + PFGLDestFramebufferCreateFullWindow(&(PFPoint2DI){640, 480}); + PFGLRendererRef renderer = PFGLRendererCreate(PFGLDeviceCreate(PF_GL_VERSION_GL3, 0), + PFFilesystemResourceLoaderLocate(), + dest_framebuffer); + + // Clear to white. + PFGLDeviceClear(PFGLRendererGetDevice(renderer), &(PFClearParams){ + (PFColorF){1.0, 1.0, 1.0, 1.0}, 0.0, 0, {0}, PF_CLEAR_FLAGS_HAS_COLOR + }); + + // Make a canvas. We're going to draw a house. + PFCanvasRef canvas = PFCanvasCreate(&(PFPoint2DF){640.0f, 480.0f}); + + // Set line width. + PFCanvasSetLineWidth(canvas, 10.0f); + + // Draw walls. + PFCanvasStrokeRect(canvas, &(PFRectF){{75.0f, 140.0f}, {225.0f, 250.0f}}); + + // Draw door. + PFCanvasFillRect(canvas, &(PFRectF){{130.0f, 190.0f}, {170.0f, 250.0f}}); + + // Draw roof. + PFPathRef path = PFPathCreate(); + PFPathMoveTo(path, &(PFPoint2DF){50.0, 140.0}); + PFPathLineTo(path, &(PFPoint2DF){150.0, 60.0}); + PFPathLineTo(path, &(PFPoint2DF){250.0, 140.0}); + PFPathClosePath(path); + PFCanvasStrokePath(canvas, path); + + // Render the canvas to screen. + PFSceneRef scene = PFCanvasCreateScene(canvas); + PFSceneProxyRef scene_proxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene); + PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, &(PFRenderOptions){0}); + SDL_GL_SwapWindow(window); + + // Wait for a keypress. + while (true) { + SDL_Event event; + if (SDL_WaitEvent(&event) == 0) + SDLFailed("Failed to get SDL event"); + if (event.type == SDL_QUIT || + (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) { + break; + } + } + + // Finish up. + SDL_Quit(); + return 0; +} + +static const void *LoadGLFunction(const char *name, void *userdata) { + return SDL_GL_GetProcAddress(name); +} + +static void SDLFailed(const char *msg) { + fprintf(stderr, "%s: %s\n", msg, SDL_GetError()); + exit(EXIT_FAILURE); +} diff --git a/gl/Cargo.toml b/gl/Cargo.toml index edf674e7..ce219884 100644 --- a/gl/Cargo.toml +++ b/gl/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2018" authors = ["Patrick Walton "] +[lib] +crate-type = ["rlib", "staticlib"] + [dependencies] gl = "0.6" rustache = "0.1" diff --git a/gl/src/lib.rs b/gl/src/lib.rs index cb4e002a..dd2f4072 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -859,11 +859,13 @@ impl VertexAttrTypeExt for VertexAttrType { } /// The version/dialect of OpenGL we should render with. +#[derive(Clone, Copy)] +#[repr(u32)] pub enum GLVersion { /// OpenGL 3.0+, core profile. - GL3, + GL3 = 0, /// OpenGL ES 3.0+. - GLES3, + GLES3 = 1, } impl GLVersion { From bc713a5181ab7ed90469d054c36f78baed36b306 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Sun, 26 May 2019 13:02:52 -0700 Subject: [PATCH 28/28] Remove the rustache dependency. 1/3 reduction in binary size for `canvas_minimal`. Closes #158. --- Cargo.lock | 102 ------------------ gl/Cargo.toml | 1 - gl/src/lib.rs | 51 +++++++-- gpu/Cargo.toml | 1 - gpu/src/lib.rs | 62 ++++------- resources/shaders/post.fs.glsl | 4 +- .../shaders/tile_alpha_monochrome.vs.glsl | 4 +- .../shaders/tile_alpha_multicolor.vs.glsl | 4 +- .../shaders/tile_solid_monochrome.vs.glsl | 4 +- .../shaders/tile_solid_multicolor.vs.glsl | 4 +- 10 files changed, 73 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b0b1404..ba24425d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,14 +5,6 @@ name = "adler32" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "aho-corasick" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.7.3" @@ -851,15 +843,6 @@ dependencies = [ "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "khronos" version = "0.1.2" @@ -983,14 +966,6 @@ dependencies = [ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memchr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.2.0" @@ -1251,7 +1226,6 @@ dependencies = [ "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", "pathfinder_simd 0.3.0", - "rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1261,7 +1235,6 @@ dependencies = [ "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_simd 0.3.0", - "rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1599,18 +1572,6 @@ dependencies = [ "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "1.1.6" @@ -1623,11 +1584,6 @@ dependencies = [ "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex-syntax" version = "0.6.6" @@ -1644,25 +1600,11 @@ dependencies = [ "xmlparser 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustache" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-demangle" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc_version" version = "0.2.3" @@ -1963,23 +1905,6 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.6" @@ -2048,11 +1973,6 @@ dependencies = [ "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "utf8-ranges" version = "1.0.2" @@ -2137,11 +2057,6 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.3.7" @@ -2151,11 +2066,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2240,7 +2150,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" "checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e" "checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" @@ -2326,7 +2235,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum jni 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "294eca097d1dc0bf59de5ab9f7eafa5f77129e9f6464c957ed3ddeb705fb4292" "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" "checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum khronos 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c0711aaa80e6ba6eb1fa8978f1f46bfcb38ceb2f3f33f3736efbff39dac89f50" "checksum khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554" "checksum khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" @@ -2343,7 +2251,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9dc8e0746b7cca11960b602f7fe037bb067746a01eab4aa502fed1494544843" "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" @@ -2394,14 +2301,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum roxmltree 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02660467d0c2da1b6276042501aee6e15ec5b8ff59423243f185b294cd53acf3" -"checksum rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86de9443c1a5618e0d51bbd8eb6227ead9916446eb8952575a70d1ef7e00209" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rusttype 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "25951e85bb2647960969f72c559392245a5bd07446a589390bf427dda31cdc4a" "checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" @@ -2437,8 +2340,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" @@ -2448,7 +2349,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum usvg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ebf4d5244ba2e8305caf9de7949377794ecdea5a9e3c84fc5610d78d21f5ee" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" @@ -2459,9 +2359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum wayland-protocols 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ccddf6a4407d982898e0f0a1172217843f3d40fe4272f828060b56a2d40d81" "checksum wayland-scanner 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "63bc5efa7dcdb8f04d2e5d1571c0d0577fc47076d133d68e056bdb299f1b60e2" "checksum wayland-sys 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e76af81a601b84d400744f85f083381daa77ac01f6c8711e57e662dc3a35d69d" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/gl/Cargo.toml b/gl/Cargo.toml index ce219884..490e2ec4 100644 --- a/gl/Cargo.toml +++ b/gl/Cargo.toml @@ -9,7 +9,6 @@ crate-type = ["rlib", "staticlib"] [dependencies] gl = "0.6" -rustache = "0.1" [dependencies.image] version = "0.21" diff --git a/gl/src/lib.rs b/gl/src/lib.rs index dd2f4072..a10b017f 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -16,14 +16,13 @@ extern crate log; use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid}; use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::rect::RectI32; +use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearParams}; use pathfinder_gpu::{DepthFunc, Device, Primitive, RenderState, ShaderKind, StencilFunc}; use pathfinder_gpu::{TextureFormat, UniformData, VertexAttrClass}; use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_simd::default::F32x4; -use rustache::{HashBuilder, Render}; use std::ffi::CString; -use std::io::Cursor; use std::mem; use std::ptr; use std::str; @@ -223,18 +222,18 @@ impl Device for GLDevice { } fn create_shader_from_source(&self, + resources: &dyn ResourceLoader, name: &str, source: &[u8], kind: ShaderKind, - mut template_input: HashBuilder) + includes: &[&str]) -> GLShader { // FIXME(pcwalton): Do this once and cache it. let glsl_version_spec = self.version.to_glsl_version_spec(); - template_input = template_input.insert("version", glsl_version_spec); - let mut output = Cursor::new(vec![]); - template_input.render(str::from_utf8(source).unwrap(), &mut output).unwrap(); - let source = output.into_inner(); + let mut output = vec![]; + self.preprocess(&mut output, resources, source, includes, glsl_version_spec); + let source = output; let gl_shader_kind = match kind { ShaderKind::Vertex => gl::VERTEX_SHADER, @@ -268,6 +267,7 @@ impl Device for GLDevice { } fn create_program_from_shaders(&self, + resources: &dyn ResourceLoader, name: &str, vertex_shader: GLShader, fragment_shader: GLShader) @@ -644,6 +644,41 @@ impl Device for GLDevice { } } +impl GLDevice { + fn preprocess(&self, + output: &mut Vec, + resources: &dyn ResourceLoader, + source: &[u8], + includes: &[&str], + version: &str) { + let mut index = 0; + while index < source.len() { + if source[index..].starts_with(b"{{") { + let end_index = source[index..].iter() + .position(|character| *character == b'}') + .expect("Expected `}`!") + index; + assert_eq!(source[end_index + 1], b'}'); + let ident = String::from_utf8_lossy(&source[(index + 2)..end_index]); + if ident == "version" { + output.extend_from_slice(version.as_bytes()); + } else if ident.starts_with("include_") { + let include_name = &ident["include_".len()..]; + if includes.iter().any(|include| *include == include_name) { + let include_source = self.load_shader_include(resources, include_name); + self.preprocess(output, resources, &include_source, includes, version); + } + } else { + panic!("unknown template variable: `{}`", ident); + } + index = end_index + 2; + } else { + output.push(source[index]); + index += 1; + } + } + } +} + pub struct GLVertexArray { pub gl_vertex_array: GLuint, } @@ -891,3 +926,5 @@ fn ck() { #[cfg(not(debug))] fn ck() {} + +// Shader preprocessing diff --git a/gpu/Cargo.toml b/gpu/Cargo.toml index e57a847f..c493efa2 100644 --- a/gpu/Cargo.toml +++ b/gpu/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Patrick Walton "] edition = "2018" [dependencies] -rustache = "0.1" [dependencies.image] version = "0.21" diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index ec418cee..a369b54e 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -17,11 +17,19 @@ use pathfinder_geometry::basic::rect::RectI32; use pathfinder_geometry::basic::transform3d::Transform3DF32; use pathfinder_geometry::color::ColorF; use pathfinder_simd::default::F32x4; -use rustache::HashBuilder; use std::time::Duration; pub mod resources; +static INCLUDES: [&str; 6] = [ + "tile_alpha_vertex", + "tile_monochrome", + "tile_multicolor", + "tile_solid_vertex", + "post_convolve", + "post_gamma_correct", +]; + pub trait Device { type Buffer; type Framebuffer; @@ -37,14 +45,16 @@ pub trait Device { fn create_texture_from_data(&self, size: Point2DI32, data: &[u8]) -> Self::Texture; fn create_shader_from_source( &self, + resources: &dyn ResourceLoader, name: &str, source: &[u8], kind: ShaderKind, - template_input: HashBuilder, + includes: &[&str], ) -> Self::Shader; fn create_vertex_array(&self) -> Self::VertexArray; fn create_program_from_shaders( &self, + resources: &dyn ResourceLoader, name: &str, vertex_shader: Self::Shader, fragment_shader: Self::Shader, @@ -109,39 +119,8 @@ pub trait Device { ShaderKind::Vertex => 'v', ShaderKind::Fragment => 'f', }; - let source = resources - .slurp(&format!("shaders/{}.{}s.glsl", name, suffix)) - .unwrap(); - - let mut load_include_tile_alpha_vertex = - |_| load_shader_include(resources, "tile_alpha_vertex"); - let mut load_include_tile_monochrome = - |_| load_shader_include(resources, "tile_monochrome"); - let mut load_include_tile_multicolor = - |_| load_shader_include(resources, "tile_multicolor"); - let mut load_include_tile_solid_vertex = - |_| load_shader_include(resources, "tile_solid_vertex"); - let mut load_include_post_convolve = |_| load_shader_include(resources, "post_convolve"); - let mut load_include_post_gamma_correct = - |_| load_shader_include(resources, "post_gamma_correct"); - let template_input = HashBuilder::new() - .insert_lambda( - "include_tile_alpha_vertex", - &mut load_include_tile_alpha_vertex, - ) - .insert_lambda("include_tile_monochrome", &mut load_include_tile_monochrome) - .insert_lambda("include_tile_multicolor", &mut load_include_tile_multicolor) - .insert_lambda( - "include_tile_solid_vertex", - &mut load_include_tile_solid_vertex, - ) - .insert_lambda("include_post_convolve", &mut load_include_post_convolve) - .insert_lambda( - "include_post_gamma_correct", - &mut load_include_post_gamma_correct, - ); - - self.create_shader_from_source(name, &source, kind, template_input) + let source = resources.slurp(&format!("shaders/{}.{}s.glsl", name, suffix)).unwrap(); + self.create_shader_from_source(resources, name, &source, kind, &INCLUDES) } fn create_program_from_shader_names( @@ -154,12 +133,16 @@ pub trait Device { let vertex_shader = self.create_shader(resources, vertex_shader_name, ShaderKind::Vertex); let fragment_shader = self.create_shader(resources, fragment_shader_name, ShaderKind::Fragment); - self.create_program_from_shaders(program_name, vertex_shader, fragment_shader) + self.create_program_from_shaders(resources, program_name, vertex_shader, fragment_shader) } fn create_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program { self.create_program_from_shader_names(resources, name, name, name) } + + fn load_shader_include(&self, resources: &dyn ResourceLoader, include_name: &str) -> Vec { + resources.slurp(&format!("shaders/{}.inc.glsl", include_name)).unwrap() + } } #[derive(Clone, Copy, Debug)] @@ -338,10 +321,3 @@ pub enum VertexAttrClass { FloatNorm, Int, } - -fn load_shader_include(resources: &dyn ResourceLoader, include_name: &str) -> String { - let resource = resources - .slurp(&format!("shaders/{}.inc.glsl", include_name)) - .unwrap(); - String::from_utf8_lossy(&resource).to_string() -} diff --git a/resources/shaders/post.fs.glsl b/resources/shaders/post.fs.glsl index 70597c79..cb7326a6 100644 --- a/resources/shaders/post.fs.glsl +++ b/resources/shaders/post.fs.glsl @@ -25,8 +25,8 @@ in vec2 vTexCoord; out vec4 oFragColor; -{{{include_post_gamma_correct}}} -{{{include_post_convolve}}} +{{include_post_gamma_correct}} +{{include_post_convolve}} // Convolve horizontally in this pass. float sample1Tap(float offset) { diff --git a/resources/shaders/tile_alpha_monochrome.vs.glsl b/resources/shaders/tile_alpha_monochrome.vs.glsl index dbe6be03..ac6cf195 100644 --- a/resources/shaders/tile_alpha_monochrome.vs.glsl +++ b/resources/shaders/tile_alpha_monochrome.vs.glsl @@ -12,8 +12,8 @@ precision highp float; -{{{include_tile_alpha_vertex}}} -{{{include_tile_monochrome}}} +{{include_tile_alpha_vertex}} +{{include_tile_monochrome}} void main() { computeVaryings(); diff --git a/resources/shaders/tile_alpha_multicolor.vs.glsl b/resources/shaders/tile_alpha_multicolor.vs.glsl index 43e9d3c7..b74c57fb 100644 --- a/resources/shaders/tile_alpha_multicolor.vs.glsl +++ b/resources/shaders/tile_alpha_multicolor.vs.glsl @@ -12,8 +12,8 @@ precision highp float; -{{{include_tile_alpha_vertex}}} -{{{include_tile_multicolor}}} +{{include_tile_alpha_vertex}} +{{include_tile_multicolor}} void main() { computeVaryings(); diff --git a/resources/shaders/tile_solid_monochrome.vs.glsl b/resources/shaders/tile_solid_monochrome.vs.glsl index d682f3c0..408488d7 100644 --- a/resources/shaders/tile_solid_monochrome.vs.glsl +++ b/resources/shaders/tile_solid_monochrome.vs.glsl @@ -12,8 +12,8 @@ precision highp float; -{{{include_tile_solid_vertex}}} -{{{include_tile_monochrome}}} +{{include_tile_solid_vertex}} +{{include_tile_monochrome}} void main() { computeVaryings(); diff --git a/resources/shaders/tile_solid_multicolor.vs.glsl b/resources/shaders/tile_solid_multicolor.vs.glsl index 868d2655..ae3b86bd 100644 --- a/resources/shaders/tile_solid_multicolor.vs.glsl +++ b/resources/shaders/tile_solid_multicolor.vs.glsl @@ -12,8 +12,8 @@ precision highp float; -{{{include_tile_solid_vertex}}} -{{{include_tile_multicolor}}} +{{include_tile_solid_vertex}} +{{include_tile_multicolor}} void main() { computeVaryings();