[librsvg/wip/euclid: 2/2] transform: add a Tranform type
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/wip/euclid: 2/2] transform: add a Tranform type
- Date: Tue, 26 Nov 2019 19:57:49 +0000 (UTC)
commit 9a1dd3dce1267e77fb73db9a9c413fd76f65a674
Author: Paolo Borelli <pborelli gnome org>
Date: Sun Nov 17 11:33:58 2019 +0100
transform: add a Tranform type
Use an alias for cairo::Matrix and add a trait to ease transition
to the euclid crate.
rsvg_internals/src/aspect_ratio.rs | 7 +-
rsvg_internals/src/bbox.rs | 19 +++--
rsvg_internals/src/clip_path.rs | 1 -
rsvg_internals/src/drawing_ctx.rs | 31 ++++----
rsvg_internals/src/node.rs | 14 ++--
rsvg_internals/src/text.rs | 3 +-
rsvg_internals/src/transform.rs | 141 ++++++++++++++++++++++---------------
7 files changed, 122 insertions(+), 94 deletions(-)
---
diff --git a/rsvg_internals/src/aspect_ratio.rs b/rsvg_internals/src/aspect_ratio.rs
index d4475aef..37c5484c 100644
--- a/rsvg_internals/src/aspect_ratio.rs
+++ b/rsvg_internals/src/aspect_ratio.rs
@@ -28,6 +28,7 @@ use crate::error::ValueErrorKind;
use crate::float_eq_cairo::ApproxEqCairo;
use crate::parsers::Parse;
use crate::parsers::ParseError;
+use crate::transform::Transform;
use crate::viewbox::ViewBox;
use cssparser::{CowRcStr, Parser};
@@ -154,7 +155,7 @@ impl AspectRatio {
&self,
vbox: Option<ViewBox>,
viewport: &cairo::Rectangle,
- ) -> Option<cairo::Matrix> {
+ ) -> Option<Transform> {
// width or height set to 0 disables rendering of the element
// https://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
// https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
@@ -174,14 +175,14 @@ impl AspectRatio {
None
} else {
let (x, y, w, h) = self.compute(&vbox, viewport);
- let mut matrix = cairo::Matrix::identity();
+ let mut matrix = Transform::identity();
matrix.translate(x, y);
matrix.scale(w / vbox.width, h / vbox.height);
matrix.translate(-vbox.x, -vbox.y);
Some(matrix)
}
} else {
- let mut matrix = cairo::Matrix::identity();
+ let mut matrix = Transform::identity();
matrix.translate(viewport.x, viewport.y);
Some(matrix)
}
diff --git a/rsvg_internals/src/bbox.rs b/rsvg_internals/src/bbox.rs
index 68ccae69..9fae6fa5 100644
--- a/rsvg_internals/src/bbox.rs
+++ b/rsvg_internals/src/bbox.rs
@@ -1,16 +1,17 @@
use cairo;
use crate::rect::RectangleExt;
+use crate::transform::{Transform, TransformExt};
#[derive(Debug, Copy, Clone)]
pub struct BoundingBox {
- pub affine: cairo::Matrix,
+ pub affine: Transform,
pub rect: Option<cairo::Rectangle>, // without stroke
pub ink_rect: Option<cairo::Rectangle>, // with stroke
}
impl BoundingBox {
- pub fn new(affine: &cairo::Matrix) -> BoundingBox {
+ pub fn new(affine: &Transform) -> BoundingBox {
BoundingBox {
affine: *affine,
rect: None,
@@ -39,14 +40,12 @@ impl BoundingBox {
return;
}
- let mut affine = self.affine;
+ if let Some(inverse) = self.affine.inverse() {
+ let affine = inverse.pre_transform(&src.affine);
- // this will panic!() if it's not invertible... should we check on our own?
- affine.invert();
- affine = cairo::Matrix::multiply(&src.affine, &affine);
-
- self.rect = combine_rects(self.rect, src.rect, &affine, clip);
- self.ink_rect = combine_rects(self.ink_rect, src.ink_rect, &affine, clip);
+ self.rect = combine_rects(self.rect, src.rect, &affine, clip);
+ self.ink_rect = combine_rects(self.ink_rect, src.ink_rect, &affine, clip);
+ }
}
pub fn insert(&mut self, src: &BoundingBox) {
@@ -70,7 +69,7 @@ fn rect_from_extents((x1, y1, x2, y2): (f64, f64, f64, f64)) -> Option<cairo::Re
fn combine_rects(
r1: Option<cairo::Rectangle>,
r2: Option<cairo::Rectangle>,
- affine: &cairo::Matrix,
+ affine: &Transform,
clip: bool,
) -> Option<cairo::Rectangle> {
match (r1, r2, clip) {
diff --git a/rsvg_internals/src/clip_path.rs b/rsvg_internals/src/clip_path.rs
index 5dfd21a2..64e5681b 100644
--- a/rsvg_internals/src/clip_path.rs
+++ b/rsvg_internals/src/clip_path.rs
@@ -1,4 +1,3 @@
-use cairo;
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::bbox::BoundingBox;
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 95661d52..9f61906d 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -25,6 +25,7 @@ use crate::property_defs::{
};
use crate::rect::RectangleExt;
use crate::surface_utils::shared_surface::SharedImageSurface;
+use crate::transform::{Transform, TransformExt};
use crate::unit_interval::UnitInterval;
use crate::viewbox::ViewBox;
@@ -77,7 +78,7 @@ pub enum ClipMode {
pub struct DrawingCtx {
document: Rc<Document>,
- initial_affine: cairo::Matrix,
+ initial_affine: Transform,
rect: cairo::Rectangle,
dpi: Dpi,
@@ -533,7 +534,7 @@ impl DrawingCtx {
}
}
- fn initial_affine_with_offset(&self) -> cairo::Matrix {
+ fn initial_affine_with_offset(&self) -> Transform {
let mut initial_with_offset = self.initial_affine;
initial_with_offset.translate(self.rect.x, self.rect.y);
initial_with_offset
@@ -831,7 +832,7 @@ impl DrawingCtx {
node: &RsvgNode,
cascaded: &CascadedValues<'_>,
surface: &cairo::ImageSurface,
- affine: cairo::Matrix,
+ affine: Transform,
width: f64,
height: f64,
) -> Result<BoundingBox, RenderingError> {
@@ -893,17 +894,17 @@ impl DrawingCtx {
#[derive(Debug)]
pub struct CompositingAffines {
- pub outside_temporary_surface: cairo::Matrix,
- pub initial: cairo::Matrix,
- pub for_temporary_surface: cairo::Matrix,
- pub compositing: cairo::Matrix,
- pub for_snapshot: cairo::Matrix,
+ pub outside_temporary_surface: Transform,
+ pub initial: Transform,
+ pub for_temporary_surface: Transform,
+ pub compositing: Transform,
+ pub for_snapshot: Transform,
}
impl CompositingAffines {
fn new(
- current: cairo::Matrix,
- initial: cairo::Matrix,
+ current: Transform,
+ initial: Transform,
cr_stack_depth: usize,
) -> CompositingAffines {
let is_topmost_temporary_surface = cr_stack_depth == 0;
@@ -913,15 +914,15 @@ impl CompositingAffines {
let outside_temporary_surface = if is_topmost_temporary_surface {
current
} else {
- cairo::Matrix::multiply(¤t, &initial_inverse)
+ initial_inverse.pre_transform(¤t)
};
let (scale_x, scale_y) = initial.transform_distance(1.0, 1.0);
let for_temporary_surface = if is_topmost_temporary_surface {
- let untransformed = cairo::Matrix::multiply(¤t, &initial_inverse);
- let scale = cairo::Matrix::new(scale_x, 0.0, 0.0, scale_y, 0.0, 0.0);
- cairo::Matrix::multiply(&untransformed, &scale)
+ let untransformed = initial_inverse.pre_transform(¤t);
+ let scale = Transform::new(scale_x, 0.0, 0.0, scale_y, 0.0, 0.0);
+ scale.pre_transform(&untransformed)
} else {
current
};
@@ -931,7 +932,7 @@ impl CompositingAffines {
scaled.scale(1.0 / scale_x, 1.0 / scale_y);
scaled
} else {
- cairo::Matrix::identity()
+ Transform::identity()
};
let for_snapshot = compositing.try_invert().unwrap();
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index fd94dd59..ea8aa8e1 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -1,6 +1,7 @@
-use cairo::Matrix;
use downcast_rs::*;
+use locale_config::Locale;
use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
+use rctree;
use std::cell::Ref;
use std::collections::HashSet;
use std::fmt;
@@ -15,8 +16,7 @@ use crate::parsers::Parse;
use crate::properties::{ComputedValues, SpecifiedValue, SpecifiedValues};
use crate::property_bag::PropertyBag;
use crate::property_defs::Overflow;
-use locale_config::Locale;
-use rctree;
+use crate::transform::Transform;
/// Tree node with specific data
pub type RsvgNode = rctree::Node<NodeData>;
@@ -31,7 +31,7 @@ pub struct NodeData {
specified_values: SpecifiedValues,
important_styles: HashSet<QualName>,
result: NodeResult,
- transform: Matrix,
+ transform: Transform,
values: ComputedValues,
cond: bool,
style_attr: String,
@@ -53,7 +53,7 @@ impl NodeData {
class: class.map(str::to_string),
specified_values: Default::default(),
important_styles: Default::default(),
- transform: Matrix::identity(),
+ transform: Transform::identity(),
result: Ok(()),
values: ComputedValues::default(),
cond: true,
@@ -94,7 +94,7 @@ impl NodeData {
self.cond
}
- pub fn get_transform(&self) -> Matrix {
+ pub fn get_transform(&self) -> Transform {
self.transform
}
@@ -135,7 +135,7 @@ impl NodeData {
for (attr, value) in pbag.iter() {
match attr.expanded() {
expanded_name!(svg "transform") => {
- return Matrix::parse_str(value).attribute(attr).and_then(|affine| {
+ return Transform::parse_str(value).attribute(attr).and_then(|affine| {
self.transform = affine;
Ok(())
});
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index 29f13c84..d10bde41 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -29,6 +29,7 @@ use crate::property_defs::{
XmlSpace,
};
use crate::space::{xml_space_normalize, NormalizeDefault, XmlSpaceNormalize};
+use crate::transform::Transform;
/// An absolutely-positioned array of `Span`s
///
@@ -363,7 +364,7 @@ impl PositionedSpan {
fn compute_text_bbox(
&self,
- affine: &cairo::Matrix,
+ affine: &Transform,
gravity: pango::Gravity,
) -> Option<BoundingBox> {
let (ink, _) = self.layout.get_extents();
diff --git a/rsvg_internals/src/transform.rs b/rsvg_internals/src/transform.rs
index 89298307..e830a6b3 100644
--- a/rsvg_internals/src/transform.rs
+++ b/rsvg_internals/src/transform.rs
@@ -7,16 +7,43 @@ use cssparser::{ParseError as CssParseError, Parser, Token};
use crate::error::*;
use crate::parsers::{finite_f32, CssParserExt, Parse, ParseError};
-impl Parse for cairo::Matrix {
+pub type Transform = cairo::Matrix;
+
+// Extension trait to prepare the switch from cairo::Matrix to euclid
+pub trait TransformExt
+where Self: std::marker::Sized
+{
+ fn row_major(m11: f64, m12: f64, m21: f64, m22: f64, m31: f64, m32: f64) -> Self;
+
+ fn inverse(&self) -> Option<Self>;
+
+ fn pre_transform(&self, mat: &Self) -> Self;
+}
+
+impl TransformExt for Transform {
+ fn row_major(m11: f64, m12: f64, m21: f64, m22: f64, m31: f64, m32: f64) -> Self {
+ cairo::Matrix::new(m11, m12, m21, m22, m31, m32)
+ }
+
+ fn inverse(&self) -> Option<Self> {
+ self.try_invert().ok()
+ }
+
+ fn pre_transform(&self, mat: &Self) -> Self {
+ cairo::Matrix::multiply(mat, self)
+ }
+}
+
+impl Parse for Transform {
type Err = ValueErrorKind;
- fn parse(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+ fn parse(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
let matrix = parse_transform_list(parser)?;
- matrix
- .try_invert()
- .map(|_| matrix)
- .map_err(|_| ValueErrorKind::Value("invalid transformation matrix".to_string()))
+ match matrix.inverse() {
+ Some(_) => Ok(matrix),
+ _ => Err(ValueErrorKind::Value("invalid transformation matrix".to_string())),
+ }
}
}
@@ -24,8 +51,8 @@ impl Parse for cairo::Matrix {
// Its operataion and grammar are described here:
// https://www.w3.org/TR/SVG/coords.html#TransformAttribute
-fn parse_transform_list(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
- let mut matrix = cairo::Matrix::identity();
+fn parse_transform_list(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
+ let mut matrix = Transform::identity();
loop {
if parser.is_exhausted() {
@@ -33,7 +60,7 @@ fn parse_transform_list(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, Va
}
let m = parse_transform_command(parser)?;
- matrix = cairo::Matrix::multiply(&m, &matrix);
+ matrix = matrix.pre_transform(&m);
parser.optional_comma();
}
@@ -47,7 +74,7 @@ fn make_expected_function_error() -> ValueErrorKind {
))
}
-fn parse_transform_command(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+fn parse_transform_command(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
match parser.next()?.clone() {
Token::Function(ref name) => parse_transform_function(name, parser),
@@ -63,7 +90,7 @@ fn parse_transform_command(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix,
fn parse_transform_function(
name: &str,
parser: &mut Parser<'_, '_>,
-) -> Result<cairo::Matrix, ValueErrorKind> {
+) -> Result<Transform, ValueErrorKind> {
match name {
"matrix" => parse_matrix_args(parser),
"translate" => parse_translate_args(parser),
@@ -75,7 +102,7 @@ fn parse_transform_function(
}
}
-fn parse_matrix_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+fn parse_matrix_args(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
parser
.parse_nested_block(|p| {
let xx = p.expect_number()?;
@@ -107,11 +134,11 @@ fn parse_matrix_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, Value
let x0 = f64::from(finite_f32(x0)?);
let y0 = f64::from(finite_f32(y0)?);
- Ok(cairo::Matrix::new(xx, yx, xy, yy, x0, y0))
+ Ok(Transform::row_major(xx, yx, xy, yy, x0, y0))
})
}
-fn parse_translate_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+fn parse_translate_args(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
parser
.parse_nested_block(|p| {
let tx = p.expect_number()?;
@@ -131,11 +158,11 @@ fn parse_translate_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, Va
let tx = f64::from(finite_f32(tx)?);
let ty = f64::from(finite_f32(ty)?);
- Ok(cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty))
+ Ok(Transform::row_major(1.0, 0.0, 0.0, 1.0, tx, ty))
})
}
-fn parse_scale_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+fn parse_scale_args(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
parser
.parse_nested_block(|p| {
let x = p.expect_number()?;
@@ -155,11 +182,11 @@ fn parse_scale_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueE
let x = f64::from(finite_f32(x)?);
let y = f64::from(finite_f32(y)?);
- Ok(cairo::Matrix::new(x, 0.0, 0.0, y, 0.0, 0.0))
+ Ok(Transform::row_major(x, 0.0, 0.0, y, 0.0, 0.0))
})
}
-fn parse_rotate_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+fn parse_rotate_args(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
parser
.parse_nested_block(|p| {
let angle = p.expect_number()?;
@@ -188,15 +215,16 @@ fn parse_rotate_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, Value
let angle = angle * PI / 180.0;
let (s, c) = angle.sin_cos();
- let mut m = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty);
+ let mut m = Transform::row_major(1.0, 0.0, 0.0, 1.0, tx, ty);
- m = cairo::Matrix::multiply(&cairo::Matrix::new(c, s, -s, c, 0.0, 0.0), &m);
- m = cairo::Matrix::multiply(&cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
+ // FIXME: use euclid pre_rotate / pre_translate?
+ m = m.pre_transform(&Transform::row_major(c, s, -s, c, 0.0, 0.0));
+ m = m.pre_transform(&Transform::row_major(1.0, 0.0, 0.0, 1.0, -tx, -ty));
Ok(m)
})
}
-fn parse_skewx_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+fn parse_skewx_args(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
parser
.parse_nested_block(|p| {
let a = p.expect_number()?;
@@ -208,11 +236,11 @@ fn parse_skewx_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueE
let a = f64::from(finite_f32(a)?);
let a = a * PI / 180.0;
- Ok(cairo::Matrix::new(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0))
+ Ok(Transform::row_major(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0))
})
}
-fn parse_skewy_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
+fn parse_skewy_args(parser: &mut Parser<'_, '_>) -> Result<Transform, ValueErrorKind> {
parser
.parse_nested_block(|p| {
let a = p.expect_number()?;
@@ -224,22 +252,21 @@ fn parse_skewy_args(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueE
let a = f64::from(finite_f32(a)?);
let a = a * PI / 180.0;
- Ok(cairo::Matrix::new(1.0, a.tan(), 0.0, 1.0, 0.0, 0.0))
+ Ok(Transform::row_major(1.0, a.tan(), 0.0, 1.0, 0.0, 0.0))
})
}
#[cfg(test)]
-fn make_rotation_matrix(angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
+fn make_rotation_matrix(angle_degrees: f64, tx: f64, ty: f64) -> Transform {
let angle = angle_degrees * PI / 180.0;
- let mut m = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty);
+ let mut m = Transform::row_major(1.0, 0.0, 0.0, 1.0, tx, ty);
- let mut r = cairo::Matrix::identity();
+ let mut r = Transform::identity();
r.rotate(angle);
- m = cairo::Matrix::multiply(&r, &m);
- m = cairo::Matrix::multiply(&cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
- m
+ m = m.pre_transform(&r);
+ m.pre_transform(&Transform::row_major(1.0, 0.0, 0.0, 1.0, -tx, -ty))
}
#[cfg(test)]
@@ -248,11 +275,11 @@ mod tests {
use float_cmp::ApproxEq;
use std::f64;
- fn parse_transform(s: &str) -> Result<cairo::Matrix, ValueErrorKind> {
- cairo::Matrix::parse_str(s)
+ fn parse_transform(s: &str) -> Result<Transform, ValueErrorKind> {
+ Transform::parse_str(s)
}
- fn assert_matrix_eq(a: &cairo::Matrix, b: &cairo::Matrix) {
+ fn assert_matrix_eq(a: &Transform, b: &Transform) {
let epsilon = 8.0 * f64::EPSILON; // kind of arbitrary, but allow for some sloppiness
assert!(a.xx.approx_eq(b.xx, (epsilon, 1)));
@@ -265,14 +292,14 @@ mod tests {
#[test]
fn parses_valid_transform() {
- let t = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
- let s = cairo::Matrix::new(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
+ let t = Transform::row_major(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
+ let s = Transform::row_major(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
let r = make_rotation_matrix(30.0, 10.0, 10.0);
- let a = cairo::Matrix::multiply(&s, &t);
+ let a = t.pre_transform(&s);
assert_matrix_eq(
&parse_transform("translate(20, 30), scale (10) rotate (30 10 10)").unwrap(),
- &cairo::Matrix::multiply(&r, &a),
+ &a.pre_transform(&r),
);
}
@@ -325,17 +352,17 @@ mod tests {
fn parses_matrix() {
assert_matrix_eq(
&parse_transform("matrix (1 2 3 4 5 6)").unwrap(),
- &cairo::Matrix::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0),
+ &Transform::row_major(1.0, 2.0, 3.0, 4.0, 5.0, 6.0),
);
assert_matrix_eq(
&parse_transform("matrix(1,2,3,4 5 6)").unwrap(),
- &cairo::Matrix::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0),
+ &Transform::row_major(1.0, 2.0, 3.0, 4.0, 5.0, 6.0),
);
assert_matrix_eq(
&parse_transform("matrix (1,2.25,-3.25e2,4 5 6)").unwrap(),
- &cairo::Matrix::new(1.0, 2.25, -325.0, 4.0, 5.0, 6.0),
+ &Transform::row_major(1.0, 2.25, -325.0, 4.0, 5.0, 6.0),
);
}
@@ -343,17 +370,17 @@ mod tests {
fn parses_translate() {
assert_matrix_eq(
&parse_transform("translate(-1 -2)").unwrap(),
- &cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, -2.0),
+ &Transform::row_major(1.0, 0.0, 0.0, 1.0, -1.0, -2.0),
);
assert_matrix_eq(
&parse_transform("translate(-1, -2)").unwrap(),
- &cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, -2.0),
+ &Transform::row_major(1.0, 0.0, 0.0, 1.0, -1.0, -2.0),
);
assert_matrix_eq(
&parse_transform("translate(-1)").unwrap(),
- &cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, 0.0),
+ &Transform::row_major(1.0, 0.0, 0.0, 1.0, -1.0, 0.0),
);
}
@@ -361,17 +388,17 @@ mod tests {
fn parses_scale() {
assert_matrix_eq(
&parse_transform("scale (-1)").unwrap(),
- &cairo::Matrix::new(-1.0, 0.0, 0.0, -1.0, 0.0, 0.0),
+ &Transform::row_major(-1.0, 0.0, 0.0, -1.0, 0.0, 0.0),
);
assert_matrix_eq(
&parse_transform("scale(-1 -2)").unwrap(),
- &cairo::Matrix::new(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0),
+ &Transform::row_major(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0),
);
assert_matrix_eq(
&parse_transform("scale(-1, -2)").unwrap(),
- &cairo::Matrix::new(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0),
+ &Transform::row_major(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0),
);
}
@@ -391,12 +418,12 @@ mod tests {
);
}
- fn make_skew_x_matrix(angle_degrees: f64) -> cairo::Matrix {
+ fn make_skew_x_matrix(angle_degrees: f64) -> Transform {
let a = angle_degrees * PI / 180.0;
- cairo::Matrix::new(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0)
+ Transform::row_major(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0)
}
- fn make_skew_y_matrix(angle_degrees: f64) -> cairo::Matrix {
+ fn make_skew_y_matrix(angle_degrees: f64) -> Transform {
let mut m = make_skew_x_matrix(angle_degrees);
m.yx = m.xy;
m.xy = 0.0;
@@ -421,29 +448,29 @@ mod tests {
#[test]
fn parses_transform_list() {
- let t = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
- let s = cairo::Matrix::new(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
+ let t = Transform::row_major(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
+ let s = Transform::row_major(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
let r = make_rotation_matrix(30.0, 10.0, 10.0);
assert_matrix_eq(
&parse_transform("scale(10)rotate(30, 10, 10)").unwrap(),
- &cairo::Matrix::multiply(&r, &s),
+ &s.pre_transform(&r),
);
assert_matrix_eq(
&parse_transform("translate(20, 30), scale (10)").unwrap(),
- &cairo::Matrix::multiply(&s, &t),
+ &t.pre_transform(&s),
);
- let a = cairo::Matrix::multiply(&s, &t);
+ let a = t.pre_transform(&s);
assert_matrix_eq(
&parse_transform("translate(20, 30), scale (10) rotate (30 10 10)").unwrap(),
- &cairo::Matrix::multiply(&r, &a),
+ &a.pre_transform(&r),
);
}
#[test]
fn parses_empty() {
- assert_matrix_eq(&parse_transform("").unwrap(), &cairo::Matrix::identity());
+ assert_matrix_eq(&parse_transform("").unwrap(), &Transform::identity());
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]