Fix incorrect definition of 2D transform multiplication
This commit is contained in:
parent
96758dfc17
commit
1eb28a5539
|
@ -115,8 +115,7 @@ impl CanvasRenderingContext2D {
|
||||||
TextAlign::Center => position.set_x(position.x() - layout.width() * 0.5),
|
TextAlign::Center => position.set_x(position.x() - layout.width() * 0.5),
|
||||||
}
|
}
|
||||||
|
|
||||||
let transform = Transform2F::from_translation(position).post_mul(&self.current_state
|
let transform = self.current_state.transform * Transform2F::from_translation(position);
|
||||||
.transform);
|
|
||||||
|
|
||||||
// TODO(pcwalton): Report errors.
|
// TODO(pcwalton): Report errors.
|
||||||
drop(self.scene.push_layout(&layout,
|
drop(self.scene.push_layout(&layout,
|
||||||
|
@ -443,7 +442,7 @@ impl Path2D {
|
||||||
end_angle: f32,
|
end_angle: f32,
|
||||||
direction: ArcDirection) {
|
direction: ArcDirection) {
|
||||||
let mut transform = Transform2F::from_scale(Vector2F::splat(radius));
|
let mut transform = Transform2F::from_scale(Vector2F::splat(radius));
|
||||||
transform = transform.post_mul(&Transform2F::from_translation(center));
|
transform = Transform2F::from_translation(center) * transform;
|
||||||
self.current_contour.push_arc(&transform, start_angle, end_angle, direction);
|
self.current_contour.push_arc(&transform, start_angle, end_angle, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +457,7 @@ impl Path2D {
|
||||||
let center = ctrl + bisector.scale(hypot / bisector.length());
|
let center = ctrl + bisector.scale(hypot / bisector.length());
|
||||||
|
|
||||||
let mut transform = Transform2F::from_scale(Vector2F::splat(radius));
|
let mut transform = Transform2F::from_scale(Vector2F::splat(radius));
|
||||||
transform = transform.post_mul(&Transform2F::from_translation(center));
|
transform = Transform2F::from_translation(center) * transform;
|
||||||
|
|
||||||
let chord = LineSegment2F::new(vu0.yx().scale_xy(Vector2F::new(-1.0, 1.0)),
|
let chord = LineSegment2F::new(vu0.yx().scale_xy(Vector2F::new(-1.0, 1.0)),
|
||||||
vu1.yx().scale_xy(Vector2F::new(1.0, -1.0)));
|
vu1.yx().scale_xy(Vector2F::new(1.0, -1.0)));
|
||||||
|
@ -484,9 +483,9 @@ impl Path2D {
|
||||||
end_angle: f32) {
|
end_angle: f32) {
|
||||||
self.flush_current_contour();
|
self.flush_current_contour();
|
||||||
|
|
||||||
let mut transform = Transform2F::from_rotation(rotation);
|
let mut transform = Transform2F::from_translation(center);
|
||||||
transform = transform.post_mul(&Transform2F::from_scale(axes));
|
transform *= Transform2F::from_rotation(rotation);
|
||||||
transform = transform.post_mul(&Transform2F::from_translation(center));
|
transform *= Transform2F::from_scale(axes);
|
||||||
self.current_contour.push_arc(&transform, start_angle, end_angle, ArcDirection::CW);
|
self.current_contour.push_arc(&transform, start_angle, end_angle, ArcDirection::CW);
|
||||||
|
|
||||||
if end_angle - start_angle >= 2.0 * PI {
|
if end_angle - start_angle >= 2.0 * PI {
|
||||||
|
|
|
@ -393,8 +393,7 @@ impl Contour {
|
||||||
|
|
||||||
let half_sweep_vector = sweep_vector.halve_angle();
|
let half_sweep_vector = sweep_vector.halve_angle();
|
||||||
let rotation = Transform2F::from_rotation_vector(half_sweep_vector.rotate_by(vector));
|
let rotation = Transform2F::from_rotation_vector(half_sweep_vector.rotate_by(vector));
|
||||||
segment = segment.transform(&direction_transform.post_mul(&rotation)
|
segment = segment.transform(&(*transform * rotation * direction_transform));
|
||||||
.post_mul(&transform));
|
|
||||||
|
|
||||||
let mut push_segment_flags = PushSegmentFlags::UPDATE_BOUNDS;
|
let mut push_segment_flags = PushSegmentFlags::UPDATE_BOUNDS;
|
||||||
if first_segment {
|
if first_segment {
|
||||||
|
@ -419,13 +418,13 @@ impl Contour {
|
||||||
self.push_segment(&segment.transform(transform),
|
self.push_segment(&segment.transform(transform),
|
||||||
PushSegmentFlags::UPDATE_BOUNDS | PushSegmentFlags::INCLUDE_FROM_POINT);
|
PushSegmentFlags::UPDATE_BOUNDS | PushSegmentFlags::INCLUDE_FROM_POINT);
|
||||||
rotation = Transform2F::from_rotation_vector(UnitVector(Vector2F::new( 0.0, 1.0)));
|
rotation = Transform2F::from_rotation_vector(UnitVector(Vector2F::new( 0.0, 1.0)));
|
||||||
self.push_segment(&segment.transform(&rotation.post_mul(&transform)),
|
self.push_segment(&segment.transform(&(*transform * rotation)),
|
||||||
PushSegmentFlags::UPDATE_BOUNDS);
|
PushSegmentFlags::UPDATE_BOUNDS);
|
||||||
rotation = Transform2F::from_rotation_vector(UnitVector(Vector2F::new(-1.0, 0.0)));
|
rotation = Transform2F::from_rotation_vector(UnitVector(Vector2F::new(-1.0, 0.0)));
|
||||||
self.push_segment(&segment.transform(&rotation.post_mul(&transform)),
|
self.push_segment(&segment.transform(&(*transform * rotation)),
|
||||||
PushSegmentFlags::UPDATE_BOUNDS);
|
PushSegmentFlags::UPDATE_BOUNDS);
|
||||||
rotation = Transform2F::from_rotation_vector(UnitVector(Vector2F::new( 0.0, -1.0)));
|
rotation = Transform2F::from_rotation_vector(UnitVector(Vector2F::new( 0.0, -1.0)));
|
||||||
self.push_segment(&segment.transform(&rotation.post_mul(&transform)),
|
self.push_segment(&segment.transform(&(*transform * rotation)),
|
||||||
PushSegmentFlags::UPDATE_BOUNDS);
|
PushSegmentFlags::UPDATE_BOUNDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ impl<'a> OutlineStrokeToFill<'a> {
|
||||||
let offset = gradient.yx().scale_xy(Vector2F::new(-1.0, 1.0));
|
let offset = gradient.yx().scale_xy(Vector2F::new(-1.0, 1.0));
|
||||||
let mut transform = Transform2F::from_scale(scale);
|
let mut transform = Transform2F::from_scale(scale);
|
||||||
let translation = p1 + offset.scale(width * 0.5);
|
let translation = p1 + offset.scale(width * 0.5);
|
||||||
transform = transform.post_mul(&Transform2F::from_translation(translation));
|
transform = Transform2F::from_translation(translation) * transform;
|
||||||
let chord = LineSegment2F::new(-offset, offset);
|
let chord = LineSegment2F::new(-offset, offset);
|
||||||
contour.push_arc_from_unit_chord(&transform, chord, ArcDirection::CW);
|
contour.push_arc_from_unit_chord(&transform, chord, ArcDirection::CW);
|
||||||
}
|
}
|
||||||
|
@ -374,8 +374,8 @@ impl Contour {
|
||||||
}
|
}
|
||||||
LineJoin::Round => {
|
LineJoin::Round => {
|
||||||
let scale = Vector2F::splat(distance.abs());
|
let scale = Vector2F::splat(distance.abs());
|
||||||
let mut transform = Transform2F::from_scale(scale);
|
let mut transform = Transform2F::from_translation(join_point);
|
||||||
transform = transform.post_mul(&Transform2F::from_translation(join_point));
|
transform *= Transform2F::from_scale(scale);
|
||||||
let chord_from = (prev_tangent.to() - join_point).normalize();
|
let chord_from = (prev_tangent.to() - join_point).normalize();
|
||||||
let chord_to = (next_tangent.to() - join_point).normalize();
|
let chord_to = (next_tangent.to() - join_point).normalize();
|
||||||
let chord = LineSegment2F::new(chord_from, chord_to);
|
let chord = LineSegment2F::new(chord_from, chord_to);
|
||||||
|
|
|
@ -56,7 +56,8 @@ impl Camera {
|
||||||
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32
|
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32
|
||||||
* scale_factor_for_view_box(view_box);
|
* scale_factor_for_view_box(view_box);
|
||||||
let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5);
|
let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5);
|
||||||
Camera::TwoD(Transform2F::from_scale(Vector2F::splat(scale)).post_translate(origin))
|
Camera::TwoD(Transform2F::from_translation(origin) *
|
||||||
|
Transform2F::from_uniform_scale(scale))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_3d(mode: Mode, view_box: RectF, viewport_size: Vector2I) -> Camera {
|
fn new_3d(mode: Mode, view_box: RectF, viewport_size: Vector2I) -> Camera {
|
||||||
|
|
|
@ -327,10 +327,10 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||||
let backing_scale_factor = self.window_size.backing_scale_factor;
|
let backing_scale_factor = self.window_size.backing_scale_factor;
|
||||||
let position = position.to_f32().scale(backing_scale_factor);
|
let position = position.to_f32().scale(backing_scale_factor);
|
||||||
*transform = transform.post_translate(-position);
|
*transform = Transform2F::from_translation(-position) * *transform;
|
||||||
let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D;
|
let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D;
|
||||||
*transform = transform.post_scale(Vector2F::splat(scale_delta));
|
*transform = Transform2F::from_uniform_scale(scale_delta) * *transform;
|
||||||
*transform = transform.post_translate(position);
|
*transform = Transform2F::from_translation(position) * *transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Look { pitch, yaw } => {
|
Event::Look { pitch, yaw } => {
|
||||||
|
@ -587,7 +587,8 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
}
|
}
|
||||||
UIEvent::MouseDragged(position) => {
|
UIEvent::MouseDragged(position) => {
|
||||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||||
*transform = transform.post_translate(position.relative.to_f32());
|
*transform = Transform2F::from_translation(position.relative.to_f32()) *
|
||||||
|
*transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -607,10 +608,10 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||||
let scale = Vector2F::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D);
|
let scale = Vector2F::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D);
|
||||||
let center = center_of_window(&self.window_size);
|
let center = center_of_window(&self.window_size);
|
||||||
*transform = transform
|
*transform = Transform2F::from_translation(center) *
|
||||||
.post_translate(-center)
|
Transform2F::from_scale(scale) *
|
||||||
.post_scale(scale)
|
Transform2F::from_translation(-center) *
|
||||||
.post_translate(center);
|
*transform;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,10 +619,10 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||||
let scale = Vector2F::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D);
|
let scale = Vector2F::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D);
|
||||||
let center = center_of_window(&self.window_size);
|
let center = center_of_window(&self.window_size);
|
||||||
*transform = transform
|
*transform = Transform2F::from_translation(center) *
|
||||||
.post_translate(-center)
|
Transform2F::from_scale(scale) *
|
||||||
.post_scale(scale)
|
Transform2F::from_translation(-center) *
|
||||||
.post_translate(center);
|
*transform;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,10 +636,10 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||||
let old_rotation = transform.rotation();
|
let old_rotation = transform.rotation();
|
||||||
let center = center_of_window(&self.window_size);
|
let center = center_of_window(&self.window_size);
|
||||||
*transform = transform
|
*transform = Transform2F::from_translation(-center) *
|
||||||
.post_translate(-center)
|
Transform2F::from_rotation(*theta - old_rotation) *
|
||||||
.post_rotate(*theta - old_rotation)
|
Transform2F::from_translation(center) *
|
||||||
.post_translate(center);
|
*transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
// 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::{CanvasFontContext, CanvasRenderingContext2D, LineJoin, Path2D};
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
|
||||||
use pathfinder_geometry::rect::RectF;
|
|
||||||
use pathfinder_content::color::ColorF;
|
use pathfinder_content::color::ColorF;
|
||||||
|
use pathfinder_geometry::rect::RectF;
|
||||||
|
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||||
use pathfinder_gl::{GLDevice, GLVersion};
|
use pathfinder_gl::{GLDevice, GLVersion};
|
||||||
use pathfinder_gpu::resources::FilesystemResourceLoader;
|
use pathfinder_gpu::resources::FilesystemResourceLoader;
|
||||||
use pathfinder_renderer::concurrent::rayon::RayonExecutor;
|
use pathfinder_renderer::concurrent::rayon::RayonExecutor;
|
||||||
|
@ -57,6 +57,7 @@ fn main() {
|
||||||
|
|
||||||
// Set line width.
|
// Set line width.
|
||||||
canvas.set_line_width(10.0);
|
canvas.set_line_width(10.0);
|
||||||
|
canvas.set_line_join(LineJoin::Round);
|
||||||
|
|
||||||
// Draw walls.
|
// Draw walls.
|
||||||
canvas.stroke_rect(RectF::new(Vector2F::new(75.0, 140.0), Vector2F::new(150.0, 110.0)));
|
canvas.stroke_rect(RectF::new(Vector2F::new(75.0, 140.0), Vector2F::new(150.0, 110.0)));
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::rect::RectF;
|
||||||
use crate::transform3d::Transform4F;
|
use crate::transform3d::Transform4F;
|
||||||
use crate::unit_vector::UnitVector;
|
use crate::unit_vector::UnitVector;
|
||||||
use pathfinder_simd::default::F32x4;
|
use pathfinder_simd::default::F32x4;
|
||||||
use std::ops::Sub;
|
use std::ops::{Mul, MulAssign, Sub};
|
||||||
|
|
||||||
/// A 2x2 matrix, optimized with SIMD, in column-major order.
|
/// A 2x2 matrix, optimized with SIMD, in column-major order.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
@ -46,18 +46,8 @@ impl Matrix2x2F {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn row_major(m11: f32, m12: f32, m21: f32, m22: f32) -> Matrix2x2F {
|
pub fn row_major(m00: f32, m01: f32, m10: f32, m11: f32) -> Matrix2x2F {
|
||||||
Matrix2x2F(F32x4::new(m11, m21, m12, m22))
|
Matrix2x2F(F32x4::new(m00, m10, m01, m11))
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn post_mul(&self, other: &Matrix2x2F) -> Matrix2x2F {
|
|
||||||
Matrix2x2F(self.0.xyxy() * other.0.xxzz() + self.0.zwzw() * other.0.yyww())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn pre_mul(&self, other: &Matrix2x2F) -> Matrix2x2F {
|
|
||||||
other.post_mul(self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -112,6 +102,14 @@ impl Sub<Matrix2x2F> for Matrix2x2F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Matrix2x2F> for Matrix2x2F {
|
||||||
|
type Output = Matrix2x2F;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, other: Matrix2x2F) -> Matrix2x2F {
|
||||||
|
Matrix2x2F(self.0.xyxy() * other.0.xxzz() + self.0.zwzw() * other.0.yyww())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An affine transform, optimized with SIMD.
|
/// An affine transform, optimized with SIMD.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Transform2F {
|
pub struct Transform2F {
|
||||||
|
@ -136,6 +134,11 @@ impl Transform2F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_uniform_scale(scale: f32) -> Transform2F {
|
||||||
|
Transform2F::from_scale(Vector2F::splat(scale))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_rotation(theta: f32) -> Transform2F {
|
pub fn from_rotation(theta: f32) -> Transform2F {
|
||||||
Transform2F {
|
Transform2F {
|
||||||
|
@ -165,7 +168,7 @@ impl Transform2F {
|
||||||
) -> Transform2F {
|
) -> Transform2F {
|
||||||
let rotation = Transform2F::from_rotation(theta);
|
let rotation = Transform2F::from_rotation(theta);
|
||||||
let translation = Transform2F::from_translation(translation);
|
let translation = Transform2F::from_translation(translation);
|
||||||
Transform2F::from_scale(scale).post_mul(&rotation).post_mul(&translation)
|
Transform2F::from_scale(scale) * rotation * translation
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -198,18 +201,6 @@ impl Transform2F {
|
||||||
RectF::from_points(min_point, max_point)
|
RectF::from_points(min_point, max_point)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn post_mul(&self, other: &Transform2F) -> Transform2F {
|
|
||||||
let matrix = self.matrix.post_mul(&other.matrix);
|
|
||||||
let vector = other.transform_point(self.vector);
|
|
||||||
Transform2F { matrix, vector }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn pre_mul(&self, other: &Transform2F) -> Transform2F {
|
|
||||||
other.post_mul(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(pcwalton): Optimize better with SIMD.
|
// TODO(pcwalton): Optimize better with SIMD.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_3d(&self) -> Transform4F {
|
pub fn to_3d(&self) -> Transform4F {
|
||||||
|
@ -255,6 +246,7 @@ impl Transform2F {
|
||||||
self.matrix.m22()
|
self.matrix.m22()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn post_translate(&self, vector: Vector2F) -> Transform2F {
|
pub fn post_translate(&self, vector: Vector2F) -> Transform2F {
|
||||||
self.post_mul(&Transform2F::from_translation(vector))
|
self.post_mul(&Transform2F::from_translation(vector))
|
||||||
|
@ -269,6 +261,7 @@ impl Transform2F {
|
||||||
pub fn post_scale(&self, scale: Vector2F) -> Transform2F {
|
pub fn post_scale(&self, scale: Vector2F) -> Transform2F {
|
||||||
self.post_mul(&Transform2F::from_scale(scale))
|
self.post_mul(&Transform2F::from_scale(scale))
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Returns the translation part of this matrix.
|
/// Returns the translation part of this matrix.
|
||||||
///
|
///
|
||||||
|
@ -294,3 +287,21 @@ impl Transform2F {
|
||||||
Vector2F(self.matrix.0.zw()).length()
|
Vector2F(self.matrix.0.zw()).length()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Transform2F> for Transform2F {
|
||||||
|
type Output = Transform2F;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, other: Transform2F) -> Transform2F {
|
||||||
|
Transform2F {
|
||||||
|
matrix: self.matrix * other.matrix,
|
||||||
|
vector: self.transform_point(other.vector),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MulAssign for Transform2F {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: Transform2F) {
|
||||||
|
*self = *self * other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -280,13 +280,13 @@ impl Transform4F {
|
||||||
|
|
||||||
// Compute temporary matrices.
|
// Compute temporary matrices.
|
||||||
let a_inv = a.inverse();
|
let a_inv = a.inverse();
|
||||||
let x = c.post_mul(&a_inv);
|
let x = c * a_inv;
|
||||||
let y = (d - x.post_mul(&b)).inverse();
|
let y = (d - x * b).inverse();
|
||||||
let z = a_inv.post_mul(&b);
|
let z = a_inv * b;
|
||||||
|
|
||||||
// Compute new submatrices.
|
// Compute new submatrices.
|
||||||
let (a_new, b_new) = (a_inv + z.post_mul(&y).post_mul(&x), (-z).post_mul(&y));
|
let (a_new, b_new) = (a_inv + z * y * x, -z * y);
|
||||||
let (c_new, d_new) = ((-y).post_mul(&x), y);
|
let (c_new, d_new) = (-y * x, y);
|
||||||
|
|
||||||
// Construct inverse.
|
// Construct inverse.
|
||||||
Transform4F::from_submatrices(a_new, b_new, c_new, d_new)
|
Transform4F::from_submatrices(a_new, b_new, c_new, d_new)
|
||||||
|
|
|
@ -119,8 +119,7 @@ impl Scene {
|
||||||
PreparedRenderTransform::Perspective { .. } => unreachable!(),
|
PreparedRenderTransform::Perspective { .. } => unreachable!(),
|
||||||
};
|
};
|
||||||
if options.subpixel_aa_enabled {
|
if options.subpixel_aa_enabled {
|
||||||
transform = transform
|
transform *= Transform2F::from_scale(Vector2F::new(3.0, 1.0))
|
||||||
.post_mul(&Transform2F::from_scale(Vector2F::new(3.0, 1.0)))
|
|
||||||
}
|
}
|
||||||
outline.transform(&transform);
|
outline.transform(&transform);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl BuiltSVG {
|
||||||
|
|
||||||
fn process_node(&mut self, node: &Node, transform: &Transform2F) {
|
fn process_node(&mut self, node: &Node, transform: &Transform2F) {
|
||||||
let node_transform = usvg_transform_to_transform_2d(&node.transform());
|
let node_transform = usvg_transform_to_transform_2d(&node.transform());
|
||||||
let transform = transform.pre_mul(&node_transform);
|
let transform = node_transform * *transform;
|
||||||
|
|
||||||
match *node.borrow() {
|
match *node.borrow() {
|
||||||
NodeKind::Group(ref group) => {
|
NodeKind::Group(ref group) => {
|
||||||
|
|
|
@ -93,8 +93,9 @@ impl SceneExt for Scene {
|
||||||
// FIXME(pcwalton): Cache this!
|
// FIXME(pcwalton): Cache this!
|
||||||
let scale = style.size / (font.metrics().units_per_em as f32);
|
let scale = style.size / (font.metrics().units_per_em as f32);
|
||||||
let scale = Vector2F::new(scale, -scale);
|
let scale = Vector2F::new(scale, -scale);
|
||||||
let transform =
|
let transform = *transform *
|
||||||
Transform2F::from_scale(scale).post_translate(offset).post_mul(transform);
|
Transform2F::from_translation(offset) *
|
||||||
|
Transform2F::from_scale(scale);
|
||||||
self.push_glyph(font,
|
self.push_glyph(font,
|
||||||
glyph.glyph_id,
|
glyph.glyph_id,
|
||||||
&transform,
|
&transform,
|
||||||
|
|
Loading…
Reference in New Issue