Add a transform field to `DrawPath`.

This is currently applied to the outline and should eventually be applied to
paints as well.
This commit is contained in:
Patrick Walton 2020-03-03 11:17:09 -08:00
parent afd1585d5d
commit 12574101e5
4 changed files with 25 additions and 17 deletions

View File

@ -96,15 +96,13 @@ impl CanvasRenderingContext2D {
let mut path = Path2D::new(); let mut path = Path2D::new();
path.rect(rect); path.rect(rect);
let mut outline = path.into_outline();
outline.transform(&self.current_state.transform);
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.scene.push_paint(&paint);
let mut path = DrawPath::new(outline, paint_id); let mut path = DrawPath::new(path.into_outline(), paint_id);
path.set_blend_mode(BlendMode::Clear); path.set_blend_mode(BlendMode::Clear);
path.set_transform(self.current_state.transform);
self.scene.push_path(path); self.scene.push_path(path);
} }
@ -198,13 +196,9 @@ 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 mut outline = path.into_outline();
outline.transform(&self.current_state.transform);
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.scene.push_paint(&paint);
self.push_path(path.into_outline(), paint_id, fill_rule);
self.push_path(outline, paint_id, fill_rule);
} }
#[inline] #[inline]
@ -236,7 +230,6 @@ impl CanvasRenderingContext2D {
stroke_to_fill.offset(); stroke_to_fill.offset();
outline = stroke_to_fill.into_outline(); outline = stroke_to_fill.into_outline();
outline.transform(&self.current_state.transform);
self.push_path(outline, paint_id, FillRule::Winding); self.push_path(outline, paint_id, FillRule::Winding);
} }
@ -252,6 +245,7 @@ impl CanvasRenderingContext2D {
} }
fn push_path(&mut self, outline: Outline, paint_id: PaintId, fill_rule: FillRule) { fn push_path(&mut self, outline: Outline, paint_id: PaintId, fill_rule: FillRule) {
let transform = self.current_state.transform;
let clip_path = self.current_state.clip_path; let clip_path = self.current_state.clip_path;
let blend_mode = self.current_state.global_composite_operation.to_blend_mode(); let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
let composite_op = self.current_state.global_composite_operation.to_composite_op(); let composite_op = self.current_state.global_composite_operation.to_composite_op();
@ -264,13 +258,13 @@ impl CanvasRenderingContext2D {
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 path = DrawPath::new(outline.clone(), paint_id);
outline.transform(&Transform2F::from_translation(self.current_state.shadow_offset));
let mut path = DrawPath::new(outline, paint_id);
path.set_clip_path(clip_path); path.set_clip_path(clip_path);
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);
path.set_transform(Transform2F::from_translation(self.current_state.shadow_offset) *
transform);
self.scene.push_path(path); self.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);
@ -284,6 +278,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);
path.set_transform(transform);
self.scene.push_path(path); self.scene.push_path(path);
self.composite_render_target_if_needed(composite_op, render_target_id); self.composite_render_target_if_needed(composite_op, render_target_id);

View File

@ -170,7 +170,9 @@ impl<'a> SceneBuilder<'a> {
built_clip_paths: &[BuiltPath], built_clip_paths: &[BuiltPath],
) -> BuiltDrawPath { ) -> BuiltDrawPath {
let path_object = &scene.paths[path_index]; let path_object = &scene.paths[path_index];
let outline = scene.apply_render_options(path_object.outline(), built_options); let mut outline = scene.apply_render_options(path_object.outline(), built_options);
outline.transform(&path_object.transform());
let paint_id = path_object.paint(); let paint_id = path_object.paint();
let paint_metadata = &paint_metadata[paint_id.0 as usize]; let paint_metadata = &paint_metadata[paint_id.0 as usize];
let built_clip_path = let built_clip_path =

View File

@ -223,6 +223,7 @@ impl<'a> Iterator for PathIter<'a> {
pub struct DrawPath { pub struct DrawPath {
outline: Outline, outline: Outline,
paint: PaintId, paint: PaintId,
transform: Transform2F,
clip_path: Option<ClipPathId>, clip_path: Option<ClipPathId>,
fill_rule: FillRule, fill_rule: FillRule,
blend_mode: BlendMode, blend_mode: BlendMode,
@ -272,6 +273,7 @@ impl DrawPath {
DrawPath { DrawPath {
outline, outline,
paint, paint,
transform: Transform2F::default(),
clip_path: None, clip_path: None,
fill_rule: FillRule::Winding, fill_rule: FillRule::Winding,
blend_mode: BlendMode::SrcOver, blend_mode: BlendMode::SrcOver,
@ -285,6 +287,16 @@ impl DrawPath {
&self.outline &self.outline
} }
#[inline]
pub(crate) fn transform(&self) -> Transform2F {
self.transform
}
#[inline]
pub fn set_transform(&mut self, new_transform: Transform2F) {
self.transform = new_transform
}
#[inline] #[inline]
pub(crate) fn clip_path(&self) -> Option<ClipPathId> { pub(crate) fn clip_path(&self) -> Option<ClipPathId> {
self.clip_path self.clip_path

View File

@ -133,7 +133,6 @@ impl BuiltSVG {
path.visibility == Visibility::Visible => { path.visibility == Visibility::Visible => {
if let Some(ref fill) = path.fill { if let Some(ref fill) = path.fill {
let path = UsvgPathToSegments::new(path.data.iter().cloned()); let path = UsvgPathToSegments::new(path.data.iter().cloned());
let path = Transform2FPathIter::new(path, &state.transform);
let outline = Outline::from_segments(path); let outline = Outline::from_segments(path);
let name = format!("Fill({})", node.id()); let name = format!("Fill({})", node.id());
@ -158,8 +157,7 @@ impl BuiltSVG {
let mut stroke_to_fill = OutlineStrokeToFill::new(&outline, stroke_style); let mut stroke_to_fill = OutlineStrokeToFill::new(&outline, stroke_style);
stroke_to_fill.offset(); stroke_to_fill.offset();
let mut outline = stroke_to_fill.into_outline(); let outline = stroke_to_fill.into_outline();
outline.transform(&state.transform);
let name = format!("Stroke({})", node.id()); let name = format!("Stroke({})", node.id());
self.push_draw_path(outline, self.push_draw_path(outline,
@ -238,6 +236,7 @@ impl BuiltSVG {
path.set_fill_rule(fill_rule); path.set_fill_rule(fill_rule);
path.set_name(name); path.set_name(name);
path.set_opacity((opacity.value() * 255.0) as u8); path.set_opacity((opacity.value() * 255.0) as u8);
path.set_transform(state.transform);
self.scene.push_path(path); self.scene.push_path(path);
} }
} }