Add front-end support for clip paths. They don't do anything yet.

This commit is contained in:
Patrick Walton 2020-02-15 13:21:12 -08:00
parent fefa3c3cd3
commit 496b55ee4e
5 changed files with 60 additions and 8 deletions

View File

@ -22,7 +22,7 @@ use pathfinder_geometry::vector::Vector2F;
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::transform2d::Transform2F; use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_renderer::paint::{Paint, PaintId}; use pathfinder_renderer::paint::{Paint, PaintId};
use pathfinder_renderer::scene::{DrawPath, Scene}; use pathfinder_renderer::scene::{ClipPath, ClipPathId, DrawPath, Scene};
use std::borrow::Cow; use std::borrow::Cow;
use std::default::Default; use std::default::Default;
use std::f32::consts::PI; use std::f32::consts::PI;
@ -199,17 +199,27 @@ impl CanvasRenderingContext2D {
self.push_path(outline, paint_id); self.push_path(outline, paint_id);
} }
pub fn clip_path(&mut self, path: Path2D) {
let mut outline = path.into_outline();
outline.transform(&self.current_state.transform);
let clip_path_id = self.scene.push_clip_path(ClipPath::new(outline, String::new()));
self.current_state.clip_path = Some(clip_path_id);
}
fn push_path(&mut self, outline: Outline, paint_id: PaintId) { fn push_path(&mut self, outline: Outline, paint_id: PaintId) {
let clip_path = self.current_state.clip_path;
if !self.current_state.shadow_paint.is_fully_transparent() { if !self.current_state.shadow_paint.is_fully_transparent() {
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.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));
self.scene.push_path(DrawPath::new(outline, paint_id, String::new())) self.scene.push_path(DrawPath::new(outline, paint_id, clip_path, String::new()))
} }
self.scene.push_path(DrawPath::new(outline, paint_id, String::new())) self.scene.push_path(DrawPath::new(outline, paint_id, clip_path, String::new()))
} }
// Transformations // Transformations
@ -273,6 +283,7 @@ struct State {
shadow_offset: Vector2F, shadow_offset: Vector2F,
text_align: TextAlign, text_align: TextAlign,
global_alpha: f32, global_alpha: f32,
clip_path: Option<ClipPathId>,
} }
impl State { impl State {
@ -293,6 +304,7 @@ impl State {
shadow_offset: Vector2F::default(), shadow_offset: Vector2F::default(),
text_align: TextAlign::Left, text_align: TextAlign::Left,
global_alpha: 1.0, global_alpha: 1.0,
clip_path: None,
} }
} }

View File

@ -24,6 +24,7 @@ use pathfinder_content::outline::Outline;
#[derive(Clone)] #[derive(Clone)]
pub struct Scene { pub struct Scene {
pub(crate) paths: Vec<DrawPath>, pub(crate) paths: Vec<DrawPath>,
pub(crate) clip_paths: Vec<ClipPath>,
palette: Palette, palette: Palette,
bounds: RectF, bounds: RectF,
view_box: RectF, view_box: RectF,
@ -34,6 +35,7 @@ impl Scene {
pub fn new() -> Scene { pub fn new() -> Scene {
Scene { Scene {
paths: vec![], paths: vec![],
clip_paths: vec![],
palette: Palette::new(), palette: Palette::new(),
bounds: RectF::default(), bounds: RectF::default(),
view_box: RectF::default(), view_box: RectF::default(),
@ -45,6 +47,13 @@ impl Scene {
self.paths.push(path); self.paths.push(path);
} }
pub fn push_clip_path(&mut self, clip_path: ClipPath) -> ClipPathId {
self.bounds = self.bounds.union_rect(clip_path.outline.bounds());
let clip_path_id = ClipPathId(self.clip_paths.len() as u32);
self.clip_paths.push(clip_path);
clip_path_id
}
#[inline] #[inline]
pub fn build_paint_info(&self) -> PaintInfo { pub fn build_paint_info(&self) -> PaintInfo {
self.palette.build_paint_info(self.view_box.size().to_i32()) self.palette.build_paint_info(self.view_box.size().to_i32())
@ -204,13 +213,24 @@ impl<'a> Iterator for PathIter<'a> {
pub struct DrawPath { pub struct DrawPath {
outline: Outline, outline: Outline,
paint: PaintId, paint: PaintId,
clip_path: Option<ClipPathId>,
name: String, name: String,
} }
#[derive(Clone, Debug)]
pub struct ClipPath {
outline: Outline,
name: String,
}
#[derive(Clone, Copy, Debug)]
pub struct ClipPathId(pub u32);
impl DrawPath { impl DrawPath {
#[inline] #[inline]
pub fn new(outline: Outline, paint: PaintId, name: String) -> DrawPath { pub fn new(outline: Outline, paint: PaintId, clip_path: Option<ClipPathId>, name: String)
DrawPath { outline, paint, name } -> DrawPath {
DrawPath { outline, paint, clip_path, name }
} }
#[inline] #[inline]
@ -218,8 +238,25 @@ impl DrawPath {
&self.outline &self.outline
} }
#[inline]
pub(crate) fn clip_path(&self) -> Option<ClipPathId> {
self.clip_path
}
#[inline] #[inline]
pub(crate) fn paint(&self) -> PaintId { pub(crate) fn paint(&self) -> PaintId {
self.paint self.paint
} }
} }
impl ClipPath {
#[inline]
pub fn new(outline: Outline, name: String) -> ClipPath {
ClipPath { outline, name }
}
#[inline]
pub fn outline(&self) -> &Outline {
&self.outline
}
}

View File

@ -122,8 +122,9 @@ impl BuiltSVG {
let path = Transform2FPathIter::new(path, &transform); let path = Transform2FPathIter::new(path, &transform);
let outline = Outline::from_segments(path); let outline = Outline::from_segments(path);
// TODO(pcwalton): Clip paths.
let name = format!("Fill({})", node.id()); let name = format!("Fill({})", node.id());
self.scene.push_path(DrawPath::new(outline, style, name)); self.scene.push_path(DrawPath::new(outline, style, None, name));
} }
if let Some(ref stroke) = path.stroke { if let Some(ref stroke) = path.stroke {
@ -148,8 +149,9 @@ impl BuiltSVG {
let mut outline = stroke_to_fill.into_outline(); let mut outline = stroke_to_fill.into_outline();
outline.transform(&transform); outline.transform(&transform);
// TODO(pcwalton): Clip paths.
let name = format!("Stroke({})", node.id()); let name = format!("Stroke({})", node.id());
self.scene.push_path(DrawPath::new(outline, style, name)); self.scene.push_path(DrawPath::new(outline, style, None, name));
} }
} }
NodeKind::Path(..) => {} NodeKind::Path(..) => {}

View File

@ -197,6 +197,7 @@ pub fn draw_paths_into_scene(library: &SymbolLibrary, scene: &mut Scene) {
scene.push_path(DrawPath::new( scene.push_path(DrawPath::new(
path, path,
paint_id, paint_id,
None,
String::new() String::new()
)); ));
} }

View File

@ -76,7 +76,7 @@ impl SceneExt for Scene {
outline = stroke_to_fill.into_outline(); outline = stroke_to_fill.into_outline();
} }
self.push_path(DrawPath::new(outline, paint_id, String::new())); self.push_path(DrawPath::new(outline, paint_id, None, String::new()));
Ok(()) Ok(())
} }