From 5d698998e9452b236e271cc94d384487837fba02 Mon Sep 17 00:00:00 2001 From: Jon Hardie Date: Sat, 15 Jun 2019 16:08:46 +1200 Subject: [PATCH 01/14] [WIP] Initial support for rendering graphic symbols from swf files. --- Cargo.toml | 2 + examples/swf_basic/Cargo.toml | 28 ++ examples/swf_basic/src/main.rs | 136 ++++++ examples/swf_basic/swf/tiger-flat.swf | Bin 0 -> 25311 bytes examples/swf_basic/swf/tiger.swf | Bin 0 -> 18971 bytes flash/Cargo.toml | 21 + flash/src/lib.rs | 207 +++++++++ flash/src/shapes.rs | 616 ++++++++++++++++++++++++++ flash/src/timeline.rs | 32 ++ 9 files changed, 1042 insertions(+) create mode 100644 examples/swf_basic/Cargo.toml create mode 100644 examples/swf_basic/src/main.rs create mode 100644 examples/swf_basic/swf/tiger-flat.swf create mode 100644 examples/swf_basic/swf/tiger.swf create mode 100644 flash/Cargo.toml create mode 100644 flash/src/lib.rs create mode 100644 flash/src/shapes.rs create mode 100644 flash/src/timeline.rs diff --git a/Cargo.toml b/Cargo.toml index d477c5b9..eaa64cae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,11 @@ members = [ "examples/canvas_moire", "examples/canvas_text", "examples/lottie_basic", + "examples/swf_basic", "geometry", "gl", "gpu", + "flash", "lottie", "renderer", "simd", diff --git a/examples/swf_basic/Cargo.toml b/examples/swf_basic/Cargo.toml new file mode 100644 index 00000000..eb64fe17 --- /dev/null +++ b/examples/swf_basic/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "swf_basic" +version = "0.1.0" +authors = ["Jon Hardie "] +edition = "2018" + +[dependencies] +gl = "0.6" +sdl2 = "0.32" +sdl2-sys = "0.32" + +swf-parser = "0.7.0" +swf-tree = "0.7.0" + +[dependencies.pathfinder_flash] +path = "../../flash" + +[dependencies.pathfinder_geometry] +path = "../../geometry" + +[dependencies.pathfinder_gl] +path = "../../gl" + +[dependencies.pathfinder_gpu] +path = "../../gpu" + +[dependencies.pathfinder_renderer] +path = "../../renderer" diff --git a/examples/swf_basic/src/main.rs b/examples/swf_basic/src/main.rs new file mode 100644 index 00000000..ea7f8b73 --- /dev/null +++ b/examples/swf_basic/src/main.rs @@ -0,0 +1,136 @@ +// pathfinder/examples/swf_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. + +use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::basic::rect::RectF; +use pathfinder_gl::{GLDevice, GLVersion}; +use pathfinder_gpu::resources::FilesystemResourceLoader; +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, RenderTransform}; +use sdl2::event::Event; +use sdl2::keyboard::Keycode; +use sdl2::video::GLProfile; +use pathfinder_renderer::scene::Scene; +use pathfinder_flash::{draw_paths_into_scene, process_swf_tags}; +use std::env; +use std::fs::read; +use pathfinder_geometry::basic::transform2d::Transform2DF; + +fn main() { + let swf_bytes; + if let Some(path) = env::args().skip(1).next() { + match read(path) { + Ok(bytes) => { + swf_bytes = bytes; + }, + Err(e) => panic!(e) + } + } else { + // NOTE(jon): This is a version of the ghostscript tiger graphic flattened to a single + // layer with no overlapping shapes. This is how artwork is 'natively' created in the Flash + // authoring tool when an artist just draws directly onto the canvas (without 'object' mode + // turned on, which is the default). + // Subsequent shapes with different fills will knock out existing fills where they overlap. + // A downside of this in current pathfinder is that cracks are visible between shape fills - + // especially obvious if you set the context clear color to #ff00ff or similar. + + // Common speculation as to why the swf format stores vector graphics in this way says that + // it is to save on file-size bytes, however in the case of our tiger, it results in a + // larger file than the layered version, since the overlapping shapes and strokes create + // a lot more geometry. I think a more likely explanation for the choice is that it was + // done to reduce overdraw in the software rasterizer running on late 90's era hardware? + // Indeed, this mode gives pathfinders' occlusion culling pass nothing to do! + let default_tiger = include_bytes!("../swf/tiger-flat.swf"); + + // NOTE(jon): This is a version of the same graphic cut and pasted into the Flash authoring + // tool from the SVG version loaded in Illustrator. When layered graphics are pasted + // into Flash, by default they retain their layering, expressed as groups. + // They are still presented as being on a single timeline layer. + // They will be drawn back to front in much the same way as the SVG version. + + //let default_tiger = include_bytes!("../tiger.swf"); + swf_bytes = Vec::from(&default_tiger[..]); + } + + let (_, movie): (_, swf_tree::Movie) = swf_parser::parsers::movie::parse_movie(&swf_bytes[..]).unwrap(); + + // Set up SDL2. + let sdl_context = sdl2::init().unwrap(); + let video = sdl_context.video().unwrap(); + + // Make sure we have at least a GL 3.0 context. Pathfinder requires this. + let gl_attributes = video.gl_attr(); + gl_attributes.set_context_profile(GLProfile::Core); + gl_attributes.set_context_version(3, 3); + + // process swf scene + // TODO(jon): Since swf is a streaming format, this really wants to be a lazy iterator over + // swf frames eventually. + let (library, stage) = process_swf_tags(&movie); + + // Open a window. + let window_size = Vector2I::new(stage.width(), stage.height()); + let window = video.window("Minimal example", window_size.x() as u32, window_size.y() as u32) + .opengl() + .allow_highdpi() + .build() + .unwrap(); + + let pixel_size = Vector2I::new( + window.drawable_size().0 as i32, + window.drawable_size().1 as i32 + ); + let device_pixel_ratio = pixel_size.x() as f32 / window_size.x() as f32; + + // Create the GL context, and make it current. + let gl_context = window.gl_create_context().unwrap(); + gl::load_with(|name| video.gl_get_proc_address(name) as *const _); + window.gl_make_current(&gl_context).unwrap(); + + // Create a Pathfinder renderer. + let mut renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0), + &FilesystemResourceLoader::locate(), + DestFramebuffer::full_window(pixel_size)); + // Clear to swf stage background color. + let mut scene = Scene::new(); + scene.set_view_box(RectF::new( + Vector2F::default(), + Vector2F::new( + stage.width() as f32 * device_pixel_ratio, + stage.height() as f32 * device_pixel_ratio) + )); + draw_paths_into_scene(&library, &mut scene); + + // Render the canvas to screen. + renderer.device.clear(&ClearParams { + color: Some(stage.background_color()), + ..ClearParams::default() + }); + let scene = SceneProxy::from_scene(scene, RayonExecutor); + let mut render_options = RenderOptions::default(); + let scale_transform = Transform2DF::from_scale( + Vector2F::new(device_pixel_ratio, device_pixel_ratio) + ); + render_options.transform = RenderTransform::Transform2D(scale_transform); + scene.build_and_render(&mut renderer, render_options); + + window.gl_swap_window(); + // Wait for a keypress. + let mut event_pump = sdl_context.event_pump().unwrap(); + loop { + match event_pump.wait_event() { + Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return, + _ => {} + } + } +} diff --git a/examples/swf_basic/swf/tiger-flat.swf b/examples/swf_basic/swf/tiger-flat.swf new file mode 100644 index 0000000000000000000000000000000000000000..70127188f531f9f5f5ad0fa219e95111bfbc1e83 GIT binary patch literal 25311 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

qxcY4QPw%XhNy?MpOoTlxVJSX_mL%5nt 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 Cs4jm1 literal 0 HcmV?d00001 diff --git a/examples/swf_basic/swf/tiger.swf b/examples/swf_basic/swf/tiger.swf new file mode 100644 index 0000000000000000000000000000000000000000..9bb17c65a7c9a2eebaa0a04b0f3cf8e68b302b22 GIT binary patch literal 18971 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 GAu>ri%Vnql literal 0 HcmV?d00001 diff --git a/flash/Cargo.toml b/flash/Cargo.toml new file mode 100644 index 00000000..2dff909f --- /dev/null +++ b/flash/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "pathfinder_flash" +version = "0.1.0" +authors = ["Jon Hardie "] +edition = "2018" + +[dependencies] +swf-parser = "0.7.0" +swf-tree = "0.7.0" + +[dependencies.pathfinder_geometry] +path = "../geometry" + +[dependencies.pathfinder_renderer] +path = "../renderer" + +[dependencies.pathfinder_gl] +path = "../gl" + +[dependencies.pathfinder_gpu] +path = "../gpu" diff --git a/flash/src/lib.rs b/flash/src/lib.rs new file mode 100644 index 00000000..fdc8b57e --- /dev/null +++ b/flash/src/lib.rs @@ -0,0 +1,207 @@ +// pathfinder/flash/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. + +use std::ops::Add; +use pathfinder_geometry::color::{ColorU, ColorF}; +use pathfinder_geometry::outline::{Outline, Contour}; +use pathfinder_geometry::basic::vector::Vector2F; +use pathfinder_geometry::stroke::{OutlineStrokeToFill, StrokeStyle}; +use pathfinder_renderer::scene::{PathObject, Scene}; + +use swf_tree; +use swf_tree::tags::SetBackgroundColor; +use swf_tree::{Tag, SRgb8, Movie}; + +use crate::shapes::{GraphicLayers, PaintOrLine}; + +mod shapes; + +type SymbolId = u16; + +// In swf, most values are specified in a fixed point format known as "twips" or twentieths of +// a pixel. We store twips in their integer form, as if we were to convert them to floating point +// at the beginning of the pipeline it's easy to start running into precision errors when we add +// coordinate deltas and then try and compare coords for equality. + +#[derive(Copy, Clone, Debug, PartialEq)] +struct Twips(i32); + +impl Twips { + // Divide twips by 20 to get the f32 value, just to be used once all processing + // of the swf coords is completed and we want to output. + fn as_f32(&self) -> f32 { + self.0 as f32 / 20.0 + } +} + +impl Add for Twips { + type Output = Twips; + fn add(self, rhs: Twips) -> Self { + Twips(self.0 + rhs.0) + } +} + +#[derive(Copy, Clone, Debug, PartialEq)] +struct Point2 { + x: T, + y: T +} + +impl Point2 { + fn as_f32(self: Point2) -> Point2 { + Point2 { + x: self.x.as_f32(), + y: self.y.as_f32(), + } + } +} + +impl Add for Point2 { + type Output = Self; + fn add(self, rhs: Self) -> Self { + Point2 { x: self.x + rhs.x, y: self.y + rhs.y } + } +} + +enum Symbol { + Graphic(GraphicLayers), + // Timeline, // TODO(jon) +} + +pub struct Stage { + // TODO(jon): Support some kind of lazy frames iterator. + // frames: Timeline, + background_color: SRgb8, + width: i32, + height: i32, +} + +impl Stage { + pub fn width(&self) -> i32 { + self.width + } + + pub fn height(&self) -> i32 { + self.height + } + + pub fn background_color(&self) -> ColorF { + ColorU { + r: self.background_color.r, + g: self.background_color.g, + b: self.background_color.b, + a: 255, + }.to_f32() + } +} + + +pub struct SymbolLibrary(Vec); + +impl SymbolLibrary { + fn add_symbol(&mut self, symbol: Symbol) { + self.0.push(symbol); + } + + fn symbols(&self) -> &Vec { + &self.0 + } +} + +pub fn process_swf_tags(movie: &Movie) -> (SymbolLibrary, Stage) { + let mut symbol_library = SymbolLibrary(Vec::new()); + let stage_width = Twips(movie.header.frame_size.x_max); + let stage_height = Twips(movie.header.frame_size.y_max); + // let num_frames = movie.header.frame_count; + + let mut stage = Stage { + // frames: Timeline(Vec::new()), // TODO(jon) + background_color: SRgb8 { + r: 255, + g: 255, + b: 255 + }, + width: stage_width.as_f32() as i32, + height: stage_height.as_f32() as i32, + }; + + for tag in &movie.tags { + match tag { + Tag::SetBackgroundColor(SetBackgroundColor { color }) => { + stage.background_color = *color; + }, + Tag::DefineShape(shape) => { + symbol_library.add_symbol(Symbol::Graphic(shapes::decode_shape(&shape))); + // We will assume that symbol ids just go up, and are 1 based. + let symbol_id: SymbolId = shape.id; + debug_assert!(symbol_id as usize == symbol_library.0.len()); + } + _ => () + } + } + (symbol_library, stage) +} + +#[allow(irrefutable_let_patterns)] +pub fn draw_paths_into_scene(library: &SymbolLibrary, scene: &mut Scene) { + for symbol in library.symbols() { + // NOTE: Right now symbols only contain graphics. + if let Symbol::Graphic(graphic) = symbol { + for style_layer in graphic.layers() { + debug_assert_ne!(style_layer.shapes().len(), 0); + let mut path = Outline::new(); + let paint_id = scene.push_paint(&style_layer.fill()); + + for shape in style_layer.shapes() { + let mut contour = Contour::new(); + let Point2 { x, y } = shape.outline.first().unwrap().from.as_f32(); + contour.push_endpoint(Vector2F::new(x, y)); + for segment in &shape.outline { + let Point2 { x, y } = segment.to.as_f32(); + match segment.ctrl { + Some(ctrl) => { + let Point2 { x: ctrl_x, y: ctrl_y } = ctrl.as_f32(); + contour.push_quadratic( + Vector2F::new(ctrl_x, ctrl_y), + Vector2F::new(x, y) + ); + } + None => { + contour.push_endpoint(Vector2F::new(x, y)); + }, + } + } + if shape.is_closed() { + // NOTE: I'm not sure if this really does anything in this context, + // since all our closed shapes already have coincident start and end points. + contour.close(); + } + path.push_contour(contour); + } + + if let PaintOrLine::Line(line) = style_layer.kind() { + let mut stroke_to_fill = OutlineStrokeToFill::new(&path, StrokeStyle { + line_width: line.width.as_f32(), + line_cap: line.cap, + line_join: line.join, + }); + stroke_to_fill.offset(); + path = stroke_to_fill.into_outline(); + } + + scene.push_path(PathObject::new( + path, + paint_id, + String::new() + )); + } + } + } +} diff --git a/flash/src/shapes.rs b/flash/src/shapes.rs new file mode 100644 index 00000000..cf724f50 --- /dev/null +++ b/flash/src/shapes.rs @@ -0,0 +1,616 @@ +use pathfinder_renderer::paint::Paint; +use pathfinder_geometry::stroke::{LineJoin, LineCap}; +use crate::{Twips, Point2}; +use std::mem; +use std::cmp::Ordering; +use swf_tree::{ + FillStyle, + StraightSRgba8, + LineStyle, + fill_styles, + JoinStyle, + CapStyle, + join_styles, + ShapeRecord, + shape_records, + Vector2D +}; +use pathfinder_geometry::color::ColorU; +use swf_tree::tags::DefineShape; + +#[derive(Clone, Copy, Debug)] +pub(crate) struct LineSegment { + pub(crate) from: Point2, + pub(crate) to: Point2, + pub(crate) ctrl: Option>, +} + +impl LineSegment { + fn reverse(&mut self) { + let tmp = self.from; + self.from = self.to; + self.to = tmp; + } +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub(crate) enum LineDirection { + Left, + Right, +} + +impl LineDirection { + fn reverse(&mut self) { + *self = match self { + LineDirection::Right => LineDirection::Left, + LineDirection::Left => LineDirection::Right + }; + } +} + +#[derive(Clone, Debug)] +pub(crate) struct Shape { + pub(crate) outline: Vec, // Could be Vec<(start, end)> + direction: LineDirection, + reversed: bool, +} + +impl Shape { + pub fn new_with_direction(direction: LineDirection) -> Shape { + Shape { + direction, + outline: Vec::new(), + reversed: false, + } + } + + fn prepend_shape(&mut self, shape: &mut Shape) { + shape.append_shape(&self); + mem::swap(&mut self.outline, &mut shape.outline); + } + + fn append_shape(&mut self, shape: &Shape) { + self.outline.extend_from_slice(&shape.outline); + } + + fn add_line_segment(&mut self, segment: LineSegment) { + self.outline.push(segment); + } + + #[inline] + fn len(&self) -> usize { + self.outline.len() + } + + #[inline] + fn first(&self) -> &LineSegment { + &self.outline.first().unwrap() + } + + #[inline] + fn last(&self) -> &LineSegment { + &self.outline.last().unwrap() + } + + #[inline] + fn comes_before(&self, other: &Shape) -> bool { + self.last().to == other.first().from + } + + #[inline] + fn comes_after(&self, other: &Shape) -> bool { + self.first().from == other.last().to + } + + #[inline] + pub(crate) fn is_closed(&self) -> bool { + self.len() > 1 && self.comes_after(self) + } + + fn reverse(&mut self) { + self.reversed = !self.reversed; + self.direction.reverse(); + for segment in &mut self.outline { + segment.reverse(); + } + self.outline.reverse(); + } +} + +pub(crate) struct SwfLineStyle { + color: Paint, + pub(crate) width: Twips, + pub(crate) join: LineJoin, + pub(crate) cap: LineCap, +} + +pub(crate) enum PaintOrLine { + Paint(Paint), + Line(SwfLineStyle), +} + +pub(crate) struct StyleLayer { + fill: PaintOrLine, + // TODO(jon): Maybe shapes are actually slices into a single buffer, then we don't + // need to realloc anything, we're just shuffling shapes around? + shapes: Vec, +} + +impl StyleLayer { + pub(crate) fn kind(&self) -> &PaintOrLine { + &self.fill + } + + fn is_fill(&self) -> bool { + match &self.fill { + PaintOrLine::Paint(_) => true, + PaintOrLine::Line(_) => false, + } + } + + pub(crate) fn fill(&self) -> Paint { + match &self.fill { + PaintOrLine::Paint(paint) => *paint, + PaintOrLine::Line(line) => line.color, + } + } + + fn push_new_shape(&mut self, direction: LineDirection) { + if let Some(prev_shape) = self.shapes.last_mut() { + // Check that the previous shape was actually used, otherwise reuse it. + if prev_shape.len() != 0 { + self.shapes.push(Shape::new_with_direction(direction)) + } else { + prev_shape.direction = direction; + } + } else { + self.shapes.push(Shape::new_with_direction(direction)) + } + } + + pub(crate) fn shapes(&self) -> &Vec { + &self.shapes + } + + fn shapes_mut(&mut self) -> &mut Vec { + &mut self.shapes + } + + fn current_shape_mut(&mut self) -> &mut Shape { + self.shapes.last_mut().unwrap() + } + + fn consolidate_edges(&mut self) { + // Reverse left fill shape fragments in place. + { + self.shapes + .iter_mut() + .filter(|frag| frag.direction == LineDirection::Left) + .for_each(|frag| frag.reverse()); + } + + // Sort shapes into [closed...open] + if self.is_fill() { + // I think sorting is only necessary when we want to have closed shapes, + // lines don't really need this? + self.shapes.sort_unstable_by(|a, b| { + match (a.is_closed(), b.is_closed()) { + (true, true) | (false, false) => Ordering::Equal, + (true, false) => Ordering::Less, + (false, true) => Ordering::Greater, + } + }); + } + + // A cursor at the index of the first unclosed shape, if any. + let first_open_index = self.shapes + .iter() + .position(|frag| !frag.is_closed()); + + if let Some(first_open_index) = first_open_index { + if self.shapes.len() - first_open_index >= 2 { + // TODO(jon): This might be sped up by doing it in a way that we don't have + // to allocate more vecs? + // Also, maybe avoid path reversal, and just flag the path as reversed and iterate it + // backwards. + let unmatched_pieces = find_matches(first_open_index, &mut self.shapes, false); + if let Some(mut unmatched_pieces) = unmatched_pieces { + if self.is_fill() { + // If they didn't match before, they're probably parts of inner shapes + // and should be reversed again so they have correct winding + let unclosed = find_matches(0, &mut unmatched_pieces, true); + // If it's a shape we should always be able to close it. + debug_assert!(unclosed.is_none()); + } + for dropped in &mut unmatched_pieces { + dropped.reverse(); + } + self.shapes.extend_from_slice(&unmatched_pieces); + } + // FIXME(jon): Sometimes we don't get the correct winding of internal closed shapes, + // need to figure out why this happens. + } + } + } +} + + +fn get_new_styles<'a>( + fills: &'a Vec, + lines: &'a Vec +) -> impl Iterator + 'a { + // This enforces the order that fills and line groupings are added in. + // Fills always come first. + fills.iter().filter_map(|fill_style| { + match fill_style { + FillStyle::Solid( + fill_styles::Solid { + color: StraightSRgba8 { + r, + g, + b, + a + } + } + ) => { + Some(PaintOrLine::Paint(Paint { + color: ColorU { + r: *r, + g: *g, + b: *b, + a: *a + } + })) + }, + _ => unimplemented!("Unimplemented fill style") + } + }).chain( + lines.iter().filter_map(|LineStyle { + width, + fill, + join, + start_cap, + end_cap: _, + /* + TODO(jon): Handle these cases? + pub no_h_scale: bool, + pub no_v_scale: bool, + pub no_close: bool, + pub pixel_hinting: bool, + */ + .. + }| { + if let FillStyle::Solid(fill_styles::Solid { + color: StraightSRgba8 { + r, + g, + b, + a + } + }) = fill { + // NOTE: PathFinder doesn't support different cap styles for start and end of + // strokes, so lets assume that they're always the same for the inputs we care about. + // Alternately, we split a line in two with a diff cap style for each. + // assert_eq!(start_cap, end_cap); + Some(PaintOrLine::Line(SwfLineStyle { + width: Twips(*width as i32), + color: Paint { color: ColorU { r: *r, g: *g, b: *b, a: *a } }, + join: match join { + JoinStyle::Bevel => LineJoin::Bevel, + JoinStyle::Round => LineJoin::Round, + JoinStyle::Miter(join_styles::Miter { limit }) => { + LineJoin::Miter(*limit as f32) + }, + }, + cap: match start_cap { + CapStyle::None => LineCap::Butt, + CapStyle::Square => LineCap::Square, + CapStyle::Round => LineCap::Round, + }, + })) + } else { + unimplemented!("unimplemented line fill style"); + } + }) + ) +} + +pub(crate) fn decode_shape(shape: &DefineShape) -> GraphicLayers { + let DefineShape { + shape, + // id, + // has_fill_winding, NOTE(jon): Could be important for some inputs? + // has_non_scaling_strokes, + // has_scaling_strokes, + .. + } = shape; + let mut graphic = GraphicLayers::new(); + let mut current_line_style = None; + let mut current_left_fill = None; + let mut current_right_fill = None; + let mut prev_pos = None; + + let mut some_fill_set = false; + let mut both_fills_set; + let mut both_fills_same = false; + let mut both_fills_set_and_same = false; + + // Create style groups for initially specified fills and lines. + for fills_or_line in get_new_styles(&shape.initial_styles.fill, &shape.initial_styles.line) { + match fills_or_line { + PaintOrLine::Paint(fill) => graphic.begin_fill_style(fill), + PaintOrLine::Line(line) => graphic.begin_line_style(line), + } + } + + for record in &shape.records { + match record { + ShapeRecord::StyleChange( + shape_records::StyleChange { + move_to, + new_styles, + line_style, + left_fill, + right_fill, + } + ) => { + // Start a whole new style grouping. + if let Some(new_style) = new_styles { + // Consolidate current style grouping and begin a new one. + graphic.end_style_group(); + graphic.begin_style_group(); + for fills_or_line in get_new_styles(&new_style.fill, &new_style.line) { + match fills_or_line { + PaintOrLine::Paint(fill) => graphic.begin_fill_style(fill), + PaintOrLine::Line(line) => graphic.begin_line_style(line), + } + } + } + + // If there's a change in right fill + if let Some(fill_id) = right_fill { + if *fill_id == 0 { + current_right_fill = None; + } else { + current_right_fill = Some(*fill_id); + graphic + .with_fill_style_mut(*fill_id) + .unwrap() + .push_new_shape(LineDirection::Right); + } + } + // If there's a change in left fill + if let Some(fill_id) = left_fill { + if *fill_id == 0 { + current_left_fill = None; + } else { + current_left_fill = Some(*fill_id); + graphic + .with_fill_style_mut(*fill_id) + .unwrap() + .push_new_shape(LineDirection::Left); + } + } + + some_fill_set = current_left_fill.is_some() || current_right_fill.is_some(); + both_fills_set = current_left_fill.is_some() && current_right_fill.is_some(); + both_fills_same = current_left_fill == current_right_fill; + both_fills_set_and_same = both_fills_set && both_fills_same; + + // If there's a change in line style + if let Some(style_id) = line_style { + if *style_id == 0 { + current_line_style = None; + } else { + current_line_style = Some(*style_id); + graphic + .with_line_style_mut(*style_id) + .unwrap() + .push_new_shape(LineDirection::Right); + } + } + + // Move to, start new shape fragments with the current styles. + if let Some(Vector2D { x, y }) = move_to { + let to: Point2 = Point2 { x: Twips(*x), y: Twips(*y) }; + prev_pos = Some(to); + + // If we didn't start a new shape for the current fill due to a fill + // style change earlier, we definitely want to start a new shape now, + // since each move_to command indicates a new shape fragment. + if let Some(current_right_fill) = current_right_fill { + graphic + .with_fill_style_mut(current_right_fill) + .unwrap() + .push_new_shape(LineDirection::Right); + } + if let Some(current_left_fill) = current_left_fill { + graphic + .with_fill_style_mut(current_left_fill) + .unwrap() + .push_new_shape(LineDirection::Left); + } + if let Some(current_line_style) = current_line_style { + // TODO(jon): Does the direction of this line depend on the current + // fill directions? + graphic + .with_line_style_mut(current_line_style) + .unwrap() + .push_new_shape(LineDirection::Right); + } + } + }, + ShapeRecord::Edge( + shape_records::Edge { + delta, + control_delta, + } + ) => { + let from = prev_pos.unwrap(); + let to = Point2 { + x: from.x + Twips(delta.x), + y: from.y + Twips(delta.y) + }; + prev_pos = Some(to); + let new_segment = LineSegment { + from, + to, + ctrl: control_delta.map(|Vector2D { x, y }| { + Point2 { + x: from.x + Twips(x), + y: from.y + Twips(y), + } + }), + }; + if some_fill_set && !both_fills_same { + for fill_id in [ + current_right_fill, + current_left_fill + ].iter() { + if let Some(fill_id) = fill_id { + graphic + .with_fill_style_mut(*fill_id) + .unwrap() + .current_shape_mut() + .add_line_segment(new_segment); + } + } + } else if both_fills_set_and_same { + for (fill_id, direction) in [ + (current_right_fill, LineDirection::Right), + (current_left_fill, LineDirection::Left) + ].iter() { + // NOTE: If both left and right fill are set the same, + // then we don't record the edge as part of the current shape; + // it's will just be an internal stroke inside an otherwise solid + // shape, and recording these edges as part of the shape means that + // we can't determine the closed shape outline later. + if let Some(fill_id) = fill_id { + graphic + .with_fill_style_mut(*fill_id) + .unwrap() + .push_new_shape(*direction); + } + } + } + if let Some(current_line_style) = current_line_style { + graphic + .with_line_style_mut(current_line_style) + .unwrap() + .current_shape_mut() + .add_line_segment(new_segment); + } + } + } + } + // NOTE: Consolidate current group of styles, joining edges of shapes/strokes where + // possible and forming closed shapes. In swf, all filled shapes should always be closed, + // so there will always be a solution for joining shape line segments together so that + // the start point and end point are coincident. + graphic.end_style_group(); + graphic +} + +fn find_matches( + mut first_open_index: usize, + shapes: &mut Vec, + reverse: bool +) -> Option> { + let mut dropped_pieces = None; + while first_open_index < shapes.len() { + // Take the last unclosed value, and try to join it onto + // one of the other unclosed values. + let mut last = shapes.pop().unwrap(); + if reverse { + last.reverse(); + } + let mut found_match = false; + for i in first_open_index..shapes.len() { + let fragment = &mut shapes[i]; + debug_assert!(!fragment.is_closed()); + if last.comes_after(fragment) { + // NOTE(jon): We do realloc quite a bit here, I wonder if it's worth trying + // to avoid that? Could do it with another level of indirection, where an outline + // is a list of fragments. + + // println!("app ({}, {})", last.reversed, fragment.reversed); + fragment.append_shape(&last); + found_match = true; + } else if last.comes_before(fragment) { + // println!("pre ({}, {})", last.reversed, fragment.reversed); + fragment.prepend_shape(&mut last); + found_match = true; + } + if found_match { + if fragment.is_closed() { + // Move the shape that was just closed to the left side of the current slice, + // and advance the cursor. + shapes.swap(first_open_index, i); + first_open_index += 1; + } + break; + } + } + if !found_match { + // Have we tried matching a reversed version of this segment? + // move last back onto the array, it will never be closed, presumably because + // it's a set of line segments rather than a shape that needs to be closed. + let dropped_pieces: &mut Vec = dropped_pieces.get_or_insert(Vec::new()); + dropped_pieces.push(last); + } + } + dropped_pieces +} + +pub(crate) struct GraphicLayers { + style_layers: Vec, + base_layer_offset: usize, + stroke_layer_offset: Option, +} + +impl GraphicLayers { + fn new() -> GraphicLayers { + GraphicLayers { style_layers: Vec::new(), stroke_layer_offset: None, base_layer_offset: 0 } + } + + fn begin_style_group(&mut self) { + self.stroke_layer_offset = None; + self.base_layer_offset = self.style_layers.len(); + } + + fn begin_fill_style(&mut self, fill: Paint) { + self.style_layers.push(StyleLayer { fill: PaintOrLine::Paint(fill), shapes: Vec::new() }) + } + + fn begin_line_style(&mut self, line: SwfLineStyle) { + if self.stroke_layer_offset.is_none() { + self.stroke_layer_offset = Some(self.style_layers.len()); + } + self.style_layers.push(StyleLayer { fill: PaintOrLine::Line(line), shapes: Vec::new() }) + } + + fn with_fill_style_mut(&mut self, fill_id: usize) -> Option<&mut StyleLayer> { + self.style_layers.get_mut(self.base_layer_offset + fill_id - 1) + } + + fn with_line_style_mut(&mut self, line_id: usize) -> Option<&mut StyleLayer> { + self.style_layers.get_mut((self.stroke_layer_offset.unwrap() + line_id) - 1) + } + + pub(crate) fn layers(&self) -> &Vec { + &self.style_layers + } + + fn end_style_group(&mut self) { + for style_layer in &mut self.style_layers[self.base_layer_offset..] { + // There can be an unused style group at the end of each layer, which we should remove. + if let Some(last) = style_layer.shapes().last() { + if last.len() == 0 { + style_layer.shapes_mut().pop(); + } + } + style_layer.consolidate_edges(); + } + } +} + diff --git a/flash/src/timeline.rs b/flash/src/timeline.rs new file mode 100644 index 00000000..662dba00 --- /dev/null +++ b/flash/src/timeline.rs @@ -0,0 +1,32 @@ +struct PlacementInfo { + symbol_id: u32, + translate_x: Twips, + translate_y: Twips, +} + +struct Timeline(Vec); + +impl Timeline { + fn first(&self) -> &Frame { + &self.0[0] + } + + fn last(&self) -> &Frame { + &self.0[self.0.len() - 1] + } + + fn first_mut(&mut self) -> &mut Frame { + &mut self.0[0] + } + + fn last_mut(&mut self) -> &mut Frame { + let last = self.0.len() - 1; + &mut self.0[last] + } +} + +struct Frame { + duration_frames_initial: u16, + duration_remaining_frames: u16, + placements: Vec +} From b17d6c605ab13c3e2cac1e9fc961c478dd6013ce Mon Sep 17 00:00:00 2001 From: jonathanhardie Date: Wed, 19 Jun 2019 11:25:26 +1200 Subject: [PATCH 02/14] Remove incorrect debug assertion --- Cargo.lock | 162 ++++++++++++++++++++++++++++++++++++++------ flash/src/shapes.rs | 1 - 2 files changed, 140 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18ff3a79..36119c38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,7 +44,7 @@ name = "approx" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -90,7 +90,7 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -98,7 +98,7 @@ name = "backtrace" 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)", + "autocfg 0.1.4 (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.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", @@ -143,6 +143,11 @@ name = "block" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.1" @@ -233,7 +238,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -348,6 +353,14 @@ dependencies = [ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crc32fast" version = "1.2.0" @@ -518,7 +531,7 @@ 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)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -570,7 +583,7 @@ name = "float-cmp" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -796,6 +809,11 @@ dependencies = [ "gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "half" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "harfbuzz" version = "0.3.1" @@ -827,6 +845,11 @@ dependencies = [ "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "humantime" version = "1.2.0" @@ -847,7 +870,7 @@ dependencies = [ "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)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -861,7 +884,7 @@ dependencies = [ "lzw 0.10.0 (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.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)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "png 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -989,7 +1012,7 @@ name = "line_drawing" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1031,7 +1054,7 @@ 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.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1042,6 +1065,16 @@ dependencies = [ "lyon_geom 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lzma-rs" +version = "0.1.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)", + "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lzw" version = "0.10.0" @@ -1108,6 +1141,15 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nom" +version = "4.2.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)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num" version = "0.1.42" @@ -1115,7 +1157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1133,7 +1175,7 @@ name = "num-integer" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1142,7 +1184,7 @@ version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1151,7 +1193,7 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1160,13 +1202,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "num_cpus" @@ -1194,7 +1239,7 @@ name = "ordered-float" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1291,6 +1336,18 @@ dependencies = [ "usvg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pathfinder_flash" +version = "0.1.0" +dependencies = [ + "pathfinder_geometry 0.3.0", + "pathfinder_gl 0.1.0", + "pathfinder_gpu 0.1.0", + "pathfinder_renderer 0.1.0", + "swf-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "swf-tree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pathfinder_geometry" version = "0.3.0" @@ -1512,7 +1569,7 @@ name = "rand" 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)", + "autocfg 0.1.4 (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)", @@ -1530,7 +1587,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1591,7 +1648,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1936,6 +1993,58 @@ dependencies = [ "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "swf-fixed" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "swf-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "half 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lzma-rs 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "swf-fixed 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "swf-tree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "swf-tree" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "swf-fixed 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "swf_basic" +version = "0.1.0" +dependencies = [ + "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_flash 0.1.0", + "pathfinder_geometry 0.3.0", + "pathfinder_gl 0.1.0", + "pathfinder_gpu 0.1.0", + "pathfinder_renderer 0.1.0", + "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)", + "swf-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "swf-tree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.34" @@ -2271,13 +2380,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "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 autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" "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 build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "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" @@ -2296,6 +2406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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 crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "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" @@ -2340,9 +2451,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glutin_gles2_sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "89996c30857ae1b4de4b5189abf1ea822a20a9fe9e1c93e5e7b862ff0bdd5cdf" "checksum glutin_glx_sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1290a5ca5e46fcfa7f66f949cc9d9194b2cb6f2ed61892c8c2b82343631dba57" "checksum glutin_wgl_sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f801bbc91efc22dd1c4818a47814fc72bf74d024510451b119381579bfa39021" +"checksum half 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9353c2a89d550b58fa0061d8ed8d002a7d8cdf2494eb0e432859bd3a9e543836" "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 hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "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.1 (registry+https://github.com/rust-lang/crates.io-index)" = "293e54ce142a936a39da748ba8178ae6aa1914b82d846a4278f11590c89bf116" @@ -2368,6 +2481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "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 lzma-rs 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9550ba35a4d6bb6be7f273bce93af3a3141c517bf7d7298763a7149e1bdb9af5" "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 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" @@ -2377,13 +2491,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98" "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 nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "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-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "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" @@ -2453,6 +2568,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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 swf-fixed 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3c575807f18641c5e079568b53630a46baf441da57caccd9ced9a9ee70f941" +"checksum swf-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b6349830c1ed5d26b97d801e3fb8664556e12a01560e3479e3961e8f5675a05" +"checksum swf-tree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c075cea0328cc5f6ee694bcd1c43534d1186a730d79258b10735f8f08e2f1baa" "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" diff --git a/flash/src/shapes.rs b/flash/src/shapes.rs index cf724f50..73d55603 100644 --- a/flash/src/shapes.rs +++ b/flash/src/shapes.rs @@ -527,7 +527,6 @@ fn find_matches( let mut found_match = false; for i in first_open_index..shapes.len() { let fragment = &mut shapes[i]; - debug_assert!(!fragment.is_closed()); if last.comes_after(fragment) { // NOTE(jon): We do realloc quite a bit here, I wonder if it's worth trying // to avoid that? Could do it with another level of indirection, where an outline From 4d53ab60fc895926634b4a41b7367cd8049c64eb Mon Sep 17 00:00:00 2001 From: Jon Hardie Date: Fri, 21 Jun 2019 11:10:26 +1200 Subject: [PATCH 03/14] [WIP] Updating to master --- examples/swf_basic/src/main.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/examples/swf_basic/src/main.rs b/examples/swf_basic/src/main.rs index ea7f8b73..ed5e9f9d 100644 --- a/examples/swf_basic/src/main.rs +++ b/examples/swf_basic/src/main.rs @@ -12,11 +12,11 @@ use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; use pathfinder_geometry::basic::rect::RectF; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::FilesystemResourceLoader; -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, RenderTransform}; +use pathfinder_renderer::gpu::renderer::Renderer; +use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions}; +use pathfinder_renderer::options::{RenderTransform, BuildOptions}; use sdl2::event::Event; use sdl2::keyboard::Keycode; use sdl2::video::GLProfile; @@ -50,7 +50,7 @@ fn main() { // a lot more geometry. I think a more likely explanation for the choice is that it was // done to reduce overdraw in the software rasterizer running on late 90's era hardware? // Indeed, this mode gives pathfinders' occlusion culling pass nothing to do! - let default_tiger = include_bytes!("../swf/tiger-flat.swf"); + //let default_tiger = include_bytes!("../swf/tiger-flat.swf"); // NOTE(jon): This is a version of the same graphic cut and pasted into the Flash authoring // tool from the SVG version loaded in Illustrator. When layered graphics are pasted @@ -58,7 +58,7 @@ fn main() { // They are still presented as being on a single timeline layer. // They will be drawn back to front in much the same way as the SVG version. - //let default_tiger = include_bytes!("../tiger.swf"); + let default_tiger = include_bytes!("../swf/tiger.swf"); swf_bytes = Vec::from(&default_tiger[..]); } @@ -98,9 +98,12 @@ fn main() { window.gl_make_current(&gl_context).unwrap(); // Create a Pathfinder renderer. - let mut renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0), - &FilesystemResourceLoader::locate(), - DestFramebuffer::full_window(pixel_size)); + let mut renderer = Renderer::new( + GLDevice::new(GLVersion::GL3, 0), + &FilesystemResourceLoader::locate(), + DestFramebuffer::full_window(pixel_size), + RendererOptions { background_color: Some(stage.background_color()) } + ); // Clear to swf stage background color. let mut scene = Scene::new(); scene.set_view_box(RectF::new( @@ -112,17 +115,13 @@ fn main() { draw_paths_into_scene(&library, &mut scene); // Render the canvas to screen. - renderer.device.clear(&ClearParams { - color: Some(stage.background_color()), - ..ClearParams::default() - }); let scene = SceneProxy::from_scene(scene, RayonExecutor); - let mut render_options = RenderOptions::default(); + let mut build_options = BuildOptions::default(); let scale_transform = Transform2DF::from_scale( Vector2F::new(device_pixel_ratio, device_pixel_ratio) ); - render_options.transform = RenderTransform::Transform2D(scale_transform); - scene.build_and_render(&mut renderer, render_options); + build_options.transform = RenderTransform::Transform2D(scale_transform); + scene.build_and_render(&mut renderer, build_options); window.gl_swap_window(); // Wait for a keypress. From f730e5d2db2b54c3bc654b0a6f7783280953432b Mon Sep 17 00:00:00 2001 From: Jon Hardie Date: Fri, 21 Jun 2019 11:12:10 +1200 Subject: [PATCH 04/14] [WIP] Remove incorrect debug assertion --- flash/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/flash/src/lib.rs b/flash/src/lib.rs index fdc8b57e..34bf5518 100644 --- a/flash/src/lib.rs +++ b/flash/src/lib.rs @@ -155,7 +155,6 @@ pub fn draw_paths_into_scene(library: &SymbolLibrary, scene: &mut Scene) { // NOTE: Right now symbols only contain graphics. if let Symbol::Graphic(graphic) = symbol { for style_layer in graphic.layers() { - debug_assert_ne!(style_layer.shapes().len(), 0); let mut path = Outline::new(); let paint_id = scene.push_paint(&style_layer.fill()); From de0662e08e85d9b23a85f073303b925b9be15b36 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 07:24:06 -0700 Subject: [PATCH 05/14] Update `spirv-cross` to upstream master. A fix has been merged for the issue that was breaking Pathfinder, so we can now use the master branch. --- resources/shaders/gl3/reproject.vs.glsl | 1 + resources/shaders/metal/debug_texture.fs.metal | 6 +++--- resources/shaders/metal/post.fs.metal | 10 +++++----- resources/shaders/metal/tile_alpha_multicolor.vs.metal | 10 +++++----- resources/shaders/metal/tile_solid_multicolor.vs.metal | 8 ++++---- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/resources/shaders/gl3/reproject.vs.glsl b/resources/shaders/gl3/reproject.vs.glsl index 35a3db40..f32005f2 100644 --- a/resources/shaders/gl3/reproject.vs.glsl +++ b/resources/shaders/gl3/reproject.vs.glsl @@ -27,6 +27,7 @@ void main(){ + gl_Position = uNewTransform * vec4(position, 0.0, 1.0); } diff --git a/resources/shaders/metal/debug_texture.fs.metal b/resources/shaders/metal/debug_texture.fs.metal index 9949a558..80a811f3 100644 --- a/resources/shaders/metal/debug_texture.fs.metal +++ b/resources/shaders/metal/debug_texture.fs.metal @@ -6,9 +6,9 @@ using namespace metal; struct spvDescriptorSetBuffer0 { - constant float4* uColor [[id(0)]]; - texture2d uTexture [[id(1)]]; - sampler uTextureSmplr [[id(2)]]; + texture2d uTexture [[id(0)]]; + sampler uTextureSmplr [[id(1)]]; + constant float4* uColor [[id(2)]]; }; struct main0_out diff --git a/resources/shaders/metal/post.fs.metal b/resources/shaders/metal/post.fs.metal index 989fd5d7..3c9502b4 100644 --- a/resources/shaders/metal/post.fs.metal +++ b/resources/shaders/metal/post.fs.metal @@ -8,12 +8,12 @@ using namespace metal; struct spvDescriptorSetBuffer0 { - constant float4* uKernel [[id(0)]]; - texture2d uGammaLUT [[id(1)]]; - texture2d uSource [[id(2)]]; - constant float2* uSourceSize [[id(3)]]; + texture2d uGammaLUT [[id(0)]]; + sampler uGammaLUTSmplr [[id(1)]]; + constant float4* uKernel [[id(2)]]; + texture2d uSource [[id(3)]]; sampler uSourceSmplr [[id(4)]]; - sampler uGammaLUTSmplr [[id(5)]]; + constant float2* uSourceSize [[id(5)]]; constant int* uGammaCorrectionEnabled [[id(6)]]; constant float4* uBGColor [[id(7)]]; constant float4* uFGColor [[id(8)]]; diff --git a/resources/shaders/metal/tile_alpha_multicolor.vs.metal b/resources/shaders/metal/tile_alpha_multicolor.vs.metal index bc25f729..7e62af78 100644 --- a/resources/shaders/metal/tile_alpha_multicolor.vs.metal +++ b/resources/shaders/metal/tile_alpha_multicolor.vs.metal @@ -9,11 +9,11 @@ using namespace metal; struct spvDescriptorSetBuffer0 { constant float2* uTileSize [[id(0)]]; - texture2d uPaintTexture [[id(1)]]; - constant float2* uViewBoxOrigin [[id(2)]]; - sampler uPaintTextureSmplr [[id(3)]]; - constant float2* uFramebufferSize [[id(4)]]; - constant float2* uStencilTextureSize [[id(5)]]; + constant float2* uViewBoxOrigin [[id(1)]]; + constant float2* uFramebufferSize [[id(2)]]; + constant float2* uStencilTextureSize [[id(3)]]; + texture2d uPaintTexture [[id(4)]]; + sampler uPaintTextureSmplr [[id(5)]]; }; struct main0_out diff --git a/resources/shaders/metal/tile_solid_multicolor.vs.metal b/resources/shaders/metal/tile_solid_multicolor.vs.metal index edfe17d0..573f5173 100644 --- a/resources/shaders/metal/tile_solid_multicolor.vs.metal +++ b/resources/shaders/metal/tile_solid_multicolor.vs.metal @@ -9,10 +9,10 @@ using namespace metal; struct spvDescriptorSetBuffer0 { constant float2* uTileSize [[id(0)]]; - texture2d uPaintTexture [[id(1)]]; - constant float2* uViewBoxOrigin [[id(2)]]; - sampler uPaintTextureSmplr [[id(3)]]; - constant float2* uFramebufferSize [[id(4)]]; + constant float2* uViewBoxOrigin [[id(1)]]; + constant float2* uFramebufferSize [[id(2)]]; + texture2d uPaintTexture [[id(3)]]; + sampler uPaintTextureSmplr [[id(4)]]; }; struct main0_out From 336f2ca30261edc00a88bfdba03595d7cd4087f6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 09:28:15 -0700 Subject: [PATCH 06/14] Rename `pathfinder_flash` to `pathfinder_swf` for consistency with other crates in the Rust Flash ecosystem --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 2 +- examples/swf_basic/Cargo.toml | 6 +++--- examples/swf_basic/src/main.rs | 2 +- {flash => swf}/Cargo.toml | 2 +- {flash => swf}/src/lib.rs | 2 +- {flash => swf}/src/shapes.rs | 10 ++++++++++ {flash => swf}/src/timeline.rs | 10 ++++++++++ 8 files changed, 40 insertions(+), 20 deletions(-) rename {flash => swf}/Cargo.toml (93%) rename {flash => swf}/src/lib.rs (99%) rename {flash => swf}/src/shapes.rs (98%) rename {flash => swf}/src/timeline.rs (59%) diff --git a/Cargo.lock b/Cargo.lock index ebab8efd..186eb4ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1416,18 +1416,6 @@ dependencies = [ "usvg 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pathfinder_flash" -version = "0.1.0" -dependencies = [ - "pathfinder_geometry 0.3.0", - "pathfinder_gl 0.1.0", - "pathfinder_gpu 0.1.0", - "pathfinder_renderer 0.1.0", - "swf-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "swf-tree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pathfinder_geometry" version = "0.3.0" @@ -1547,6 +1535,18 @@ dependencies = [ "usvg 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pathfinder_swf" +version = "0.1.0" +dependencies = [ + "pathfinder_geometry 0.3.0", + "pathfinder_gl 0.1.0", + "pathfinder_gpu 0.1.0", + "pathfinder_renderer 0.1.0", + "swf-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "swf-tree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pathfinder_text" version = "0.1.0" @@ -2127,11 +2127,11 @@ name = "swf_basic" version = "0.1.0" dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pathfinder_flash 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", "pathfinder_renderer 0.1.0", + "pathfinder_swf 0.1.0", "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)", "swf-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 305b8133..d11db85e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,12 +16,12 @@ members = [ "geometry", "gl", "gpu", - "flash", "lottie", "metal", "renderer", "simd", "svg", + "swf", "text", "ui", "utils/area-lut", diff --git a/examples/swf_basic/Cargo.toml b/examples/swf_basic/Cargo.toml index eb64fe17..ced4ed19 100644 --- a/examples/swf_basic/Cargo.toml +++ b/examples/swf_basic/Cargo.toml @@ -12,9 +12,6 @@ sdl2-sys = "0.32" swf-parser = "0.7.0" swf-tree = "0.7.0" -[dependencies.pathfinder_flash] -path = "../../flash" - [dependencies.pathfinder_geometry] path = "../../geometry" @@ -26,3 +23,6 @@ path = "../../gpu" [dependencies.pathfinder_renderer] path = "../../renderer" + +[dependencies.pathfinder_swf] +path = "../../swf" diff --git a/examples/swf_basic/src/main.rs b/examples/swf_basic/src/main.rs index ed5e9f9d..39959d99 100644 --- a/examples/swf_basic/src/main.rs +++ b/examples/swf_basic/src/main.rs @@ -21,7 +21,7 @@ use sdl2::event::Event; use sdl2::keyboard::Keycode; use sdl2::video::GLProfile; use pathfinder_renderer::scene::Scene; -use pathfinder_flash::{draw_paths_into_scene, process_swf_tags}; +use pathfinder_swf::{draw_paths_into_scene, process_swf_tags}; use std::env; use std::fs::read; use pathfinder_geometry::basic::transform2d::Transform2DF; diff --git a/flash/Cargo.toml b/swf/Cargo.toml similarity index 93% rename from flash/Cargo.toml rename to swf/Cargo.toml index 2dff909f..b063d864 100644 --- a/flash/Cargo.toml +++ b/swf/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pathfinder_flash" +name = "pathfinder_swf" version = "0.1.0" authors = ["Jon Hardie "] edition = "2018" diff --git a/flash/src/lib.rs b/swf/src/lib.rs similarity index 99% rename from flash/src/lib.rs rename to swf/src/lib.rs index 34bf5518..94bf0e35 100644 --- a/flash/src/lib.rs +++ b/swf/src/lib.rs @@ -1,4 +1,4 @@ -// pathfinder/flash/src/lib.rs +// pathfinder/swf/src/lib.rs // // Copyright © 2019 The Pathfinder Project Developers. // diff --git a/flash/src/shapes.rs b/swf/src/shapes.rs similarity index 98% rename from flash/src/shapes.rs rename to swf/src/shapes.rs index 73d55603..b2c94936 100644 --- a/flash/src/shapes.rs +++ b/swf/src/shapes.rs @@ -1,3 +1,13 @@ +// pathfinder/swf/src/shapes.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 pathfinder_renderer::paint::Paint; use pathfinder_geometry::stroke::{LineJoin, LineCap}; use crate::{Twips, Point2}; diff --git a/flash/src/timeline.rs b/swf/src/timeline.rs similarity index 59% rename from flash/src/timeline.rs rename to swf/src/timeline.rs index 662dba00..e3f684b3 100644 --- a/flash/src/timeline.rs +++ b/swf/src/timeline.rs @@ -1,3 +1,13 @@ +// pathfinder/swf/src/timeline.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. + struct PlacementInfo { symbol_id: u32, translate_x: Twips, From b16300bf0266acabe165d25d4b7bc9da8c99c582 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 09:32:48 -0700 Subject: [PATCH 07/14] Move the SWF assets into `resources/`. --- examples/swf_basic/src/main.rs | 9 +++++---- .../swf_basic => resources}/swf/tiger-flat.swf | Bin {examples/swf_basic => resources}/swf/tiger.swf | Bin 3 files changed, 5 insertions(+), 4 deletions(-) rename {examples/swf_basic => resources}/swf/tiger-flat.swf (100%) rename {examples/swf_basic => resources}/swf/tiger.swf (100%) diff --git a/examples/swf_basic/src/main.rs b/examples/swf_basic/src/main.rs index 39959d99..a06d7f79 100644 --- a/examples/swf_basic/src/main.rs +++ b/examples/swf_basic/src/main.rs @@ -11,7 +11,7 @@ use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; use pathfinder_geometry::basic::rect::RectF; use pathfinder_gl::{GLDevice, GLVersion}; -use pathfinder_gpu::resources::FilesystemResourceLoader; +use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; use pathfinder_renderer::concurrent::rayon::RayonExecutor; use pathfinder_renderer::concurrent::scene_proxy::SceneProxy; use pathfinder_renderer::gpu::renderer::Renderer; @@ -27,6 +27,8 @@ use std::fs::read; use pathfinder_geometry::basic::transform2d::Transform2DF; fn main() { + let resource_loader = FilesystemResourceLoader::locate(); + let swf_bytes; if let Some(path) = env::args().skip(1).next() { match read(path) { @@ -50,7 +52,6 @@ fn main() { // a lot more geometry. I think a more likely explanation for the choice is that it was // done to reduce overdraw in the software rasterizer running on late 90's era hardware? // Indeed, this mode gives pathfinders' occlusion culling pass nothing to do! - //let default_tiger = include_bytes!("../swf/tiger-flat.swf"); // NOTE(jon): This is a version of the same graphic cut and pasted into the Flash authoring // tool from the SVG version loaded in Illustrator. When layered graphics are pasted @@ -58,7 +59,7 @@ fn main() { // They are still presented as being on a single timeline layer. // They will be drawn back to front in much the same way as the SVG version. - let default_tiger = include_bytes!("../swf/tiger.swf"); + let default_tiger = resource_loader.slurp("swf/tiger.swf").unwrap(); swf_bytes = Vec::from(&default_tiger[..]); } @@ -100,7 +101,7 @@ fn main() { // Create a Pathfinder renderer. let mut renderer = Renderer::new( GLDevice::new(GLVersion::GL3, 0), - &FilesystemResourceLoader::locate(), + &resource_loader, DestFramebuffer::full_window(pixel_size), RendererOptions { background_color: Some(stage.background_color()) } ); diff --git a/examples/swf_basic/swf/tiger-flat.swf b/resources/swf/tiger-flat.swf similarity index 100% rename from examples/swf_basic/swf/tiger-flat.swf rename to resources/swf/tiger-flat.swf diff --git a/examples/swf_basic/swf/tiger.swf b/resources/swf/tiger.swf similarity index 100% rename from examples/swf_basic/swf/tiger.swf rename to resources/swf/tiger.swf From 431dcf3d2e884e5a241e65f68d1685963deb2d6f Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 10:06:19 -0700 Subject: [PATCH 08/14] Rename `pathfinder_geometry::basic` to simply `pathfinder_geometry`, and move the remaining code in that crate to a new crate, `pathfinder_content` The old hierarchy was confusing. --- Cargo.lock | 32 ++++- Cargo.toml | 1 + c/Cargo.toml | 3 + c/src/lib.rs | 46 ++++--- canvas/Cargo.toml | 3 + canvas/src/lib.rs | 20 +-- content/Cargo.toml | 17 +++ {geometry => content}/src/clip.rs | 10 +- {geometry => content}/src/color.rs | 0 {geometry => content}/src/dash.rs | 0 {geometry => content}/src/dilation.rs | 4 +- .../src/basic/mod.rs => content/src/lib.rs | 26 +++- {geometry => content}/src/orientation.rs | 0 {geometry => content}/src/outline.rs | 14 +- {geometry => content}/src/segment.rs | 10 +- {geometry => content}/src/stroke.rs | 10 +- content/src/transform.rs | 124 ++++++++++++++++++ demo/android/rust/src/lib.rs | 4 +- demo/common/Cargo.toml | 3 + demo/common/src/camera.rs | 8 +- demo/common/src/lib.rs | 10 +- demo/common/src/renderer.rs | 8 +- demo/common/src/ui.rs | 4 +- demo/common/src/window.rs | 6 +- demo/magicleap/Cargo.toml | 3 + demo/magicleap/src/display.rs | 8 +- demo/magicleap/src/glwindow.rs | 8 +- demo/magicleap/src/immersive.rs | 14 +- demo/magicleap/src/lib.rs | 10 +- demo/magicleap/src/magicleap.rs | 12 +- demo/native/src/main.rs | 4 +- examples/canvas_glutin_minimal/Cargo.toml | 3 + examples/canvas_glutin_minimal/src/main.rs | 6 +- examples/canvas_metal_minimal/Cargo.toml | 3 + examples/canvas_metal_minimal/src/main.rs | 6 +- examples/canvas_minimal/Cargo.toml | 3 + examples/canvas_minimal/src/main.rs | 6 +- examples/canvas_moire/Cargo.toml | 3 + examples/canvas_moire/src/main.rs | 4 +- examples/canvas_text/Cargo.toml | 3 + examples/canvas_text/src/main.rs | 4 +- examples/swf_basic/src/main.rs | 6 +- geometry/Cargo.toml | 5 - geometry/src/lib.rs | 26 +--- geometry/src/{basic => }/line_segment.rs | 4 +- geometry/src/{basic => }/rect.rs | 2 +- geometry/src/{basic => }/transform2d.rs | 63 +-------- geometry/src/{basic => }/transform3d.rs | 66 +--------- geometry/src/unit_vector.rs | 2 +- geometry/src/{basic => }/vector.rs | 0 gl/src/lib.rs | 4 +- gpu/Cargo.toml | 3 + gpu/src/lib.rs | 8 +- metal/src/lib.rs | 4 +- renderer/Cargo.toml | 3 + renderer/src/builder.rs | 6 +- renderer/src/concurrent/scene_proxy.rs | 2 +- renderer/src/gpu/debug.rs | 4 +- renderer/src/gpu/options.rs | 6 +- renderer/src/gpu/renderer.rs | 8 +- renderer/src/gpu_data.rs | 6 +- renderer/src/options.rs | 10 +- renderer/src/paint.rs | 4 +- renderer/src/scene.rs | 10 +- renderer/src/tile_map.rs | 4 +- renderer/src/tiles.rs | 10 +- renderer/src/z_buffer.rs | 4 +- svg/Cargo.toml | 3 + svg/src/lib.rs | 17 +-- swf/Cargo.toml | 3 + swf/src/lib.rs | 8 +- swf/src/shapes.rs | 4 +- text/Cargo.toml | 3 + text/src/lib.rs | 8 +- ui/Cargo.toml | 3 + ui/src/lib.rs | 6 +- 76 files changed, 443 insertions(+), 345 deletions(-) create mode 100644 content/Cargo.toml rename {geometry => content}/src/clip.rs (98%) rename {geometry => content}/src/color.rs (100%) rename {geometry => content}/src/dash.rs (100%) rename {geometry => content}/src/dilation.rs (98%) rename geometry/src/basic/mod.rs => content/src/lib.rs (50%) rename {geometry => content}/src/orientation.rs (100%) rename {geometry => content}/src/outline.rs (98%) rename {geometry => content}/src/segment.rs (98%) rename {geometry => content}/src/stroke.rs (98%) create mode 100644 content/src/transform.rs rename geometry/src/{basic => }/line_segment.rs (98%) rename geometry/src/{basic => }/rect.rs (99%) rename geometry/src/{basic => }/transform2d.rs (82%) rename geometry/src/{basic => }/transform3d.rs (89%) rename geometry/src/{basic => }/vector.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 186eb4ef..1a5dc613 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,6 +159,7 @@ dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -174,6 +175,7 @@ dependencies = [ "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -189,6 +191,7 @@ version = "0.1.0" dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -203,6 +206,7 @@ version = "0.1.0" dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -218,6 +222,7 @@ dependencies = [ "font-kit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -1377,6 +1382,7 @@ dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -1389,12 +1395,25 @@ name = "pathfinder_canvas" version = "0.1.0" dependencies = [ "font-kit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_content 0.1.0", "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=a2d683856ba1f2d0095b12dd7823d1602a87614e)", ] +[[package]] +name = "pathfinder_content" +version = "0.1.0" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "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_geometry 0.3.0", + "pathfinder_simd 0.3.0", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pathfinder_demo" version = "0.1.0" @@ -1404,6 +1423,7 @@ dependencies = [ "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)", "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -1420,13 +1440,8 @@ dependencies = [ name = "pathfinder_geometry" version = "0.3.0" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "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.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)", ] [[package]] @@ -1447,6 +1462,7 @@ name = "pathfinder_gpu" version = "0.1.0" dependencies = [ "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_simd 0.3.0", ] @@ -1468,6 +1484,7 @@ dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_content 0.1.0", "pathfinder_demo 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", @@ -1507,6 +1524,7 @@ dependencies = [ "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gpu 0.1.0", "pathfinder_simd 0.3.0", @@ -1530,6 +1548,7 @@ name = "pathfinder_svg" version = "0.1.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_renderer 0.1.0", "usvg 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1539,6 +1558,7 @@ dependencies = [ name = "pathfinder_swf" version = "0.1.0" dependencies = [ + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", @@ -1554,6 +1574,7 @@ dependencies = [ "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.2.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_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_renderer 0.1.0", "skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=a2d683856ba1f2d0095b12dd7823d1602a87614e)", @@ -1564,6 +1585,7 @@ name = "pathfinder_ui" version = "0.1.0" dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gpu 0.1.0", "pathfinder_simd 0.3.0", diff --git a/Cargo.toml b/Cargo.toml index d11db85e..5d8e378e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "c", "canvas", + "content", "demo/android/rust", "demo/common", "demo/magicleap", diff --git a/c/Cargo.toml b/c/Cargo.toml index ea2c8146..caad0fec 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -14,6 +14,9 @@ libc = "0.2" [dependencies.pathfinder_canvas] path = "../canvas" +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/c/src/lib.rs b/c/src/lib.rs index 219e43bd..9823f7d1 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -13,11 +13,11 @@ use gl; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin}; use pathfinder_canvas::{Path2D, TextMetrics}; -use pathfinder_geometry::basic::rect::{RectF, RectI}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::color::{ColorF, ColorU}; -use pathfinder_geometry::outline::ArcDirection; -use pathfinder_geometry::stroke::LineCap; +use pathfinder_content::color::{ColorF, ColorU}; +use pathfinder_content::outline::ArcDirection; +use pathfinder_content::stroke::LineCap; +use pathfinder_geometry::rect::{RectF, RectI}; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; use pathfinder_renderer::concurrent::rayon::RayonExecutor; @@ -44,7 +44,7 @@ pub const PF_LINE_JOIN_MITER: u8 = 0; pub const PF_LINE_JOIN_BEVEL: u8 = 1; pub const PF_LINE_JOIN_ROUND: u8 = 2; -// `geometry` +// `content` pub const PF_ARC_DIRECTION_CW: u8 = 0; pub const PF_ARC_DIRECTION_CCW: u8 = 1; @@ -68,6 +68,22 @@ pub struct PFTextMetrics { pub width: f32, } +// `content` +#[repr(C)] +pub struct PFColorF { + pub r: f32, + pub g: f32, + pub b: f32, + pub a: f32, +} +#[repr(C)] +pub struct PFColorU { + pub r: u8, + pub g: u8, + pub b: u8, + pub a: u8, +} + // `geometry` #[repr(C)] pub struct PFVector2F { @@ -89,20 +105,6 @@ pub struct PFRectI { pub origin: PFVector2I, pub lower_right: PFVector2I, } -#[repr(C)] -pub struct PFColorF { - pub r: f32, - pub g: f32, - pub b: f32, - pub a: f32, -} -#[repr(C)] -pub struct PFColorU { - pub r: u8, - pub g: u8, - pub b: u8, - pub a: u8, -} // `gl` pub type PFGLDeviceRef = *mut GLDevice; @@ -472,7 +474,7 @@ impl TextMetricsExt for TextMetrics { } } -// Helpers for `geometry` +// Helpers for `content` impl PFColorF { #[inline] @@ -488,6 +490,8 @@ impl PFColorU { } } +// Helpers for `geometry` + impl PFRectF { #[inline] pub fn to_rust(&self) -> RectF { diff --git a/canvas/Cargo.toml b/canvas/Cargo.toml index 1c620859..fb4f8037 100644 --- a/canvas/Cargo.toml +++ b/canvas/Cargo.toml @@ -10,6 +10,9 @@ crate-type = ["rlib", "staticlib"] [dependencies] font-kit = "0.2" +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 9f710dd0..581ca48a 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -17,15 +17,15 @@ use font_kit::loaders::default::Font; use font_kit::properties::Properties; use font_kit::source::{Source, SystemSource}; use font_kit::sources::mem::MemSource; -use pathfinder_geometry::basic::line_segment::LineSegment2F; -use pathfinder_geometry::basic::vector::Vector2F; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::basic::transform2d::Transform2DF; -use pathfinder_geometry::color::ColorU; -use pathfinder_geometry::dash::OutlineDash; -use pathfinder_geometry::outline::{ArcDirection, Contour, Outline}; -use pathfinder_geometry::stroke::{LineCap, LineJoin as StrokeLineJoin}; -use pathfinder_geometry::stroke::{OutlineStrokeToFill, StrokeStyle}; +use pathfinder_content::color::ColorU; +use pathfinder_content::dash::OutlineDash; +use pathfinder_content::outline::{ArcDirection, Contour, Outline}; +use pathfinder_content::stroke::{LineCap, LineJoin as StrokeLineJoin}; +use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; +use pathfinder_geometry::line_segment::LineSegment2F; +use pathfinder_geometry::vector::Vector2F; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; use pathfinder_renderer::paint::{Paint, PaintId}; use pathfinder_renderer::scene::{PathObject, Scene}; use pathfinder_text::{SceneExt, TextRenderMode}; @@ -526,7 +526,7 @@ pub enum TextAlign { Center, } -// We duplicate `pathfinder_geometry::stroke::LineJoin` here because the HTML canvas API treats the +// We duplicate `pathfinder_content::stroke::LineJoin` here because the HTML canvas API treats the // miter limit as part of the canvas state, while the native Pathfinder API treats the miter limit // as part of the line join. Pathfinder's choice is more logical, because the miter limit is // specific to miter joins. In this API, however, for compatibility we go with the HTML canvas diff --git a/content/Cargo.toml b/content/Cargo.toml new file mode 100644 index 00000000..cdd7b473 --- /dev/null +++ b/content/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "pathfinder_content" +version = "0.1.0" +authors = ["Patrick Walton "] +edition = "2018" + +[dependencies] +arrayvec = "0.4" +bitflags = "1.0" +log = "0.4" +smallvec = "0.6" + +[dependencies.pathfinder_geometry] +path = "../geometry" + +[dependencies.pathfinder_simd] +path = "../simd" diff --git a/geometry/src/clip.rs b/content/src/clip.rs similarity index 98% rename from geometry/src/clip.rs rename to content/src/clip.rs index 4569a68d..b4620ba5 100644 --- a/geometry/src/clip.rs +++ b/content/src/clip.rs @@ -1,4 +1,4 @@ -// pathfinder/geometry/src/clip.rs +// pathfinder/content/src/clip.rs // // Copyright © 2019 The Pathfinder Project Developers. // @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::basic::line_segment::LineSegment2F; -use crate::basic::vector::{Vector2F, Vector4F}; -use crate::basic::rect::RectF; use crate::outline::{Contour, PointFlags, PushSegmentFlags}; use crate::segment::{CubicSegment, Segment}; -use crate::util::lerp; use arrayvec::ArrayVec; +use pathfinder_geometry::line_segment::LineSegment2F; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::util::lerp; +use pathfinder_geometry::vector::{Vector2F, Vector4F}; use smallvec::SmallVec; use std::fmt::Debug; use std::mem; diff --git a/geometry/src/color.rs b/content/src/color.rs similarity index 100% rename from geometry/src/color.rs rename to content/src/color.rs diff --git a/geometry/src/dash.rs b/content/src/dash.rs similarity index 100% rename from geometry/src/dash.rs rename to content/src/dash.rs diff --git a/geometry/src/dilation.rs b/content/src/dilation.rs similarity index 98% rename from geometry/src/dilation.rs rename to content/src/dilation.rs index 4441c90b..40a1c729 100644 --- a/geometry/src/dilation.rs +++ b/content/src/dilation.rs @@ -1,4 +1,4 @@ -// pathfinder/geometry/src/dilation.rs +// pathfinder/content/src/dilation.rs // // Copyright © 2019 The Pathfinder Project Developers. // @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::basic::vector::Vector2F; use crate::orientation::Orientation; use crate::outline::Contour; +use pathfinder_geometry::vector::Vector2F; pub struct ContourDilator<'a> { contour: &'a mut Contour, diff --git a/geometry/src/basic/mod.rs b/content/src/lib.rs similarity index 50% rename from geometry/src/basic/mod.rs rename to content/src/lib.rs index d77c1fc0..00abb4d1 100644 --- a/geometry/src/basic/mod.rs +++ b/content/src/lib.rs @@ -1,4 +1,4 @@ -// pathfinder/geometry/src/basic/mod.rs +// pathfinder/content/src/lib.rs // // Copyright © 2019 The Pathfinder Project Developers. // @@ -8,10 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Basic geometry and linear algebra primitives, optimized with SIMD. +//! Pathfinder's representation of a vector scene. +//! +//! This module also contains various path utilities. -pub mod line_segment; -pub mod rect; -pub mod transform2d; -pub mod transform3d; -pub mod vector; +#[macro_use] +extern crate bitflags; +#[macro_use] +extern crate log; + +pub mod clip; +pub mod color; +pub mod dash; +pub mod orientation; +pub mod outline; +pub mod segment; +pub mod stroke; +pub mod transform; + +mod dilation; diff --git a/geometry/src/orientation.rs b/content/src/orientation.rs similarity index 100% rename from geometry/src/orientation.rs rename to content/src/orientation.rs diff --git a/geometry/src/outline.rs b/content/src/outline.rs similarity index 98% rename from geometry/src/outline.rs rename to content/src/outline.rs index 5858941c..b09cc668 100644 --- a/geometry/src/outline.rs +++ b/content/src/outline.rs @@ -1,4 +1,4 @@ -// pathfinder/geometry/src/outline.rs +// pathfinder/content/src/outline.rs // // Copyright © 2019 The Pathfinder Project Developers. // @@ -10,16 +10,16 @@ //! A compressed in-memory representation of paths. -use crate::basic::line_segment::LineSegment2F; -use crate::basic::vector::Vector2F; -use crate::basic::rect::RectF; -use crate::basic::transform2d::Transform2DF; -use crate::basic::transform3d::Perspective; use crate::clip::{self, ContourPolygonClipper, ContourRectClipper}; use crate::dilation::ContourDilator; use crate::orientation::Orientation; use crate::segment::{Segment, SegmentFlags, SegmentKind}; -use crate::unit_vector::UnitVector; +use pathfinder_geometry::line_segment::LineSegment2F; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::transform3d::Perspective; +use pathfinder_geometry::unit_vector::UnitVector; +use pathfinder_geometry::vector::Vector2F; use std::f32::consts::PI; use std::fmt::{self, Debug, Formatter}; use std::mem; diff --git a/geometry/src/segment.rs b/content/src/segment.rs similarity index 98% rename from geometry/src/segment.rs rename to content/src/segment.rs index 2cd8adf4..4a9d6a76 100644 --- a/geometry/src/segment.rs +++ b/content/src/segment.rs @@ -1,4 +1,4 @@ -// pathfinder/geometry/src/segment.rs +// pathfinder/content/src/segment.rs // // Copyright © 2019 The Pathfinder Project Developers. // @@ -10,10 +10,10 @@ //! Line or curve segments, optimized with SIMD. -use crate::basic::line_segment::LineSegment2F; -use crate::basic::vector::Vector2F; -use crate::basic::transform2d::Transform2DF; -use crate::util::{self, EPSILON}; +use pathfinder_geometry::line_segment::LineSegment2F; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::util::{self, EPSILON}; +use pathfinder_geometry::vector::Vector2F; use pathfinder_simd::default::F32x4; use std::f32::consts::SQRT_2; diff --git a/geometry/src/stroke.rs b/content/src/stroke.rs similarity index 98% rename from geometry/src/stroke.rs rename to content/src/stroke.rs index 4e9a195a..48f68276 100644 --- a/geometry/src/stroke.rs +++ b/content/src/stroke.rs @@ -1,4 +1,4 @@ -// pathfinder/geometry/src/stroke.rs +// pathfinder/content/src/stroke.rs // // Copyright © 2019 The Pathfinder Project Developers. // @@ -10,12 +10,12 @@ //! Utilities for converting path strokes to fills. -use crate::basic::line_segment::LineSegment2F; -use crate::basic::vector::Vector2F; -use crate::basic::rect::RectF; -use crate::basic::transform2d::Transform2DF; use crate::outline::{ArcDirection, Contour, Outline, PushSegmentFlags}; use crate::segment::Segment; +use pathfinder_geometry::line_segment::LineSegment2F; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::vector::Vector2F; use std::f32; const TOLERANCE: f32 = 0.01; diff --git a/content/src/transform.rs b/content/src/transform.rs new file mode 100644 index 00000000..283b4386 --- /dev/null +++ b/content/src/transform.rs @@ -0,0 +1,124 @@ +// pathfinder/content/src/transform.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. + +//! Utilities for transforming paths. + +use crate::segment::Segment; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::transform3d::Perspective; + +/// Transforms a path with a SIMD 2D transform. +pub struct Transform2DFPathIter +where + I: Iterator, +{ + iter: I, + transform: Transform2DF, +} + +impl Iterator for Transform2DFPathIter +where + I: Iterator, +{ + type Item = Segment; + + #[inline] + fn next(&mut self) -> Option { + // TODO(pcwalton): Can we go faster by transforming an entire line segment with SIMD? + let mut segment = self.iter.next()?; + if !segment.is_none() { + segment + .baseline + .set_from(&self.transform.transform_point(segment.baseline.from())); + segment + .baseline + .set_to(&self.transform.transform_point(segment.baseline.to())); + if !segment.is_line() { + segment + .ctrl + .set_from(&self.transform.transform_point(segment.ctrl.from())); + if !segment.is_quadratic() { + segment + .ctrl + .set_to(&self.transform.transform_point(segment.ctrl.to())); + } + } + } + Some(segment) + } +} + +impl Transform2DFPathIter +where + I: Iterator, +{ + #[inline] + pub fn new(iter: I, transform: &Transform2DF) -> Transform2DFPathIter { + Transform2DFPathIter { + iter, + transform: *transform, + } + } +} + +/// Transforms a path with a perspective projection. +pub struct PerspectivePathIter +where + I: Iterator, +{ + iter: I, + perspective: Perspective, +} + +impl Iterator for PerspectivePathIter +where + I: Iterator, +{ + type Item = Segment; + + #[inline] + fn next(&mut self) -> Option { + let mut segment = self.iter.next()?; + if !segment.is_none() { + segment.baseline.set_from( + &self + .perspective + .transform_point_2d(&segment.baseline.from()), + ); + segment + .baseline + .set_to(&self.perspective.transform_point_2d(&segment.baseline.to())); + if !segment.is_line() { + segment + .ctrl + .set_from(&self.perspective.transform_point_2d(&segment.ctrl.from())); + if !segment.is_quadratic() { + segment + .ctrl + .set_to(&self.perspective.transform_point_2d(&segment.ctrl.to())); + } + } + } + Some(segment) + } +} + +impl PerspectivePathIter +where + I: Iterator, +{ + #[inline] + pub fn new(iter: I, perspective: &Perspective) -> PerspectivePathIter { + PerspectivePathIter { + iter, + perspective: *perspective, + } + } +} diff --git a/demo/android/rust/src/lib.rs b/demo/android/rust/src/lib.rs index 6e322418..4fdf1fa7 100644 --- a/demo/android/rust/src/lib.rs +++ b/demo/android/rust/src/lib.rs @@ -16,8 +16,8 @@ use jni::{JNIEnv, JavaVM}; use pathfinder_demo::window::{Event, SVGPath, View, Window, WindowSize}; use pathfinder_demo::DemoApp; use pathfinder_demo::Options; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectI; use pathfinder_gl::GLVersion; use pathfinder_gpu::resources::ResourceLoader; use std::cell::RefCell; diff --git a/demo/common/Cargo.toml b/demo/common/Cargo.toml index 45ea0798..b6aa30e5 100644 --- a/demo/common/Cargo.toml +++ b/demo/common/Cargo.toml @@ -22,6 +22,9 @@ features = ["png_codec"] version = "0.4" features = ["release_max_level_warn"] +[dependencies.pathfinder_content] +path = "../../content" + [dependencies.pathfinder_geometry] path = "../../geometry" diff --git a/demo/common/src/camera.rs b/demo/common/src/camera.rs index f8dc6445..eea0649e 100644 --- a/demo/common/src/camera.rs +++ b/demo/common/src/camera.rs @@ -14,10 +14,10 @@ // proper. use crate::window::{OcularTransform, View}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I, Vector4F}; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::basic::transform2d::Transform2DF; -use pathfinder_geometry::basic::transform3d::{Perspective, Transform3DF}; +use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F}; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::transform3d::{Perspective, Transform3DF}; use std::f32::consts::FRAC_PI_4; const NEAR_CLIP_PLANE: f32 = 0.01; diff --git a/demo/common/src/lib.rs b/demo/common/src/lib.rs index 76c5a964..e97231b2 100644 --- a/demo/common/src/lib.rs +++ b/demo/common/src/lib.rs @@ -22,11 +22,11 @@ use crate::device::{GroundProgram, GroundVertexArray}; use crate::ui::{DemoUIModel, DemoUIPresenter, ScreenshotInfo, ScreenshotType, UIAction}; use crate::window::{Event, Keycode, SVGPath, Window, WindowSize}; use clap::{App, Arg}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::basic::transform2d::Transform2DF; -use pathfinder_geometry::basic::transform3d::Transform3DF; -use pathfinder_geometry::color::ColorU; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::transform3d::Transform3DF; +use pathfinder_content::color::ColorU; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::Device; use pathfinder_renderer::concurrent::scene_proxy::{RenderCommandStream, SceneProxy}; diff --git a/demo/common/src/renderer.rs b/demo/common/src/renderer.rs index fb42869d..c4bc0cc3 100644 --- a/demo/common/src/renderer.rs +++ b/demo/common/src/renderer.rs @@ -14,12 +14,12 @@ use crate::camera::{Camera, Mode}; use crate::window::{View, Window}; use crate::{BackgroundColor, DemoApp, UIVisibility}; use image::ColorType; -use pathfinder_geometry::color::{ColorF, ColorU}; +use pathfinder_content::color::{ColorF, ColorU}; use pathfinder_gpu::{ClearOps, DepthFunc, DepthState, Device, Primitive, RenderOptions}; use pathfinder_gpu::{RenderState, RenderTarget, TextureData, TextureFormat, UniformData}; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::transform3d::Transform3DF; -use pathfinder_geometry::basic::vector::Vector2I; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::transform3d::Transform3DF; +use pathfinder_geometry::vector::Vector2I; use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions}; use pathfinder_renderer::gpu::renderer::RenderMode; use pathfinder_renderer::gpu_data::RenderCommand; diff --git a/demo/common/src/ui.rs b/demo/common/src/ui.rs index 270893c5..2c7c8c5e 100644 --- a/demo/common/src/ui.rs +++ b/demo/common/src/ui.rs @@ -11,8 +11,8 @@ use crate::camera::Mode; use crate::window::Window; use crate::{BackgroundColor, Options}; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectI; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::Device; use pathfinder_renderer::gpu::debug::DebugUIPresenter; diff --git a/demo/common/src/window.rs b/demo/common/src/window.rs index d8fc0019..edacf767 100644 --- a/demo/common/src/window.rs +++ b/demo/common/src/window.rs @@ -10,9 +10,9 @@ //! A minimal cross-platform windowing layer. -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::transform3d::{Perspective, Transform3DF}; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::transform3d::{Perspective, Transform3DF}; use pathfinder_gpu::resources::ResourceLoader; use rayon::ThreadPoolBuilder; use std::path::PathBuf; diff --git a/demo/magicleap/Cargo.toml b/demo/magicleap/Cargo.toml index efba31a8..6e7e8ff0 100644 --- a/demo/magicleap/Cargo.toml +++ b/demo/magicleap/Cargo.toml @@ -20,6 +20,9 @@ crate-type = ["cdylib"] [features] mocked = ["glutin"] +[dependencies.pathfinder_content] +path = "../../content" + [dependencies.pathfinder_demo] path = "../common" diff --git a/demo/magicleap/src/display.rs b/demo/magicleap/src/display.rs index 6a0f94ba..2176e43d 100644 --- a/demo/magicleap/src/display.rs +++ b/demo/magicleap/src/display.rs @@ -10,10 +10,10 @@ use std::error::Error; use std::io; -use pathfinder_geometry::basic::point::Point2DI32; -use pathfinder_geometry::basic::rect::RectI32; -use pathfinder_geometry::basic::transform3d::Perspective; -use pathfinder_geometry::basic::transform3d::Transform3DF32; +use pathfinder_geometry::point::Point2DI32; +use pathfinder_geometry::rect::RectI32; +use pathfinder_geometry::transform3d::Perspective; +use pathfinder_geometry::transform3d::Transform3DF32; use pathfinder_gl::GLVersion; use pathfinder_gpu::resources::ResourceLoader; diff --git a/demo/magicleap/src/glwindow.rs b/demo/magicleap/src/glwindow.rs index bd90d08e..50005428 100644 --- a/demo/magicleap/src/glwindow.rs +++ b/demo/magicleap/src/glwindow.rs @@ -25,10 +25,10 @@ use crate::display::Display; use crate::display::DisplayCamera; use crate::display::DisplayError; -use pathfinder_geometry::basic::point::Point2DI32; -use pathfinder_geometry::basic::rect::RectI32; -use pathfinder_geometry::basic::transform3d::Transform3DF32; -use pathfinder_geometry::basic::transform3d::Perspective; +use pathfinder_geometry::point::Point2DI32; +use pathfinder_geometry::rect::RectI32; +use pathfinder_geometry::transform3d::Transform3DF32; +use pathfinder_geometry::transform3d::Perspective; use pathfinder_gl::GLVersion; use pathfinder_gpu::resources::FilesystemResourceLoader; use pathfinder_gpu::resources::ResourceLoader; diff --git a/demo/magicleap/src/immersive.rs b/demo/magicleap/src/immersive.rs index 775a0b37..b01741ce 100644 --- a/demo/magicleap/src/immersive.rs +++ b/demo/magicleap/src/immersive.rs @@ -15,13 +15,13 @@ use pathfinder_demo::Camera; use pathfinder_demo::CameraTransform3D; use pathfinder_gl::GLDevice; use pathfinder_renderer::gpu::renderer::Renderer; -use pathfinder_geometry::basic::point::Point2DI32; -use pathfinder_geometry::basic::point::Point2DF32; -use pathfinder_geometry::basic::point::Point3DF32; -use pathfinder_geometry::basic::rect::RectI32; -use pathfinder_geometry::basic::transform2d::Transform2DF32; -use pathfinder_geometry::basic::transform3d::Transform3DF32; -use pathfinder_geometry::basic::transform3d::Perspective; +use pathfinder_geometry::point::Point2DI32; +use pathfinder_geometry::point::Point2DF32; +use pathfinder_geometry::point::Point3DF32; +use pathfinder_geometry::rect::RectI32; +use pathfinder_geometry::transform2d::Transform2DF32; +use pathfinder_geometry::transform3d::Transform3DF32; +use pathfinder_geometry::transform3d::Perspective; use pathfinder_gpu::Device; use pathfinder_simd::default::F32x4; use pathfinder_svg::BuiltSVG; diff --git a/demo/magicleap/src/lib.rs b/demo/magicleap/src/lib.rs index 632023c0..5530e4ab 100644 --- a/demo/magicleap/src/lib.rs +++ b/demo/magicleap/src/lib.rs @@ -29,11 +29,11 @@ use pathfinder_demo::BackgroundColor; use pathfinder_demo::Mode; use pathfinder_demo::window::Event; use pathfinder_demo::window::SVGPath; -use pathfinder_geometry::basic::vector::Vector2F; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::transform2d::Transform2DF; -use pathfinder_geometry::color::ColorF; +use pathfinder_geometry::vector::Vector2F; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_content::color::ColorF; use pathfinder_gl::GLDevice; use pathfinder_gl::GLVersion; use pathfinder_gpu::ClearParams; diff --git a/demo/magicleap/src/magicleap.rs b/demo/magicleap/src/magicleap.rs index 1790c4a3..29c74df9 100644 --- a/demo/magicleap/src/magicleap.rs +++ b/demo/magicleap/src/magicleap.rs @@ -48,12 +48,12 @@ use pathfinder_demo::window::OcularTransform; use pathfinder_demo::window::View; use pathfinder_demo::window::Window; use pathfinder_demo::window::WindowSize; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::vector::Vector2F; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::transform3d::Perspective; -use pathfinder_geometry::basic::transform3d::Transform3DF; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::vector::Vector2F; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::transform3d::Perspective; +use pathfinder_geometry::transform3d::Transform3DF; use pathfinder_geometry::util; use pathfinder_gl::GLVersion; use pathfinder_gpu::resources::FilesystemResourceLoader; diff --git a/demo/native/src/main.rs b/demo/native/src/main.rs index 78636e4c..29069ae1 100644 --- a/demo/native/src/main.rs +++ b/demo/native/src/main.rs @@ -13,8 +13,8 @@ use nfd::Response; use pathfinder_demo::window::{Event, Keycode, SVGPath, View, Window, WindowSize}; use pathfinder_demo::{DemoApp, Options}; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectI; use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; use sdl2::event::{Event as SDLEvent, WindowEvent}; use sdl2::keyboard::Keycode as SDLKeycode; diff --git a/examples/canvas_glutin_minimal/Cargo.toml b/examples/canvas_glutin_minimal/Cargo.toml index 37b25e22..2b1a6bb3 100644 --- a/examples/canvas_glutin_minimal/Cargo.toml +++ b/examples/canvas_glutin_minimal/Cargo.toml @@ -11,6 +11,9 @@ glutin = "0.21" [dependencies.pathfinder_canvas] path = "../../canvas" +[dependencies.pathfinder_content] +path = "../../content" + [dependencies.pathfinder_geometry] path = "../../geometry" diff --git a/examples/canvas_glutin_minimal/src/main.rs b/examples/canvas_glutin_minimal/src/main.rs index 9b8662c0..597f7e27 100644 --- a/examples/canvas_glutin_minimal/src/main.rs +++ b/examples/canvas_glutin_minimal/src/main.rs @@ -14,9 +14,9 @@ use glutin::dpi::PhysicalSize; use glutin::{ContextBuilder, ControlFlow, Event, EventsLoop, GlProfile, GlRequest, KeyboardInput}; use glutin::{VirtualKeyCode, WindowBuilder, WindowEvent}; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::color::ColorF; +use pathfinder_content::color::ColorF; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::rect::RectF; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::FilesystemResourceLoader; use pathfinder_renderer::concurrent::rayon::RayonExecutor; diff --git a/examples/canvas_metal_minimal/Cargo.toml b/examples/canvas_metal_minimal/Cargo.toml index 41673409..74cfde80 100644 --- a/examples/canvas_metal_minimal/Cargo.toml +++ b/examples/canvas_metal_minimal/Cargo.toml @@ -15,6 +15,9 @@ sdl2-sys = "0.32" [dependencies.pathfinder_canvas] path = "../../canvas" +[dependencies.pathfinder_content] +path = "../../content" + [dependencies.pathfinder_geometry] path = "../../geometry" diff --git a/examples/canvas_metal_minimal/src/main.rs b/examples/canvas_metal_minimal/src/main.rs index 8d8417ad..2b0b6b06 100644 --- a/examples/canvas_metal_minimal/src/main.rs +++ b/examples/canvas_metal_minimal/src/main.rs @@ -11,9 +11,9 @@ use foreign_types::ForeignTypeRef; use metal::{CAMetalLayer, CoreAnimationLayerRef}; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::color::ColorF; +use pathfinder_content::color::ColorF; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::rect::RectF; use pathfinder_gpu::resources::FilesystemResourceLoader; use pathfinder_metal::MetalDevice; use pathfinder_renderer::concurrent::rayon::RayonExecutor; diff --git a/examples/canvas_minimal/Cargo.toml b/examples/canvas_minimal/Cargo.toml index ccd2fe25..0becc032 100644 --- a/examples/canvas_minimal/Cargo.toml +++ b/examples/canvas_minimal/Cargo.toml @@ -12,6 +12,9 @@ sdl2-sys = "0.32" [dependencies.pathfinder_canvas] path = "../../canvas" +[dependencies.pathfinder_content] +path = "../../content" + [dependencies.pathfinder_geometry] path = "../../geometry" diff --git a/examples/canvas_minimal/src/main.rs b/examples/canvas_minimal/src/main.rs index 230640c3..dce34e5d 100644 --- a/examples/canvas_minimal/src/main.rs +++ b/examples/canvas_minimal/src/main.rs @@ -9,9 +9,9 @@ // except according to those terms. use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::color::ColorF; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::rect::RectF; +use pathfinder_content::color::ColorF; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::FilesystemResourceLoader; use pathfinder_renderer::concurrent::rayon::RayonExecutor; diff --git a/examples/canvas_moire/Cargo.toml b/examples/canvas_moire/Cargo.toml index 0bab187d..cb8f98ea 100644 --- a/examples/canvas_moire/Cargo.toml +++ b/examples/canvas_moire/Cargo.toml @@ -12,6 +12,9 @@ sdl2-sys = "0.32" [dependencies.pathfinder_canvas] path = "../../canvas" +[dependencies.pathfinder_content] +path = "../../content" + [dependencies.pathfinder_geometry] path = "../../geometry" diff --git a/examples/canvas_moire/src/main.rs b/examples/canvas_moire/src/main.rs index 1f579b1e..36312a09 100644 --- a/examples/canvas_moire/src/main.rs +++ b/examples/canvas_moire/src/main.rs @@ -9,8 +9,8 @@ // except according to those terms. use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, Path2D}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::color::{ColorF, ColorU}; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_content::color::{ColorF, ColorU}; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::FilesystemResourceLoader; use pathfinder_renderer::concurrent::rayon::RayonExecutor; diff --git a/examples/canvas_text/Cargo.toml b/examples/canvas_text/Cargo.toml index 720a0863..6250e71a 100644 --- a/examples/canvas_text/Cargo.toml +++ b/examples/canvas_text/Cargo.toml @@ -13,6 +13,9 @@ sdl2-sys = "0.32" [dependencies.pathfinder_canvas] path = "../../canvas" +[dependencies.pathfinder_content] +path = "../../content" + [dependencies.pathfinder_geometry] path = "../../geometry" diff --git a/examples/canvas_text/src/main.rs b/examples/canvas_text/src/main.rs index 7d4b8385..2942e3ae 100644 --- a/examples/canvas_text/src/main.rs +++ b/examples/canvas_text/src/main.rs @@ -10,8 +10,8 @@ use font_kit::handle::Handle; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, TextAlign}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::color::ColorF; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_content::color::ColorF; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; use pathfinder_renderer::concurrent::rayon::RayonExecutor; diff --git a/examples/swf_basic/src/main.rs b/examples/swf_basic/src/main.rs index a06d7f79..cd790074 100644 --- a/examples/swf_basic/src/main.rs +++ b/examples/swf_basic/src/main.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::RectF; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::rect::RectF; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; use pathfinder_renderer::concurrent::rayon::RayonExecutor; @@ -24,7 +24,7 @@ use pathfinder_renderer::scene::Scene; use pathfinder_swf::{draw_paths_into_scene, process_swf_tags}; use std::env; use std::fs::read; -use pathfinder_geometry::basic::transform2d::Transform2DF; +use pathfinder_geometry::transform2d::Transform2DF; fn main() { let resource_loader = FilesystemResourceLoader::locate(); diff --git a/geometry/Cargo.toml b/geometry/Cargo.toml index 580a84da..8136c255 100644 --- a/geometry/Cargo.toml +++ b/geometry/Cargo.toml @@ -5,11 +5,6 @@ edition = "2018" authors = ["Patrick Walton "] [dependencies] -arrayvec = "0.4" -bitflags = "1.0" -serde = "1.0" -serde_derive = "1.0" -smallvec = "0.6" [dependencies.log] version = "0.4" diff --git a/geometry/src/lib.rs b/geometry/src/lib.rs index 8445b7ae..3ff52601 100644 --- a/geometry/src/lib.rs +++ b/geometry/src/lib.rs @@ -8,24 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Utilities for Bézier curves. -//! -//! These may be merged into upstream Lyon eventually. +//! Basic geometry and linear algebra primitives, optimized with SIMD. -#[macro_use] -extern crate bitflags; -#[macro_use] -extern crate log; - -pub mod basic; -pub mod clip; -pub mod color; -pub mod dash; -pub mod orientation; -pub mod outline; -pub mod segment; -pub mod stroke; +pub mod line_segment; +pub mod rect; +pub mod transform2d; +pub mod transform3d; +pub mod unit_vector; pub mod util; - -mod dilation; -mod unit_vector; +pub mod vector; diff --git a/geometry/src/basic/line_segment.rs b/geometry/src/line_segment.rs similarity index 98% rename from geometry/src/basic/line_segment.rs rename to geometry/src/line_segment.rs index 3d68f655..7842c893 100644 --- a/geometry/src/basic/line_segment.rs +++ b/geometry/src/line_segment.rs @@ -10,8 +10,8 @@ //! Line segment types, optimized with SIMD. -use crate::basic::vector::Vector2F; -use crate::basic::transform2d::Matrix2x2F; +use crate::vector::Vector2F; +use crate::transform2d::Matrix2x2F; use crate::util; use pathfinder_simd::default::F32x4; use std::ops::{Add, Sub}; diff --git a/geometry/src/basic/rect.rs b/geometry/src/rect.rs similarity index 99% rename from geometry/src/basic/rect.rs rename to geometry/src/rect.rs index 95e60ee3..ec7e103a 100644 --- a/geometry/src/basic/rect.rs +++ b/geometry/src/rect.rs @@ -10,7 +10,7 @@ //! 2D axis-aligned rectangles, optimized with SIMD. -use crate::basic::vector::{Vector2F, Vector2I}; +use crate::vector::{Vector2F, Vector2I}; use pathfinder_simd::default::{F32x4, I32x4}; #[derive(Clone, Copy, Debug, PartialEq, Default)] diff --git a/geometry/src/basic/transform2d.rs b/geometry/src/transform2d.rs similarity index 82% rename from geometry/src/basic/transform2d.rs rename to geometry/src/transform2d.rs index db0df148..b48c8882 100644 --- a/geometry/src/basic/transform2d.rs +++ b/geometry/src/transform2d.rs @@ -10,11 +10,10 @@ //! 2D affine transforms. -use crate::basic::line_segment::LineSegment2F; -use crate::basic::vector::Vector2F; -use crate::basic::rect::RectF; -use crate::basic::transform3d::Transform3DF; -use crate::segment::Segment; +use crate::line_segment::LineSegment2F; +use crate::vector::Vector2F; +use crate::rect::RectF; +use crate::transform3d::Transform3DF; use crate::unit_vector::UnitVector; use pathfinder_simd::default::F32x4; use std::ops::Sub; @@ -295,57 +294,3 @@ impl Transform2DF { Vector2F(self.matrix.0.zwxy()).length() } } - -/// Transforms a path with a SIMD 2D transform. -pub struct Transform2DFPathIter -where - I: Iterator, -{ - iter: I, - transform: Transform2DF, -} - -impl Iterator for Transform2DFPathIter -where - I: Iterator, -{ - type Item = Segment; - - #[inline] - fn next(&mut self) -> Option { - // TODO(pcwalton): Can we go faster by transforming an entire line segment with SIMD? - let mut segment = self.iter.next()?; - if !segment.is_none() { - segment - .baseline - .set_from(&self.transform.transform_point(segment.baseline.from())); - segment - .baseline - .set_to(&self.transform.transform_point(segment.baseline.to())); - if !segment.is_line() { - segment - .ctrl - .set_from(&self.transform.transform_point(segment.ctrl.from())); - if !segment.is_quadratic() { - segment - .ctrl - .set_to(&self.transform.transform_point(segment.ctrl.to())); - } - } - } - Some(segment) - } -} - -impl Transform2DFPathIter -where - I: Iterator, -{ - #[inline] - pub fn new(iter: I, transform: &Transform2DF) -> Transform2DFPathIter { - Transform2DFPathIter { - iter, - transform: *transform, - } - } -} diff --git a/geometry/src/basic/transform3d.rs b/geometry/src/transform3d.rs similarity index 89% rename from geometry/src/basic/transform3d.rs rename to geometry/src/transform3d.rs index bdd71c0c..7425b34c 100644 --- a/geometry/src/basic/transform3d.rs +++ b/geometry/src/transform3d.rs @@ -10,10 +10,9 @@ //! 3D transforms that can be applied to paths. -use crate::basic::vector::{Vector2F, Vector2I, Vector4F}; -use crate::basic::rect::RectF; -use crate::basic::transform2d::Matrix2x2F; -use crate::segment::Segment; +use crate::vector::{Vector2F, Vector2I, Vector4F}; +use crate::rect::RectF; +use crate::transform2d::Matrix2x2F; use pathfinder_simd::default::F32x4; use std::ops::{Add, Neg}; @@ -372,65 +371,10 @@ impl Perspective { } } -/// Transforms a path with a perspective projection. -pub struct PerspectivePathIter -where - I: Iterator, -{ - iter: I, - perspective: Perspective, -} - -impl Iterator for PerspectivePathIter -where - I: Iterator, -{ - type Item = Segment; - - #[inline] - fn next(&mut self) -> Option { - let mut segment = self.iter.next()?; - if !segment.is_none() { - segment.baseline.set_from( - &self - .perspective - .transform_point_2d(&segment.baseline.from()), - ); - segment - .baseline - .set_to(&self.perspective.transform_point_2d(&segment.baseline.to())); - if !segment.is_line() { - segment - .ctrl - .set_from(&self.perspective.transform_point_2d(&segment.ctrl.from())); - if !segment.is_quadratic() { - segment - .ctrl - .set_to(&self.perspective.transform_point_2d(&segment.ctrl.to())); - } - } - } - Some(segment) - } -} - -impl PerspectivePathIter -where - I: Iterator, -{ - #[inline] - pub fn new(iter: I, perspective: &Perspective) -> PerspectivePathIter { - PerspectivePathIter { - iter, - perspective: *perspective, - } - } -} - #[cfg(test)] mod test { - use crate::basic::vector::Vector4F; - use crate::basic::transform3d::Transform3DF; + use crate::vector::Vector4F; + use crate::transform3d::Transform3DF; #[test] fn test_post_mul() { diff --git a/geometry/src/unit_vector.rs b/geometry/src/unit_vector.rs index 35533e7a..b46431b0 100644 --- a/geometry/src/unit_vector.rs +++ b/geometry/src/unit_vector.rs @@ -10,7 +10,7 @@ //! A utility module that allows unit vectors to be treated like angles. -use crate::basic::vector::Vector2F; +use crate::vector::Vector2F; use pathfinder_simd::default::F32x4; #[derive(Clone, Copy, Debug)] diff --git a/geometry/src/basic/vector.rs b/geometry/src/vector.rs similarity index 100% rename from geometry/src/basic/vector.rs rename to geometry/src/vector.rs diff --git a/gl/src/lib.rs b/gl/src/lib.rs index f53faeaf..1c832544 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -14,8 +14,8 @@ extern crate log; use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid}; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::vector::Vector2I; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::vector::Vector2I; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{RenderTarget, BlendState, BufferData, BufferTarget, BufferUploadMode}; use pathfinder_gpu::{ClearOps, DepthFunc, Device, Primitive, RenderOptions, RenderState}; diff --git a/gpu/Cargo.toml b/gpu/Cargo.toml index c493efa2..cc9ca12f 100644 --- a/gpu/Cargo.toml +++ b/gpu/Cargo.toml @@ -11,6 +11,9 @@ version = "0.21" default-features = false features = ["png_codec"] +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index 227b0993..70dcd132 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -12,10 +12,10 @@ use crate::resources::ResourceLoader; use image::ImageFormat; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::transform3d::Transform3DF; -use pathfinder_geometry::color::ColorF; +use pathfinder_content::color::ColorF; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::transform3d::Transform3DF; +use pathfinder_geometry::vector::Vector2I; use pathfinder_simd::default::F32x4; use std::time::Duration; diff --git a/metal/src/lib.rs b/metal/src/lib.rs index 63856a09..3c1c4f89 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -40,8 +40,8 @@ use metal::{SamplerDescriptor, SamplerState, StencilDescriptor, StructMemberRef, use metal::{StructTypeRef, TextureDescriptor, Texture, TextureRef, VertexAttribute}; use metal::{VertexAttributeRef, VertexDescriptor, VertexDescriptorRef}; use objc::runtime::{Class, Object}; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::vector::Vector2I; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::vector::Vector2I; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, DepthFunc, Device}; use pathfinder_gpu::{Primitive, RenderState, RenderTarget, ShaderKind, StencilFunc, TextureData}; diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml index 106c0bab..e8e789a0 100644 --- a/renderer/Cargo.toml +++ b/renderer/Cargo.toml @@ -18,6 +18,9 @@ smallvec = "0.6" version = "0.4" features = ["release_max_level_warn"] +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index ff054432..b3d4ca1c 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -17,9 +17,9 @@ use crate::scene::Scene; use crate::tile_map::DenseTileMap; use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH, Tiler}; use crate::z_buffer::ZBuffer; -use pathfinder_geometry::basic::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8}; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::{RectF, RectI}; +use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8}; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::rect::{RectF, RectI}; use pathfinder_geometry::util; use pathfinder_simd::default::{F32x4, I32x4}; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/renderer/src/concurrent/scene_proxy.rs b/renderer/src/concurrent/scene_proxy.rs index a85d3e89..22e29155 100644 --- a/renderer/src/concurrent/scene_proxy.rs +++ b/renderer/src/concurrent/scene_proxy.rs @@ -24,7 +24,7 @@ use crate::gpu::renderer::Renderer; use crate::gpu_data::RenderCommand; use crate::options::{BuildOptions, RenderCommandListener}; use crate::scene::Scene; -use pathfinder_geometry::basic::rect::RectF; +use pathfinder_geometry::rect::RectF; use pathfinder_gpu::Device; use std::sync::mpsc::{self, Receiver, Sender}; use std::thread; diff --git a/renderer/src/gpu/debug.rs b/renderer/src/gpu/debug.rs index 5e982d79..7d28b952 100644 --- a/renderer/src/gpu/debug.rs +++ b/renderer/src/gpu/debug.rs @@ -16,8 +16,8 @@ //! The debug font atlas was generated using: https://evanw.github.io/font-texture-generator/ use crate::gpu::renderer::{RenderStats, RenderTime}; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectI; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::Device; use pathfinder_ui::{FONT_ASCENT, LINE_HEIGHT, PADDING, UIPresenter, WINDOW_COLOR}; diff --git a/renderer/src/gpu/options.rs b/renderer/src/gpu/options.rs index 04c9af59..8ffe9d88 100644 --- a/renderer/src/gpu/options.rs +++ b/renderer/src/gpu/options.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::color::ColorF; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_content::color::ColorF; use pathfinder_gpu::Device; /// Options that influence rendering. diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index e616615e..87565d36 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -14,10 +14,10 @@ use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive, PaintData}; use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive}; use crate::post::DefringingKernel; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; -use pathfinder_geometry::basic::vector::{Vector2I, Vector4F}; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::basic::transform3d::Transform3DF; -use pathfinder_geometry::color::ColorF; +use pathfinder_geometry::vector::{Vector2I, Vector4F}; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::transform3d::Transform3DF; +use pathfinder_content::color::ColorF; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearOps}; use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderOptions, RenderState}; diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 6c5045f7..6e65cb46 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -12,9 +12,9 @@ use crate::options::BoundingQuad; use crate::tile_map::DenseTileMap; -use pathfinder_geometry::basic::line_segment::{LineSegmentU4, LineSegmentU8}; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectF; +use pathfinder_geometry::line_segment::{LineSegmentU4, LineSegmentU8}; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectF; use std::fmt::{Debug, Formatter, Result as DebugResult}; use std::time::Duration; diff --git a/renderer/src/options.rs b/renderer/src/options.rs index 32357c08..0266ec78 100644 --- a/renderer/src/options.rs +++ b/renderer/src/options.rs @@ -11,11 +11,11 @@ //! Options that control how rendering is to be performed. use crate::gpu_data::RenderCommand; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::basic::transform2d::Transform2DF; -use pathfinder_geometry::basic::transform3d::Perspective; -use pathfinder_geometry::basic::vector::{Vector2F, Vector4F}; -use pathfinder_geometry::clip::PolygonClipper3D; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::transform3d::Perspective; +use pathfinder_geometry::vector::{Vector2F, Vector4F}; +use pathfinder_content::clip::PolygonClipper3D; pub trait RenderCommandListener: Send + Sync { fn send(&self, command: RenderCommand); diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs index d0140004..2426092c 100644 --- a/renderer/src/paint.rs +++ b/renderer/src/paint.rs @@ -10,8 +10,8 @@ use crate::gpu_data::PaintData; use crate::scene::Scene; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::color::ColorU; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_content::color::ColorU; const PAINT_TEXTURE_WIDTH: i32 = 256; const PAINT_TEXTURE_HEIGHT: i32 = 256; diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index db5319c6..328c3f82 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -16,11 +16,11 @@ use crate::options::{BuildOptions, PreparedBuildOptions}; use crate::options::{PreparedRenderTransform, RenderCommandListener}; use crate::paint::{Paint, PaintId}; use hashbrown::HashMap; -use pathfinder_geometry::basic::vector::Vector2F; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::basic::transform2d::Transform2DF; -use pathfinder_geometry::color::ColorU; -use pathfinder_geometry::outline::Outline; +use pathfinder_geometry::vector::Vector2F; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_content::color::ColorU; +use pathfinder_content::outline::Outline; use std::io::{self, Write}; #[derive(Clone)] diff --git a/renderer/src/tile_map.rs b/renderer/src/tile_map.rs index a280df3b..f0d5ac40 100644 --- a/renderer/src/tile_map.rs +++ b/renderer/src/tile_map.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectI; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectI; #[derive(Debug)] pub struct DenseTileMap { diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 3f5eb89a..0c98f0a5 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -12,11 +12,11 @@ use crate::builder::SceneBuilder; use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive}; use crate::paint::{self, PaintId}; use crate::sorted_vector::SortedVector; -use pathfinder_geometry::basic::line_segment::LineSegment2F; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::{RectF, RectI}; -use pathfinder_geometry::outline::{Contour, Outline, PointIndex}; -use pathfinder_geometry::segment::Segment; +use pathfinder_geometry::line_segment::LineSegment2F; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_geometry::rect::{RectF, RectI}; +use pathfinder_content::outline::{Contour, Outline, PointIndex}; +use pathfinder_content::segment::Segment; use std::cmp::Ordering; use std::mem; diff --git a/renderer/src/z_buffer.rs b/renderer/src/z_buffer.rs index 858a9e90..ae4bdf9e 100644 --- a/renderer/src/z_buffer.rs +++ b/renderer/src/z_buffer.rs @@ -15,8 +15,8 @@ use crate::paint; use crate::scene::PathObject; use crate::tile_map::DenseTileMap; use crate::tiles; -use pathfinder_geometry::basic::vector::Vector2I; -use pathfinder_geometry::basic::rect::RectF; +use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::rect::RectF; use std::ops::Range; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; diff --git a/svg/Cargo.toml b/svg/Cargo.toml index d735fdaf..13c630dc 100644 --- a/svg/Cargo.toml +++ b/svg/Cargo.toml @@ -8,6 +8,9 @@ authors = ["Patrick Walton "] bitflags = "1.0" usvg = "0.7" +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/svg/src/lib.rs b/svg/src/lib.rs index e9f14486..2d9b6454 100644 --- a/svg/src/lib.rs +++ b/svg/src/lib.rs @@ -13,14 +13,15 @@ #[macro_use] extern crate bitflags; -use pathfinder_geometry::basic::line_segment::LineSegment2F; -use pathfinder_geometry::basic::vector::Vector2F; -use pathfinder_geometry::basic::rect::RectF; -use pathfinder_geometry::basic::transform2d::{Transform2DF, Transform2DFPathIter}; -use pathfinder_geometry::color::ColorU; -use pathfinder_geometry::outline::Outline; -use pathfinder_geometry::segment::{Segment, SegmentFlags}; -use pathfinder_geometry::stroke::{LineCap, LineJoin, OutlineStrokeToFill, StrokeStyle}; +use pathfinder_content::color::ColorU; +use pathfinder_content::outline::Outline; +use pathfinder_content::segment::{Segment, SegmentFlags}; +use pathfinder_content::stroke::{LineCap, LineJoin, OutlineStrokeToFill, StrokeStyle}; +use pathfinder_content::transform::Transform2DFPathIter; +use pathfinder_geometry::line_segment::LineSegment2F; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::vector::Vector2F; use pathfinder_renderer::paint::Paint; use pathfinder_renderer::scene::{PathObject, Scene}; use std::fmt::{Display, Formatter, Result as FormatResult}; diff --git a/swf/Cargo.toml b/swf/Cargo.toml index b063d864..389a0fd7 100644 --- a/swf/Cargo.toml +++ b/swf/Cargo.toml @@ -8,6 +8,9 @@ edition = "2018" swf-parser = "0.7.0" swf-tree = "0.7.0" +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/swf/src/lib.rs b/swf/src/lib.rs index 94bf0e35..c8a683e8 100644 --- a/swf/src/lib.rs +++ b/swf/src/lib.rs @@ -9,10 +9,10 @@ // except according to those terms. use std::ops::Add; -use pathfinder_geometry::color::{ColorU, ColorF}; -use pathfinder_geometry::outline::{Outline, Contour}; -use pathfinder_geometry::basic::vector::Vector2F; -use pathfinder_geometry::stroke::{OutlineStrokeToFill, StrokeStyle}; +use pathfinder_content::color::{ColorU, ColorF}; +use pathfinder_content::outline::{Outline, Contour}; +use pathfinder_geometry::vector::Vector2F; +use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; use pathfinder_renderer::scene::{PathObject, Scene}; use swf_tree; diff --git a/swf/src/shapes.rs b/swf/src/shapes.rs index b2c94936..ff0a7b02 100644 --- a/swf/src/shapes.rs +++ b/swf/src/shapes.rs @@ -9,7 +9,7 @@ // except according to those terms. use pathfinder_renderer::paint::Paint; -use pathfinder_geometry::stroke::{LineJoin, LineCap}; +use pathfinder_content::stroke::{LineJoin, LineCap}; use crate::{Twips, Point2}; use std::mem; use std::cmp::Ordering; @@ -25,7 +25,7 @@ use swf_tree::{ shape_records, Vector2D }; -use pathfinder_geometry::color::ColorU; +use pathfinder_content::color::ColorU; use swf_tree::tags::DefineShape; #[derive(Clone, Copy, Debug)] diff --git a/text/Cargo.toml b/text/Cargo.toml index 76985371..493f98e3 100644 --- a/text/Cargo.toml +++ b/text/Cargo.toml @@ -9,6 +9,9 @@ euclid = "0.19" font-kit = "0.2" lyon_path = "0.12" +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/text/src/lib.rs b/text/src/lib.rs index cbf56765..49dcd1ce 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -13,10 +13,10 @@ use font_kit::error::GlyphLoadingError; use font_kit::hinting::HintingOptions; use font_kit::loader::Loader; use lyon_path::builder::{FlatPathBuilder, PathBuilder}; -use pathfinder_geometry::basic::vector::Vector2F; -use pathfinder_geometry::basic::transform2d::Transform2DF; -use pathfinder_geometry::outline::{Contour, Outline}; -use pathfinder_geometry::stroke::{OutlineStrokeToFill, StrokeStyle}; +use pathfinder_content::outline::{Contour, Outline}; +use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; +use pathfinder_geometry::transform2d::Transform2DF; +use pathfinder_geometry::vector::Vector2F; use pathfinder_renderer::paint::PaintId; use pathfinder_renderer::scene::{PathObject, Scene}; use skribo::{FontCollection, Layout, TextStyle}; diff --git a/ui/Cargo.toml b/ui/Cargo.toml index 259f8c26..2cad25a6 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -13,6 +13,9 @@ serde_json = "1.0" version = "0.1" features = ["serde"] +[dependencies.pathfinder_content] +path = "../content" + [dependencies.pathfinder_geometry] path = "../geometry" diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 18817224..7ae36ab3 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -17,9 +17,9 @@ extern crate serde_derive; use hashbrown::HashMap; -use pathfinder_geometry::basic::vector::{Vector2F, Vector2I}; -use pathfinder_geometry::basic::rect::RectI; -use pathfinder_geometry::color::ColorU; +use pathfinder_content::color::ColorU; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, Device, Primitive}; use pathfinder_gpu::{RenderOptions, RenderState, RenderTarget, UniformData, VertexAttrClass}; From 9107f21966f126b31114a2bab6740b62d3975d6c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 20 Jun 2019 22:18:09 -0700 Subject: [PATCH 09/14] wip --- .gitignore | 1 + Cargo.lock | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ c/Cargo.toml | 4 ++++ c/build.rs | 20 +++++++++++++++++++ c/cbindgen.toml | 13 +++++++++++++ 5 files changed, 89 insertions(+) create mode 100644 c/build.rs create mode 100644 c/cbindgen.toml diff --git a/.gitignore b/.gitignore index 4150bad5..ac289464 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ target node_modules /examples/c_canvas_minimal/build /shaders/build +/c/build # Editors *.swp diff --git a/Cargo.lock b/Cargo.lock index 1a5dc613..bc59b993 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,6 +231,23 @@ dependencies = [ "sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cbindgen" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (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)", + "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)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" version = "1.0.36" @@ -1379,6 +1396,7 @@ dependencies = [ name = "pathfinder_c" version = "0.1.0" dependencies = [ + "cbindgen 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", @@ -1858,6 +1876,14 @@ dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "roxmltree" version = "0.6.1" @@ -2181,6 +2207,19 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "3.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "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)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.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]] name = "term" version = "0.5.2" @@ -2236,6 +2275,14 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ttf-parser" version = "0.1.0" @@ -2528,6 +2575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum cbindgen 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f861ef68cabbb271d373a7795014052bff37edce22c620d95e395e8719d7dc5" "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.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" @@ -2683,6 +2731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum roxmltree 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "330d8f80a274bc3cb608908ee345970e7e24b96907f1ad69615a498bec57871c" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2718,12 +2767,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum swf-tree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c075cea0328cc5f6ee694bcd1c43534d1186a730d79258b10735f8f08e2f1baa" "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 tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" "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.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_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 toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum ttf-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29637063e570f7e5260924119666113215386c1b94e1d1ceb4525e269dfbe2d0" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" diff --git a/c/Cargo.toml b/c/Cargo.toml index caad0fec..e894ec6c 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -3,6 +3,7 @@ name = "pathfinder_c" version = "0.1.0" authors = ["Patrick Walton "] edition = "2018" +build = "build.rs" [lib] crate-type = ["staticlib"] @@ -31,3 +32,6 @@ path = "../renderer" [dependencies.pathfinder_simd] path = "../simd" + +[build-dependencies] +cbindgen = "0.8" diff --git a/c/build.rs b/c/build.rs new file mode 100644 index 00000000..def89d30 --- /dev/null +++ b/c/build.rs @@ -0,0 +1,20 @@ +// pathfinder/c/build.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 cbindgen; +use std::env; +use std::fs; + +fn main() { + fs::create_dir_all("build/include/pathfinder").expect("Failed to create directories!"); + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + cbindgen::generate(crate_dir).expect("cbindgen failed!") + .write_to_file("build/include/pathfinder/pathfinder.h"); +} diff --git a/c/cbindgen.toml b/c/cbindgen.toml new file mode 100644 index 00000000..d5f73f3a --- /dev/null +++ b/c/cbindgen.toml @@ -0,0 +1,13 @@ +language = "C" +header = "/* Generated code. Do not edit; instead run `cargo build` in `pathfinder_c`. */" +include_guard = "PF_PATHFINDER_H" +include_version = true + +[parse] +parse_deps = true +include = [ + "pathfinder_canvas", + "pathfinder_geometry", + "pathfinder_gl", + "pathfinder_renderer", +] From 1caad35b46a9b8ef16bb55fa171fd6dafbbf70e8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 11:35:18 -0700 Subject: [PATCH 10/14] Use `cbindgen` instead of hand-writing a header file --- c/cbindgen.toml | 8 +- c/include/pathfinder/pathfinder.h | 222 ----------------------------- examples/c_canvas_minimal/Makefile | 2 +- 3 files changed, 8 insertions(+), 224 deletions(-) delete mode 100644 c/include/pathfinder/pathfinder.h diff --git a/c/cbindgen.toml b/c/cbindgen.toml index d5f73f3a..4d096e5d 100644 --- a/c/cbindgen.toml +++ b/c/cbindgen.toml @@ -1,5 +1,10 @@ language = "C" -header = "/* Generated code. Do not edit; instead run `cargo build` in `pathfinder_c`. */" +header = """\ +/* Generated code. Do not edit; instead run `cargo build` in `pathfinder_c`. */ + +extern \"C\" { +""" +trailer = "}" include_guard = "PF_PATHFINDER_H" include_version = true @@ -7,6 +12,7 @@ include_version = true parse_deps = true include = [ "pathfinder_canvas", + "pathfinder_content", "pathfinder_geometry", "pathfinder_gl", "pathfinder_renderer", diff --git a/c/include/pathfinder/pathfinder.h b/c/include/pathfinder/pathfinder.h deleted file mode 100644 index 7ded8d08..00000000 --- a/c/include/pathfinder/pathfinder.h +++ /dev/null @@ -1,222 +0,0 @@ -// 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 - -// `canvas` - -#define PF_LINE_CAP_BUTT 0 -#define PF_LINE_CAP_SQUARE 1 -#define PF_LINE_CAP_ROUND 2 - -#define PF_LINE_JOIN_MITER 0 -#define PF_LINE_JOIN_BEVEL 1 -#define PF_LINE_JOIN_ROUND 2 - -// `geometry` - -#define PF_ARC_DIRECTION_CW 0 -#define PF_ARC_DIRECTION_CCW 1 - -// `gl` - -#define PF_GL_VERSION_GL3 0 -#define PF_GL_VERSION_GLES3 1 - -// `renderer` - -#define PF_RENDERER_OPTIONS_FLAGS_HAS_BACKGROUND_COLOR 0x1 - -// Types - -// `canvas` - -struct PFCanvas; -typedef struct PFCanvas *PFCanvasRef; -struct PFPath; -typedef struct PFPath *PFPathRef; -struct PFCanvasFontContext; -typedef struct PFCanvasFontContext *PFCanvasFontContextRef; -struct PFFillStyle; -typedef struct PFFillStyle *PFFillStyleRef; -typedef uint8_t PFLineCap; -typedef uint8_t PFLineJoin; -typedef uint8_t PFArcDirection; -struct PFTextMetrics { - float width; -}; -typedef struct PFTextMetrics PFTextMetrics; - -// `geometry` - -struct PFColorF { - float r, g, b, a; -}; -typedef struct PFColorF PFColorF; -struct PFColorU { - uint8_t r, g, b, a; -}; -typedef struct PFColorU PFColorU; -struct PFVector2F { - float x, y; -}; -typedef struct PFVector2F PFVector2F; -struct PFVector2I { - int32_t x, y; -}; -typedef struct PFVector2I PFVector2I; -struct PFRectF { - PFVector2F origin, lower_right; -}; -typedef struct PFRectF PFRectF; -struct PFRectI { - PFVector2I 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` - -struct PFResourceLoader; -typedef struct PFResourceLoader *PFResourceLoaderRef; - -// `renderer` - -typedef uint8_t PFRendererOptionsFlags; -struct PFRendererOptions { - PFColorF background_color; - PFRendererOptionsFlags flags; -}; -struct PFBuildOptions { - uint32_t placeholder; -}; -typedef struct PFRendererOptions PFRendererOptions; -typedef struct PFBuildOptions PFBuildOptions; -struct PFScene; -typedef struct PFScene *PFSceneRef; -struct PFSceneProxy; -typedef struct PFSceneProxy *PFSceneProxyRef; - -// Functions - -// `canvas` - -PFCanvasRef PFCanvasCreate(PFCanvasFontContextRef font_context, const PFVector2F *size); -void PFCanvasDestroy(PFCanvasRef canvas); -PFCanvasFontContextRef PFCanvasFontContextCreateWithSystemSource(); -void PFCanvasFontContextDestroy(PFCanvasFontContextRef font_context); -PFCanvasFontContextRef PFCanvasFontContextClone(PFCanvasFontContextRef font_context); -PFSceneRef PFCanvasCreateScene(PFCanvasRef canvas); -void PFCanvasFillRect(PFCanvasRef canvas, const PFRectF *rect); -void PFCanvasStrokeRect(PFCanvasRef canvas, const PFRectF *rect); -void PFCanvasFillText(PFCanvasRef canvas, - const char *string, - size_t string_len, - const PFVector2F *position); -void PFCanvasStrokeText(PFCanvasRef canvas, - const char *string, - size_t string_len, - const PFVector2F *position); -void PFCanvasMeasureText(PFCanvasRef canvas, - const char *string, - size_t string_len, - PFTextMetrics *out_text_metrics); -void PFCanvasSetLineWidth(PFCanvasRef canvas, float new_line_width); -void PFCanvasSetLineCap(PFCanvasRef canvas, PFLineCap new_line_cap); -void PFCanvasSetLineJoin(PFCanvasRef canvas, PFLineJoin new_line_join); -void PFCanvasSetMiterLimit(PFCanvasRef canvas, float new_miter_limit); -void PFCanvasSetLineDash(PFCanvasRef canvas, - const float *new_line_dashes, - size_t new_line_dash_count); -void PFCanvasSetLineDashOffset(PFCanvasRef canvas, float offset); -void PFCanvasSetFillStyle(PFCanvasRef canvas, PFFillStyleRef fill_style); -void PFCanvasSetStrokeStyle(PFCanvasRef canvas, PFFillStyleRef stroke_style); -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 PFVector2F *to); -void PFPathLineTo(PFPathRef path, const PFVector2F *to); -void PFPathQuadraticCurveTo(PFPathRef path, const PFVector2F *ctrl, const PFVector2F *to); -void PFPathBezierCurveTo(PFPathRef path, - const PFVector2F *ctrl0, - const PFVector2F *ctrl1, - const PFVector2F *to); -void PFPathArc(PFPathRef path, - const PFVector2F *center, - float radius, - float start_angle, - float end_angle, - PFArcDirection direction); -void PFPathArcTo(PFPathRef path, const PFVector2F *ctrl, const PFVector2F *to, float radius); -void PFPathRect(PFPathRef path, const PFRectF *rect); -void PFPathEllipse(PFPathRef path, - const PFVector2F *center, - const PFVector2F *axes, - float rotation, - float start_angle, - float end_angle); -void PFPathClosePath(PFPathRef path); -PFFillStyleRef PFFillStyleCreateColor(PFColorU color); -void PFFillStyleDestroy(PFFillStyleRef fill_style); - -// `gl` - -PFGLDestFramebufferRef PFGLDestFramebufferCreateFullWindow(const PFVector2I *window_size); -void PFGLDestFramebufferDestroy(PFGLDestFramebufferRef dest_framebuffer); -PFGLDeviceRef PFGLDeviceCreate(PFGLVersion version, uint32_t default_framebuffer); -void PFGLDeviceDestroy(PFGLDeviceRef device); -void PFGLLoadWith(PFGLFunctionLoader loader, void *userdata); -PFGLRendererRef PFGLRendererCreate(PFGLDeviceRef device, - PFResourceLoaderRef resources, - PFGLDestFramebufferRef dest_framebuffer, - const PFRendererOptions *options); -void PFGLRendererDestroy(PFGLRendererRef renderer); -/// Returns a borrowed reference to the device. -PFGLDeviceRef PFGLRendererGetDevice(PFGLRendererRef renderer); -void PFSceneProxyBuildAndRenderGL(PFSceneProxyRef scene_proxy, - PFGLRendererRef renderer, - const PFBuildOptions *build_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/examples/c_canvas_minimal/Makefile b/examples/c_canvas_minimal/Makefile index 35f4b9ef..14563401 100644 --- a/examples/c_canvas_minimal/Makefile +++ b/examples/c_canvas_minimal/Makefile @@ -5,7 +5,7 @@ RUST_TARGET_DIR?=../../target RUST_SRC_DIR?=../../c RUSTFLAGS?=-C target-cpu=native -CFLAGS?=-Wall -g -I../../c/include +CFLAGS?=-Wall -g -I../../c/build/include LIBS?=-lpathfinder_c MKDIR?=mkdir -p RM?=rm From 1c34b12948da385e71f273b6717359d463dcbfef Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 13:17:11 -0700 Subject: [PATCH 11/14] Add some font functions to the C API --- Cargo.lock | 1 + c/Cargo.toml | 1 + c/src/lib.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index bc59b993..9333a6c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1397,6 +1397,7 @@ name = "pathfinder_c" version = "0.1.0" dependencies = [ "cbindgen 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", diff --git a/c/Cargo.toml b/c/Cargo.toml index e894ec6c..a4ea30e5 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -9,6 +9,7 @@ build = "build.rs" crate-type = ["staticlib"] [dependencies] +font-kit = "0.2" gl = "0.6" libc = "0.2" diff --git a/c/src/lib.rs b/c/src/lib.rs index 9823f7d1..b8403638 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -10,6 +10,7 @@ //! C bindings to Pathfinder. +use font_kit::handle::Handle; use gl; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin}; use pathfinder_canvas::{Path2D, TextMetrics}; @@ -55,6 +56,9 @@ pub const PF_RENDERER_OPTIONS_FLAGS_HAS_BACKGROUND_COLOR: u8 = 0x1; // Types +// External: `font-kit` +pub type FKHandleRef = *mut Handle; + // `canvas` pub type PFCanvasRef = *mut CanvasRenderingContext2D; pub type PFPathRef = *mut Path2D; @@ -154,6 +158,16 @@ pub unsafe extern "C" fn PFCanvasFontContextCreateWithSystemSource() -> PFCanvas Box::into_raw(Box::new(CanvasFontContext::from_system_source())) } +#[no_mangle] +pub unsafe extern "C" fn PFCanvasFontContextCreateWithFonts(fonts: *const FKHandleRef, + font_count: usize) + -> PFCanvasFontContextRef { + let fonts = slice::from_raw_parts(fonts, font_count); + Box::into_raw(Box::new(CanvasFontContext::from_fonts(fonts.into_iter().map(|font| { + (**font).clone() + })))) +} + #[no_mangle] pub unsafe extern "C" fn PFCanvasFontContextDestroy(font_context: PFCanvasFontContextRef) { drop(Box::from_raw(font_context)) @@ -250,6 +264,18 @@ pub unsafe extern "C" fn PFCanvasSetLineDashOffset(canvas: PFCanvasRef, new_offs (*canvas).set_line_dash_offset(new_offset) } +#[no_mangle] +pub unsafe extern "C" fn PFCanvasSetFontByPostScriptName(canvas: PFCanvasRef, + postscript_name: *const c_char, + postscript_name_len: usize) { + (*canvas).set_font_by_postscript_name(to_rust_string(&postscript_name, postscript_name_len)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFCanvasSetFontSize(canvas: PFCanvasRef, new_font_size: f32) { + (*canvas).set_font_size(new_font_size) +} + #[no_mangle] pub unsafe extern "C" fn PFCanvasSetFillStyle(canvas: PFCanvasRef, fill_style: PFFillStyleRef) { (*canvas).set_fill_style(*fill_style) From 2c49a3360e1a4f907d25b6c033f6244b2fec1243 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 13:37:17 -0700 Subject: [PATCH 12/14] Add Metal support to the C API --- Cargo.lock | 3 ++ c/Cargo.toml | 7 +++ c/src/lib.rs | 77 ++++++++++++++++++++++++++++++ examples/c_canvas_minimal/Makefile | 2 +- 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 9333a6c7..215c4503 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1398,13 +1398,16 @@ version = "0.1.0" dependencies = [ "cbindgen 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.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)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", + "pathfinder_metal 0.1.0", "pathfinder_renderer 0.1.0", "pathfinder_simd 0.3.0", ] diff --git a/c/Cargo.toml b/c/Cargo.toml index a4ea30e5..e1c0eb0b 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["staticlib"] [dependencies] font-kit = "0.2" +foreign-types = "0.3" gl = "0.6" libc = "0.2" @@ -34,5 +35,11 @@ path = "../renderer" [dependencies.pathfinder_simd] path = "../simd" +[target.'cfg(target_os = "macos")'.dependencies] +metal = "0.14" + +[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] +path = "../metal" + [build-dependencies] cbindgen = "0.8" diff --git a/c/src/lib.rs b/c/src/lib.rs index b8403638..6b6235c1 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -11,6 +11,7 @@ //! C bindings to Pathfinder. use font_kit::handle::Handle; +use foreign_types::ForeignTypeRef; use gl; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin}; use pathfinder_canvas::{Path2D, TextMetrics}; @@ -33,6 +34,11 @@ use std::os::raw::{c_char, c_void}; use std::slice; use std::str; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +use metal::{CAMetalLayer, CoreAnimationLayerRef}; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +use pathfinder_metal::MetalDevice; + // Constants // `canvas` @@ -118,10 +124,18 @@ pub type PFGLFunctionLoader = extern "C" fn(name: *const c_char, userdata: *mut // `gpu` pub type PFGLDestFramebufferRef = *mut DestFramebuffer; pub type PFGLRendererRef = *mut Renderer; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +pub type PFMetalDestFramebufferRef = *mut DestFramebuffer; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +pub type PFMetalRendererRef = *mut Renderer; // FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is // stable? pub type PFResourceLoaderRef = *mut Box; +// `metal` +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +pub type PFMetalDeviceRef = *mut MetalDevice; + // `renderer` pub type PFSceneRef = *mut Scene; pub type PFSceneProxyRef = *mut SceneProxy; @@ -456,6 +470,46 @@ pub unsafe extern "C" fn PFGLRendererGetDevice(renderer: PFGLRendererRef) -> PFG &mut (*renderer).device } +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDestFramebufferCreateFullWindow(window_size: *const PFVector2I) + -> PFMetalDestFramebufferRef { + Box::into_raw(Box::new(DestFramebuffer::full_window((*window_size).to_rust()))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDestFramebufferDestroy(dest_framebuffer: + PFMetalDestFramebufferRef) { + drop(Box::from_raw(dest_framebuffer)) +} + +/// Takes ownership of `device` and `dest_framebuffer`, but not `resources`. +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalRendererCreate(device: PFMetalDeviceRef, + resources: PFResourceLoaderRef, + dest_framebuffer: PFMetalDestFramebufferRef, + options: *const PFRendererOptions) + -> PFMetalRendererRef { + Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device), + &**resources, + *Box::from_raw(dest_framebuffer), + (*options).to_rust()))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalRendererDestroy(renderer: PFMetalRendererRef) { + drop(Box::from_raw(renderer)) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalRendererGetDevice(renderer: PFMetalRendererRef) -> PFMetalDeviceRef { + &mut (*renderer).device +} + #[no_mangle] pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef, renderer: PFGLRendererRef, @@ -463,6 +517,29 @@ pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyR (*scene_proxy).build_and_render(&mut *renderer, (*build_options).to_rust()) } +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFSceneProxyBuildAndRenderMetal(scene_proxy: PFSceneProxyRef, + renderer: PFMetalRendererRef, + build_options: *const PFBuildOptions) { + (*scene_proxy).build_and_render(&mut *renderer, (*build_options).to_rust()) +} + +// `metal` + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDeviceCreate(layer: *mut CAMetalLayer) + -> PFMetalDeviceRef { + Box::into_raw(Box::new(MetalDevice::new(CoreAnimationLayerRef::from_ptr(layer)))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDeviceDestroy(device: PFMetalDeviceRef) { + drop(Box::from_raw(device)) +} + // `renderer` #[no_mangle] diff --git a/examples/c_canvas_minimal/Makefile b/examples/c_canvas_minimal/Makefile index 14563401..d2c8a5dc 100644 --- a/examples/c_canvas_minimal/Makefile +++ b/examples/c_canvas_minimal/Makefile @@ -15,7 +15,7 @@ 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 + LIBS+=-framework Metal -lharfbuzz else LIBS+=-lGL endif From d86ff9011a4b304121ee75ed5f6352b426f9852a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 21 Jun 2019 18:04:18 -0700 Subject: [PATCH 13/14] Update the postprocessing shader and vertex array for the Metal changes. Closes #201. --- renderer/src/gpu/renderer.rs | 4 ++-- resources/shaders/gl3/post.vs.glsl | 10 ++++++++-- resources/shaders/metal/post.vs.metal | 6 ++++-- shaders/post.vs.glsl | 10 ++++++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 87565d36..f70f56d7 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -654,7 +654,7 @@ where } } - self.device.draw_arrays(4, &RenderState { + self.device.draw_elements(6, &RenderState { target: &self.dest_render_target(), program: &self.postprocess_program.program, vertex_array: &self.postprocess_vertex_array.vertex_array, @@ -1451,7 +1451,7 @@ where device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor { size: 2, class: VertexAttrClass::Int, - attr_type: VertexAttrType::U16, + attr_type: VertexAttrType::I16, stride: 4, offset: 0, divisor: 0, diff --git a/resources/shaders/gl3/post.vs.glsl b/resources/shaders/gl3/post.vs.glsl index b30dcf8d..a1d8effb 100644 --- a/resources/shaders/gl3/post.vs.glsl +++ b/resources/shaders/gl3/post.vs.glsl @@ -19,7 +19,13 @@ in ivec2 aPosition; out vec2 vTexCoord; void main(){ - vTexCoord = vec2(aPosition); - gl_Position = vec4(vec2(aPosition)* 2.0 - 1.0, 0.0, 1.0); + vec2 position = vec2(aPosition); + vTexCoord = position; + + + + + + gl_Position = vec4(vec2(position)* 2.0 - 1.0, 0.0, 1.0); } diff --git a/resources/shaders/metal/post.vs.metal b/resources/shaders/metal/post.vs.metal index 0fcc0bf6..f7385038 100644 --- a/resources/shaders/metal/post.vs.metal +++ b/resources/shaders/metal/post.vs.metal @@ -18,8 +18,10 @@ struct main0_in vertex main0_out main0(main0_in in [[stage_in]]) { main0_out out = {}; - out.vTexCoord = float2(in.aPosition); - out.gl_Position = float4((float2(in.aPosition) * 2.0) - float2(1.0), 0.0, 1.0); + float2 position = float2(in.aPosition); + out.vTexCoord = position; + position.y = 1.0 - position.y; + out.gl_Position = float4((float2(position) * 2.0) - float2(1.0), 0.0, 1.0); return out; } diff --git a/shaders/post.vs.glsl b/shaders/post.vs.glsl index 137cf388..52cf3eea 100644 --- a/shaders/post.vs.glsl +++ b/shaders/post.vs.glsl @@ -17,6 +17,12 @@ in ivec2 aPosition; out vec2 vTexCoord; void main() { - vTexCoord = vec2(aPosition); - gl_Position = vec4(vec2(aPosition) * 2.0 - 1.0, 0.0, 1.0); + vec2 position = vec2(aPosition); + vTexCoord = position; + +#ifdef PF_ORIGIN_UPPER_LEFT + // FIXME(pcwalton): This is wrong. + position.y = 1.0 - position.y; +#endif + gl_Position = vec4(vec2(position) * 2.0 - 1.0, 0.0, 1.0); } From dfdfebfdd239346f733c5443f6f067158d900a9b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Sat, 22 Jun 2019 14:38:56 -0700 Subject: [PATCH 14/14] Fix use-after-free in Metal argument encoding --- metal/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/metal/src/lib.rs b/metal/src/lib.rs index 3c1c4f89..13f157bc 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -1356,6 +1356,7 @@ impl FunctionExt for Function { let encoder: *mut MTLArgumentEncoder = msg_send![self.as_ptr(), newArgumentEncoderWithBufferIndex:buffer_index reflection:&mut reflection]; + msg_send![reflection, retain]; (ArgumentEncoder::from_ptr(encoder), Argument::from_ptr(reflection)) } }