Add the ability to merge scenes together, and expose it to the canvas API.
Closes #268.
This commit is contained in:
parent
5d43eedf20
commit
ba7fe4be39
|
@ -13,8 +13,8 @@
|
||||||
use font_kit::handle::Handle;
|
use font_kit::handle::Handle;
|
||||||
use foreign_types::ForeignTypeRef;
|
use foreign_types::ForeignTypeRef;
|
||||||
use gl;
|
use gl;
|
||||||
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin, Path2D};
|
use pathfinder_canvas::{Canvas, CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin};
|
||||||
use pathfinder_canvas::{TextAlign, TextMetrics};
|
use pathfinder_canvas::{Path2D, TextAlign, TextMetrics};
|
||||||
use pathfinder_color::{ColorF, ColorU};
|
use pathfinder_color::{ColorF, ColorU};
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::outline::ArcDirection;
|
use pathfinder_content::outline::ArcDirection;
|
||||||
|
@ -196,8 +196,7 @@ pub type PFRenderTransformRef = *mut RenderTransform;
|
||||||
pub unsafe extern "C" fn PFCanvasCreate(font_context: PFCanvasFontContextRef,
|
pub unsafe extern "C" fn PFCanvasCreate(font_context: PFCanvasFontContextRef,
|
||||||
size: *const PFVector2F)
|
size: *const PFVector2F)
|
||||||
-> PFCanvasRef {
|
-> PFCanvasRef {
|
||||||
Box::into_raw(Box::new(CanvasRenderingContext2D::new((*font_context).clone(),
|
Box::into_raw(Box::new(Canvas::new((*size).to_rust()).get_context_2d((*font_context).clone())))
|
||||||
(*size).to_rust())))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -235,7 +234,7 @@ pub unsafe extern "C" fn PFCanvasFontContextRelease(font_context: PFCanvasFontCo
|
||||||
/// the scene is destroyed.
|
/// the scene is destroyed.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef {
|
pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef {
|
||||||
Box::into_raw(Box::new(Box::from_raw(canvas).into_scene()))
|
Box::into_raw(Box::new(Box::from_raw(canvas).into_canvas().into_scene()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawing rectangles
|
// Drawing rectangles
|
||||||
|
|
|
@ -16,7 +16,7 @@ use pathfinder_content::effects::{BlendMode, BlurDirection, Effects, Filter};
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::gradient::Gradient;
|
use pathfinder_content::gradient::Gradient;
|
||||||
use pathfinder_content::outline::{ArcDirection, Contour, Outline};
|
use pathfinder_content::outline::{ArcDirection, Contour, Outline};
|
||||||
use pathfinder_content::pattern::{Pattern, PatternFlags};
|
use pathfinder_content::pattern::{Pattern, PatternFlags, PatternSource};
|
||||||
use pathfinder_content::render_target::RenderTargetId;
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_content::stroke::{LineCap, LineJoin as StrokeLineJoin};
|
use pathfinder_content::stroke::{LineCap, LineJoin as StrokeLineJoin};
|
||||||
use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle};
|
use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle};
|
||||||
|
@ -43,7 +43,6 @@ use crate::text::FontCollection;
|
||||||
#[cfg(feature = "pf-text")]
|
#[cfg(feature = "pf-text")]
|
||||||
pub use text::TextMetrics;
|
pub use text::TextMetrics;
|
||||||
|
|
||||||
|
|
||||||
const HAIRLINE_STROKE_WIDTH: f32 = 0.0333;
|
const HAIRLINE_STROKE_WIDTH: f32 = 0.0333;
|
||||||
const DEFAULT_FONT_SIZE: f32 = 10.0;
|
const DEFAULT_FONT_SIZE: f32 = 10.0;
|
||||||
|
|
||||||
|
@ -68,8 +67,44 @@ mod text {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub struct CanvasRenderingContext2D {
|
pub struct Canvas {
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Canvas {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(size: Vector2F) -> Canvas {
|
||||||
|
let mut scene = Scene::new();
|
||||||
|
scene.set_view_box(RectF::new(Vector2F::zero(), size));
|
||||||
|
Canvas::from_scene(scene)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_scene(scene: Scene) -> Canvas {
|
||||||
|
Canvas { scene }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn into_scene(self) -> Scene {
|
||||||
|
self.scene
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_context_2d(self, font_context: CanvasFontContext) -> CanvasRenderingContext2D {
|
||||||
|
#[cfg(feature = "pf-text")]
|
||||||
|
let default_font_collection = font_context.default_font_collection.clone();
|
||||||
|
#[cfg(not(feature = "pf-text"))]
|
||||||
|
let default_font_collection = Arc::new(FontCollection);
|
||||||
|
CanvasRenderingContext2D {
|
||||||
|
canvas: self,
|
||||||
|
current_state: State::default(default_font_collection),
|
||||||
|
saved_states: vec![],
|
||||||
|
font_context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CanvasRenderingContext2D {
|
||||||
|
canvas: Canvas,
|
||||||
current_state: State,
|
current_state: State,
|
||||||
saved_states: Vec<State>,
|
saved_states: Vec<State>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -77,29 +112,11 @@ pub struct CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasRenderingContext2D {
|
impl CanvasRenderingContext2D {
|
||||||
#[inline]
|
// Finalization
|
||||||
pub fn new(font_context: CanvasFontContext, size: Vector2F) -> CanvasRenderingContext2D {
|
|
||||||
let mut scene = Scene::new();
|
|
||||||
scene.set_view_box(RectF::new(Vector2F::zero(), size));
|
|
||||||
CanvasRenderingContext2D::from_scene(font_context, scene)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_scene(font_context: CanvasFontContext, scene: Scene) -> CanvasRenderingContext2D {
|
|
||||||
#[cfg(feature = "pf-text")]
|
|
||||||
let default_font_collection = font_context.default_font_collection.clone();
|
|
||||||
#[cfg(not(feature = "pf-text"))]
|
|
||||||
let default_font_collection = Arc::new(FontCollection);
|
|
||||||
CanvasRenderingContext2D {
|
|
||||||
scene,
|
|
||||||
current_state: State::default(default_font_collection),
|
|
||||||
saved_states: vec![],
|
|
||||||
font_context,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_scene(self) -> Scene {
|
pub fn into_canvas(self) -> Canvas {
|
||||||
self.scene
|
self.canvas
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawing rectangles
|
// Drawing rectangles
|
||||||
|
@ -124,14 +141,14 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
let paint = Paint::transparent_black();
|
let paint = Paint::transparent_black();
|
||||||
let paint = self.current_state.resolve_paint(&paint);
|
let paint = self.current_state.resolve_paint(&paint);
|
||||||
let paint_id = self.scene.push_paint(&paint);
|
let paint_id = self.canvas.scene.push_paint(&paint);
|
||||||
|
|
||||||
let mut outline = path.into_outline();
|
let mut outline = path.into_outline();
|
||||||
outline.transform(&self.current_state.transform);
|
outline.transform(&self.current_state.transform);
|
||||||
|
|
||||||
let mut path = DrawPath::new(outline, paint_id);
|
let mut path = DrawPath::new(outline, paint_id);
|
||||||
path.set_blend_mode(BlendMode::Clear);
|
path.set_blend_mode(BlendMode::Clear);
|
||||||
self.scene.push_path(path);
|
self.canvas.scene.push_path(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Line styles
|
// Line styles
|
||||||
|
@ -225,14 +242,14 @@ impl CanvasRenderingContext2D {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn fill_path(&mut self, path: Path2D, fill_rule: FillRule) {
|
pub fn fill_path(&mut self, path: Path2D, fill_rule: FillRule) {
|
||||||
let paint = self.current_state.resolve_paint(&self.current_state.fill_paint);
|
let paint = self.current_state.resolve_paint(&self.current_state.fill_paint);
|
||||||
let paint_id = self.scene.push_paint(&paint);
|
let paint_id = self.canvas.scene.push_paint(&paint);
|
||||||
self.push_path(path.into_outline(), paint_id, fill_rule);
|
self.push_path(path.into_outline(), paint_id, fill_rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stroke_path(&mut self, path: Path2D) {
|
pub fn stroke_path(&mut self, path: Path2D) {
|
||||||
let paint = self.current_state.resolve_paint(&self.current_state.stroke_paint);
|
let paint = self.current_state.resolve_paint(&self.current_state.stroke_paint);
|
||||||
let paint_id = self.scene.push_paint(&paint);
|
let paint_id = self.canvas.scene.push_paint(&paint);
|
||||||
|
|
||||||
let mut stroke_style = self.current_state.resolve_stroke_style();
|
let mut stroke_style = self.current_state.resolve_stroke_style();
|
||||||
|
|
||||||
|
@ -267,7 +284,7 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
let mut clip_path = ClipPath::new(outline);
|
let mut clip_path = ClipPath::new(outline);
|
||||||
clip_path.set_fill_rule(fill_rule);
|
clip_path.set_fill_rule(fill_rule);
|
||||||
let clip_path_id = self.scene.push_clip_path(clip_path);
|
let clip_path_id = self.canvas.scene.push_clip_path(clip_path);
|
||||||
|
|
||||||
self.current_state.clip_path = Some(clip_path_id);
|
self.current_state.clip_path = Some(clip_path_id);
|
||||||
}
|
}
|
||||||
|
@ -282,7 +299,7 @@ impl CanvasRenderingContext2D {
|
||||||
let shadow_blur_render_target_ids = self.push_shadow_blur_render_targets_if_needed();
|
let shadow_blur_render_target_ids = self.push_shadow_blur_render_targets_if_needed();
|
||||||
|
|
||||||
let paint = self.current_state.resolve_paint(&self.current_state.shadow_paint);
|
let paint = self.current_state.resolve_paint(&self.current_state.shadow_paint);
|
||||||
let paint_id = self.scene.push_paint(&paint);
|
let paint_id = self.canvas.scene.push_paint(&paint);
|
||||||
|
|
||||||
let mut outline = outline.clone();
|
let mut outline = outline.clone();
|
||||||
outline.transform(&(Transform2F::from_translation(self.current_state.shadow_offset) *
|
outline.transform(&(Transform2F::from_translation(self.current_state.shadow_offset) *
|
||||||
|
@ -293,7 +310,7 @@ impl CanvasRenderingContext2D {
|
||||||
path.set_fill_rule(fill_rule);
|
path.set_fill_rule(fill_rule);
|
||||||
path.set_blend_mode(blend_mode);
|
path.set_blend_mode(blend_mode);
|
||||||
path.set_opacity(opacity);
|
path.set_opacity(opacity);
|
||||||
self.scene.push_path(path);
|
self.canvas.scene.push_path(path);
|
||||||
|
|
||||||
self.composite_shadow_blur_render_targets_if_needed(shadow_blur_render_target_ids);
|
self.composite_shadow_blur_render_targets_if_needed(shadow_blur_render_target_ids);
|
||||||
}
|
}
|
||||||
|
@ -305,7 +322,7 @@ impl CanvasRenderingContext2D {
|
||||||
path.set_fill_rule(fill_rule);
|
path.set_fill_rule(fill_rule);
|
||||||
path.set_blend_mode(blend_mode);
|
path.set_blend_mode(blend_mode);
|
||||||
path.set_opacity(opacity);
|
path.set_opacity(opacity);
|
||||||
self.scene.push_path(path);
|
self.canvas.scene.push_path(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_shadow_blur_render_targets_if_needed(&mut self) -> Option<[RenderTargetId; 2]> {
|
fn push_shadow_blur_render_targets_if_needed(&mut self) -> Option<[RenderTargetId; 2]> {
|
||||||
|
@ -313,11 +330,11 @@ impl CanvasRenderingContext2D {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_target_size = self.scene.view_box().size().ceil().to_i32();
|
let render_target_size = self.canvas.scene.view_box().size().ceil().to_i32();
|
||||||
let render_target_id_a =
|
let render_target_a = RenderTarget::new(render_target_size, String::new());
|
||||||
self.scene.push_render_target(RenderTarget::new(render_target_size, String::new()));
|
let render_target_id_a = self.canvas.scene.push_render_target(render_target_a);
|
||||||
let render_target_id_b =
|
let render_target_b = RenderTarget::new(render_target_size, String::new());
|
||||||
self.scene.push_render_target(RenderTarget::new(render_target_size, String::new()));
|
let render_target_id_b = self.canvas.scene.push_render_target(render_target_b);
|
||||||
Some([render_target_id_a, render_target_id_b])
|
Some([render_target_id_a, render_target_id_b])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,13 +347,13 @@ impl CanvasRenderingContext2D {
|
||||||
};
|
};
|
||||||
|
|
||||||
let sigma = self.current_state.shadow_blur * 0.5;
|
let sigma = self.current_state.shadow_blur * 0.5;
|
||||||
self.scene.pop_render_target();
|
self.canvas.scene.pop_render_target();
|
||||||
self.scene.draw_render_target(render_target_ids[1], Effects::new(Filter::Blur {
|
self.canvas.scene.draw_render_target(render_target_ids[1], Effects::new(Filter::Blur {
|
||||||
direction: BlurDirection::X,
|
direction: BlurDirection::X,
|
||||||
sigma,
|
sigma,
|
||||||
}));
|
}));
|
||||||
self.scene.pop_render_target();
|
self.canvas.scene.pop_render_target();
|
||||||
self.scene.draw_render_target(render_target_ids[0], Effects::new(Filter::Blur {
|
self.canvas.scene.draw_render_target(render_target_ids[0], Effects::new(Filter::Blur {
|
||||||
direction: BlurDirection::Y,
|
direction: BlurDirection::Y,
|
||||||
sigma,
|
sigma,
|
||||||
}));
|
}));
|
||||||
|
@ -431,6 +448,19 @@ impl CanvasRenderingContext2D {
|
||||||
self.current_state = state;
|
self.current_state = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
|
||||||
|
pub fn create_pattern_from_canvas(&mut self, canvas: Canvas) -> Pattern {
|
||||||
|
let subscene = canvas.into_scene();
|
||||||
|
let subscene_size = subscene.view_box().size().ceil().to_i32();
|
||||||
|
let render_target = RenderTarget::new(subscene_size, String::new());
|
||||||
|
let render_target_id = self.canvas.scene.push_render_target(render_target);
|
||||||
|
self.canvas.scene.append_scene(subscene);
|
||||||
|
self.canvas.scene.pop_render_target();
|
||||||
|
let pattern_source = PatternSource::RenderTarget(render_target_id);
|
||||||
|
Pattern::new(pattern_source, Transform2F::default(), PatternFlags::empty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -26,12 +26,12 @@ use std::sync::Arc;
|
||||||
|
|
||||||
impl CanvasRenderingContext2D {
|
impl CanvasRenderingContext2D {
|
||||||
pub fn fill_text(&mut self, string: &str, position: Vector2F) {
|
pub fn fill_text(&mut self, string: &str, position: Vector2F) {
|
||||||
let paint_id = self.scene.push_paint(&self.current_state.fill_paint);
|
let paint_id = self.canvas.scene.push_paint(&self.current_state.fill_paint);
|
||||||
self.fill_or_stroke_text(string, position, paint_id, TextRenderMode::Fill);
|
self.fill_or_stroke_text(string, position, paint_id, TextRenderMode::Fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stroke_text(&mut self, string: &str, position: Vector2F) {
|
pub fn stroke_text(&mut self, string: &str, position: Vector2F) {
|
||||||
let paint_id = self.scene.push_paint(&self.current_state.stroke_paint);
|
let paint_id = self.canvas.scene.push_paint(&self.current_state.stroke_paint);
|
||||||
let render_mode = TextRenderMode::Stroke(self.current_state.resolve_stroke_style());
|
let render_mode = TextRenderMode::Stroke(self.current_state.resolve_stroke_style());
|
||||||
self.fill_or_stroke_text(string, position, paint_id, render_mode);
|
self.fill_or_stroke_text(string, position, paint_id, render_mode);
|
||||||
}
|
}
|
||||||
|
@ -41,13 +41,13 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_layout(&mut self, layout: &Layout, transform: Transform2F) {
|
pub fn fill_layout(&mut self, layout: &Layout, transform: Transform2F) {
|
||||||
let paint_id = self.scene.push_paint(&self.current_state.fill_paint);
|
let paint_id = self.canvas.scene.push_paint(&self.current_state.fill_paint);
|
||||||
drop(self.scene.push_layout(&layout,
|
drop(self.canvas.scene.push_layout(&layout,
|
||||||
&TextStyle { size: self.current_state.font_size },
|
&TextStyle { size: self.current_state.font_size },
|
||||||
&(transform * self.current_state.transform),
|
&(transform * self.current_state.transform),
|
||||||
TextRenderMode::Fill,
|
TextRenderMode::Fill,
|
||||||
HintingOptions::None,
|
HintingOptions::None,
|
||||||
paint_id));
|
paint_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_or_stroke_text(&mut self,
|
fn fill_or_stroke_text(&mut self,
|
||||||
|
@ -77,12 +77,12 @@ impl CanvasRenderingContext2D {
|
||||||
let transform = self.current_state.transform * Transform2F::from_translation(position);
|
let transform = self.current_state.transform * Transform2F::from_translation(position);
|
||||||
|
|
||||||
// TODO(pcwalton): Report errors.
|
// TODO(pcwalton): Report errors.
|
||||||
drop(self.scene.push_layout(&layout,
|
drop(self.canvas.scene.push_layout(&layout,
|
||||||
&TextStyle { size: self.current_state.font_size },
|
&TextStyle { size: self.current_state.font_size },
|
||||||
&transform,
|
&transform,
|
||||||
render_mode,
|
render_mode,
|
||||||
HintingOptions::None,
|
HintingOptions::None,
|
||||||
paint_id));
|
paint_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_text(&self, string: &str) -> Layout {
|
fn layout_text(&self, string: &str) -> Layout {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use glutin::{ContextBuilder, GlProfile, GlRequest};
|
||||||
use glutin::event_loop::{ControlFlow, EventLoop};
|
use glutin::event_loop::{ControlFlow, EventLoop};
|
||||||
use glutin::event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
use glutin::event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
use glutin::window::WindowBuilder;
|
use glutin::window::WindowBuilder;
|
||||||
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D};
|
use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D};
|
||||||
use pathfinder_color::ColorF;
|
use pathfinder_color::ColorF;
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::vector::{vec2f, vec2i};
|
use pathfinder_geometry::vector::{vec2f, vec2i};
|
||||||
|
@ -54,8 +54,8 @@ fn main() {
|
||||||
RendererOptions { background_color: Some(ColorF::white()) });
|
RendererOptions { background_color: Some(ColorF::white()) });
|
||||||
|
|
||||||
// Make a canvas. We're going to draw a house.
|
// Make a canvas. We're going to draw a house.
|
||||||
let mut canvas = CanvasRenderingContext2D::new(CanvasFontContext::from_system_source(),
|
let font_context = CanvasFontContext::from_system_source();
|
||||||
window_size.to_f32());
|
let mut canvas = Canvas::new(window_size.to_f32()).get_context_2d(font_context);
|
||||||
|
|
||||||
// Set line width.
|
// Set line width.
|
||||||
canvas.set_line_width(10.0);
|
canvas.set_line_width(10.0);
|
||||||
|
@ -75,7 +75,7 @@ fn main() {
|
||||||
canvas.stroke_path(path);
|
canvas.stroke_path(path);
|
||||||
|
|
||||||
// Render the canvas to screen.
|
// Render the canvas to screen.
|
||||||
let scene = SceneProxy::from_scene(canvas.into_scene(), RayonExecutor);
|
let scene = SceneProxy::from_scene(canvas.into_canvas().into_scene(), RayonExecutor);
|
||||||
scene.build_and_render(&mut renderer, BuildOptions::default());
|
scene.build_and_render(&mut renderer, BuildOptions::default());
|
||||||
gl_context.swap_buffers().unwrap();
|
gl_context.swap_buffers().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D};
|
use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D};
|
||||||
use pathfinder_color::ColorF;
|
use pathfinder_color::ColorF;
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::vector::{vec2f, vec2i};
|
use pathfinder_geometry::vector::{vec2f, vec2i};
|
||||||
|
@ -52,8 +52,8 @@ fn main() {
|
||||||
RendererOptions { background_color: Some(ColorF::white()) });
|
RendererOptions { background_color: Some(ColorF::white()) });
|
||||||
|
|
||||||
// Make a canvas. We're going to draw a house.
|
// Make a canvas. We're going to draw a house.
|
||||||
let mut canvas = CanvasRenderingContext2D::new(CanvasFontContext::from_system_source(),
|
let font_context = CanvasFontContext::from_system_source();
|
||||||
window_size.to_f32());
|
let mut canvas = Canvas::new(window_size.to_f32()).get_context_2d(font_context);
|
||||||
|
|
||||||
// Set line width.
|
// Set line width.
|
||||||
canvas.set_line_width(10.0);
|
canvas.set_line_width(10.0);
|
||||||
|
@ -73,7 +73,7 @@ fn main() {
|
||||||
canvas.stroke_path(path);
|
canvas.stroke_path(path);
|
||||||
|
|
||||||
// Render the canvas to screen.
|
// Render the canvas to screen.
|
||||||
let scene = SceneProxy::from_scene(canvas.into_scene(), RayonExecutor);
|
let scene = SceneProxy::from_scene(canvas.into_canvas().into_scene(), RayonExecutor);
|
||||||
scene.build_and_render(&mut renderer, BuildOptions::default());
|
scene.build_and_render(&mut renderer, BuildOptions::default());
|
||||||
window.gl_swap_window();
|
window.gl_swap_window();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, Path2D};
|
use pathfinder_canvas::{Canvas, CanvasFontContext, CanvasRenderingContext2D, FillStyle, Path2D};
|
||||||
use pathfinder_color::{ColorF, ColorU};
|
use pathfinder_color::{ColorF, ColorU};
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2f, vec2i};
|
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2f, vec2i};
|
||||||
use pathfinder_gl::{GLDevice, GLVersion};
|
use pathfinder_gl::{GLDevice, GLVersion};
|
||||||
|
@ -127,8 +127,8 @@ impl MoireRenderer {
|
||||||
self.renderer.set_options(RendererOptions { background_color: Some(background_color) });
|
self.renderer.set_options(RendererOptions { background_color: Some(background_color) });
|
||||||
|
|
||||||
// Make a canvas.
|
// Make a canvas.
|
||||||
let mut canvas = CanvasRenderingContext2D::new(self.font_context.clone(),
|
let mut canvas =
|
||||||
self.drawable_size.to_f32());
|
Canvas::new(self.drawable_size.to_f32()).get_context_2d(self.font_context.clone());
|
||||||
canvas.set_line_width(CIRCLE_THICKNESS * self.device_pixel_ratio);
|
canvas.set_line_width(CIRCLE_THICKNESS * self.device_pixel_ratio);
|
||||||
canvas.set_stroke_style(FillStyle::Color(foreground_color.to_u8()));
|
canvas.set_stroke_style(FillStyle::Color(foreground_color.to_u8()));
|
||||||
canvas.set_global_alpha(0.75);
|
canvas.set_global_alpha(0.75);
|
||||||
|
@ -138,7 +138,7 @@ impl MoireRenderer {
|
||||||
self.draw_circles(&mut canvas, inner_center);
|
self.draw_circles(&mut canvas, inner_center);
|
||||||
|
|
||||||
// Build and render scene.
|
// Build and render scene.
|
||||||
self.scene.replace_scene(canvas.into_scene());
|
self.scene.replace_scene(canvas.into_canvas().into_scene());
|
||||||
self.scene.build_and_render(&mut self.renderer, BuildOptions::default());
|
self.scene.build_and_render(&mut self.renderer, BuildOptions::default());
|
||||||
|
|
||||||
self.frame += 1;
|
self.frame += 1;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use font_kit::handle::Handle;
|
use font_kit::handle::Handle;
|
||||||
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, TextAlign};
|
use pathfinder_canvas::{Canvas, CanvasFontContext, TextAlign};
|
||||||
use pathfinder_color::ColorF;
|
use pathfinder_color::ColorF;
|
||||||
use pathfinder_geometry::vector::{vec2f, vec2i};
|
use pathfinder_geometry::vector::{vec2f, vec2i};
|
||||||
use pathfinder_gl::{GLDevice, GLVersion};
|
use pathfinder_gl::{GLDevice, GLVersion};
|
||||||
|
@ -61,7 +61,7 @@ fn main() {
|
||||||
let font_context = CanvasFontContext::from_fonts(iter::once(font));
|
let font_context = CanvasFontContext::from_fonts(iter::once(font));
|
||||||
|
|
||||||
// Make a canvas.
|
// Make a canvas.
|
||||||
let mut canvas = CanvasRenderingContext2D::new(font_context, window_size.to_f32());
|
let mut canvas = Canvas::new(window_size.to_f32()).get_context_2d(font_context);
|
||||||
|
|
||||||
// Draw the text.
|
// Draw the text.
|
||||||
canvas.set_font("Overpass-Regular");
|
canvas.set_font("Overpass-Regular");
|
||||||
|
@ -71,7 +71,7 @@ fn main() {
|
||||||
canvas.stroke_text("Goodbye Pathfinder!", vec2f(608.0, 464.0));
|
canvas.stroke_text("Goodbye Pathfinder!", vec2f(608.0, 464.0));
|
||||||
|
|
||||||
// Render the canvas to screen.
|
// Render the canvas to screen.
|
||||||
let scene = SceneProxy::from_scene(canvas.into_scene(), RayonExecutor);
|
let scene = SceneProxy::from_scene(canvas.into_canvas().into_scene(), RayonExecutor);
|
||||||
scene.build_and_render(&mut renderer, BuildOptions::default());
|
scene.build_and_render(&mut renderer, BuildOptions::default());
|
||||||
window.gl_swap_window();
|
window.gl_swap_window();
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub enum Paint {
|
||||||
Pattern(Pattern),
|
Pattern(Pattern),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct PaintId(pub u16);
|
pub struct PaintId(pub u16);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
|
|
@ -22,6 +22,7 @@ use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::transform2d::Transform2F;
|
use pathfinder_geometry::transform2d::Transform2F;
|
||||||
use pathfinder_geometry::vector::{Vector2I, vec2f};
|
use pathfinder_geometry::vector::{Vector2I, vec2f};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
|
@ -85,6 +86,51 @@ impl Scene {
|
||||||
self.display_list.push(DisplayItem::DrawRenderTarget { render_target, effects });
|
self.display_list.push(DisplayItem::DrawRenderTarget { render_target, effects });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn append_scene(&mut self, scene: Scene) {
|
||||||
|
// Merge render targets.
|
||||||
|
let mut render_target_mapping = HashMap::new();
|
||||||
|
for (old_render_target_index, render_target) in scene.palette
|
||||||
|
.render_targets
|
||||||
|
.into_iter()
|
||||||
|
.enumerate() {
|
||||||
|
let old_render_target_id = RenderTargetId(old_render_target_index as u32);
|
||||||
|
let new_render_target_id = self.palette.push_render_target(render_target);
|
||||||
|
render_target_mapping.insert(old_render_target_id, new_render_target_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge paints.
|
||||||
|
let mut paint_mapping = HashMap::new();
|
||||||
|
for (old_paint_index, paint) in scene.palette.paints.iter().enumerate() {
|
||||||
|
let old_paint_id = PaintId(old_paint_index as u16);
|
||||||
|
let new_paint_id = self.palette.push_paint(&paint);
|
||||||
|
paint_mapping.insert(old_paint_id, new_paint_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge clip paths.
|
||||||
|
let mut clip_path_mapping = Vec::with_capacity(scene.clip_paths.len());
|
||||||
|
for clip_path in scene.clip_paths {
|
||||||
|
clip_path_mapping.push(self.clip_paths.len());
|
||||||
|
self.clip_paths.push(clip_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge draw paths.
|
||||||
|
let mut draw_path_mapping = Vec::with_capacity(scene.paths.len());
|
||||||
|
for draw_path in scene.paths {
|
||||||
|
draw_path_mapping.push(self.paths.len());
|
||||||
|
self.paths.push(DrawPath {
|
||||||
|
outline: draw_path.outline,
|
||||||
|
paint: paint_mapping[&draw_path.paint],
|
||||||
|
clip_path: draw_path.clip_path.map(|clip_path_id| {
|
||||||
|
ClipPathId(clip_path_mapping[clip_path_id.0 as usize] as u32)
|
||||||
|
}),
|
||||||
|
fill_rule: draw_path.fill_rule,
|
||||||
|
blend_mode: draw_path.blend_mode,
|
||||||
|
opacity: draw_path.opacity,
|
||||||
|
name: draw_path.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build_paint_info(&self, render_transform: Transform2F) -> PaintInfo {
|
pub fn build_paint_info(&self, render_transform: Transform2F) -> PaintInfo {
|
||||||
self.palette.build_paint_info(render_transform)
|
self.palette.build_paint_info(render_transform)
|
||||||
|
|
Loading…
Reference in New Issue