From 2c984de1ead9eca06940ff126d73c33abff09bc7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 12 Jul 2019 11:34:48 -0700 Subject: [PATCH] Add convenience translation, rotation, and scaling methods to `Transform2D` --- canvas/src/lib.rs | 10 +++------- content/src/stroke.rs | 6 ++---- demo/common/src/camera.rs | 5 ++--- demo/common/src/lib.rs | 26 +++++++++----------------- examples/canvas_minimal/src/main.rs | 3 +-- geometry/src/transform2d.rs | 19 +++++++++++-------- text/src/lib.rs | 4 +--- 7 files changed, 29 insertions(+), 44 deletions(-) diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 0ccd3317..e5428ef6 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -441,8 +441,7 @@ impl Path2D { start_angle: f32, end_angle: f32, direction: ArcDirection) { - let mut transform = Transform2F::from_scale(Vector2F::splat(radius)); - transform = Transform2F::from_translation(center) * transform; + let transform = Transform2F::from_scale(Vector2F::splat(radius)).translate(center); self.current_contour.push_arc(&transform, start_angle, end_angle, direction); } @@ -456,8 +455,7 @@ impl Path2D { let bisector = vu0 + vu1; let center = ctrl + bisector.scale(hypot / bisector.length()); - let mut transform = Transform2F::from_scale(Vector2F::splat(radius)); - transform = Transform2F::from_translation(center) * transform; + let transform = Transform2F::from_scale(Vector2F::splat(radius)).translate(center); let chord = LineSegment2F::new(vu0.yx().scale_xy(Vector2F::new(-1.0, 1.0)), vu1.yx().scale_xy(Vector2F::new(1.0, -1.0))); @@ -483,9 +481,7 @@ impl Path2D { end_angle: f32) { self.flush_current_contour(); - let mut transform = Transform2F::from_translation(center); - transform *= Transform2F::from_rotation(rotation); - transform *= Transform2F::from_scale(axes); + let transform = Transform2F::from_scale(axes).rotate(rotation).translate(center); self.current_contour.push_arc(&transform, start_angle, end_angle, ArcDirection::CW); if end_angle - start_angle >= 2.0 * PI { diff --git a/content/src/stroke.rs b/content/src/stroke.rs index 4e8a26ac..cd9e6034 100644 --- a/content/src/stroke.rs +++ b/content/src/stroke.rs @@ -138,9 +138,8 @@ impl<'a> OutlineStrokeToFill<'a> { LineCap::Round => { let scale = Vector2F::splat(width * 0.5); let offset = gradient.yx().scale_xy(Vector2F::new(-1.0, 1.0)); - let mut transform = Transform2F::from_scale(scale); let translation = p1 + offset.scale(width * 0.5); - transform = Transform2F::from_translation(translation) * transform; + let transform = Transform2F::from_scale(scale).translate(translation); let chord = LineSegment2F::new(-offset, offset); contour.push_arc_from_unit_chord(&transform, chord, ArcDirection::CW); } @@ -374,8 +373,7 @@ impl Contour { } LineJoin::Round => { let scale = Vector2F::splat(distance.abs()); - let mut transform = Transform2F::from_translation(join_point); - transform *= Transform2F::from_scale(scale); + let transform = Transform2F::from_scale(scale).translate(join_point); let chord_from = (prev_tangent.to() - join_point).normalize(); let chord_to = (next_tangent.to() - join_point).normalize(); let chord = LineSegment2F::new(chord_from, chord_to); diff --git a/demo/common/src/camera.rs b/demo/common/src/camera.rs index d108c21b..28975750 100644 --- a/demo/common/src/camera.rs +++ b/demo/common/src/camera.rs @@ -14,7 +14,7 @@ // proper. use crate::window::{OcularTransform, View}; -use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F}; +use pathfinder_geometry::vector::{Vector2I, Vector4F}; use pathfinder_geometry::rect::RectF; use pathfinder_geometry::transform2d::Transform2F; use pathfinder_geometry::transform3d::{Perspective, Transform4F}; @@ -56,8 +56,7 @@ impl Camera { let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 * scale_factor_for_view_box(view_box); let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5); - Camera::TwoD(Transform2F::from_translation(origin) * - Transform2F::from_uniform_scale(scale)) + Camera::TwoD(Transform2F::from_uniform_scale(scale).translate(origin)) } fn new_3d(mode: Mode, view_box: RectF, viewport_size: Vector2I) -> Camera { diff --git a/demo/common/src/lib.rs b/demo/common/src/lib.rs index 3b0626ae..832597b4 100644 --- a/demo/common/src/lib.rs +++ b/demo/common/src/lib.rs @@ -327,10 +327,10 @@ impl DemoApp where W: Window { if let Camera::TwoD(ref mut transform) = self.camera { let backing_scale_factor = self.window_size.backing_scale_factor; let position = position.to_f32().scale(backing_scale_factor); - *transform = Transform2F::from_translation(-position) * *transform; let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D; - *transform = Transform2F::from_uniform_scale(scale_delta) * *transform; - *transform = Transform2F::from_translation(position) * *transform; + *transform = transform.translate(-position) + .uniform_scale(scale_delta) + .translate(position); } } Event::Look { pitch, yaw } => { @@ -587,8 +587,7 @@ impl DemoApp where W: Window { } UIEvent::MouseDragged(position) => { if let Camera::TwoD(ref mut transform) = self.camera { - *transform = Transform2F::from_translation(position.relative.to_f32()) * - *transform; + *transform = transform.translate(position.relative.to_f32()); } } _ => {} @@ -608,10 +607,7 @@ impl DemoApp where W: Window { if let Camera::TwoD(ref mut transform) = self.camera { let scale = Vector2F::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D); let center = center_of_window(&self.window_size); - *transform = Transform2F::from_translation(center) * - Transform2F::from_scale(scale) * - Transform2F::from_translation(-center) * - *transform; + *transform = transform.translate(-center).scale(scale).translate(center); self.dirty = true; } } @@ -619,10 +615,7 @@ impl DemoApp where W: Window { if let Camera::TwoD(ref mut transform) = self.camera { let scale = Vector2F::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D); let center = center_of_window(&self.window_size); - *transform = Transform2F::from_translation(center) * - Transform2F::from_scale(scale) * - Transform2F::from_translation(-center) * - *transform; + *transform = transform.translate(-center).scale(scale).translate(center); self.dirty = true; } } @@ -636,10 +629,9 @@ impl DemoApp where W: Window { if let Camera::TwoD(ref mut transform) = self.camera { let old_rotation = transform.rotation(); let center = center_of_window(&self.window_size); - *transform = Transform2F::from_translation(-center) * - Transform2F::from_rotation(*theta - old_rotation) * - Transform2F::from_translation(center) * - *transform; + *transform = transform.translate(-center) + .rotate(*theta - old_rotation) + .translate(center); } } } diff --git a/examples/canvas_minimal/src/main.rs b/examples/canvas_minimal/src/main.rs index 26b7e655..27d1469c 100644 --- a/examples/canvas_minimal/src/main.rs +++ b/examples/canvas_minimal/src/main.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, LineJoin, Path2D}; +use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D}; use pathfinder_content::color::ColorF; use pathfinder_geometry::rect::RectF; use pathfinder_geometry::vector::{Vector2F, Vector2I}; @@ -57,7 +57,6 @@ fn main() { // Set line width. canvas.set_line_width(10.0); - canvas.set_line_join(LineJoin::Round); // Draw walls. canvas.stroke_rect(RectF::new(Vector2F::new(75.0, 140.0), Vector2F::new(150.0, 110.0))); diff --git a/geometry/src/transform2d.rs b/geometry/src/transform2d.rs index 4a68e619..779cdeb0 100644 --- a/geometry/src/transform2d.rs +++ b/geometry/src/transform2d.rs @@ -246,22 +246,25 @@ impl Transform2F { self.matrix.m22() } - /* #[inline] - pub fn post_translate(&self, vector: Vector2F) -> Transform2F { - self.post_mul(&Transform2F::from_translation(vector)) + pub fn translate(&self, vector: Vector2F) -> Transform2F { + Transform2F::from_translation(vector) * *self } #[inline] - pub fn post_rotate(&self, theta: f32) -> Transform2F { - self.post_mul(&Transform2F::from_rotation(theta)) + pub fn rotate(&self, theta: f32) -> Transform2F { + Transform2F::from_rotation(theta) * *self } #[inline] - pub fn post_scale(&self, scale: Vector2F) -> Transform2F { - self.post_mul(&Transform2F::from_scale(scale)) + pub fn scale(&self, scale: Vector2F) -> Transform2F { + Transform2F::from_scale(scale) * *self + } + + #[inline] + pub fn uniform_scale(&self, scale: f32) -> Transform2F { + self.scale(Vector2F::splat(scale)) } - */ /// Returns the translation part of this matrix. /// diff --git a/text/src/lib.rs b/text/src/lib.rs index 4433b07c..8b2d780c 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -93,9 +93,7 @@ impl SceneExt for Scene { // FIXME(pcwalton): Cache this! let scale = style.size / (font.metrics().units_per_em as f32); let scale = Vector2F::new(scale, -scale); - let transform = *transform * - Transform2F::from_translation(offset) * - Transform2F::from_scale(scale); + let transform = *transform * Transform2F::from_scale(scale).translate(offset); self.push_glyph(font, glyph.glyph_id, &transform,