Struct tiny_skia::Transform

source ·
pub struct Transform {
    pub sx: f32,
    pub kx: f32,
    pub ky: f32,
    pub sy: f32,
    pub tx: f32,
    pub ty: f32,
}
Expand description

An affine transformation matrix.

Unlike other types, doesn’t guarantee to be valid. This is Skia quirk. Meaning Transform(0, 0, 0, 0, 0, 0) is ok, while it’s technically not. Non-finite values are also not an error.

Fields§

§sx: f32§kx: f32§ky: f32§sy: f32§tx: f32§ty: f32

Implementations§

source§

impl Transform

source

pub fn identity() -> Transform

Creates an identity transform.

Examples found in repository?
examples/pattern.rs (line 23)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
fn main() {
    let triangle = crate_triangle();

    let mut paint = Paint::default();
    paint.anti_alias = true;
    paint.shader = Pattern::new(
        triangle.as_ref(),
        SpreadMode::Repeat,
        FilterQuality::Bicubic,
        1.0,
        Transform::from_row(1.5, -0.4, 0.0, -0.8, 5.0, 1.0),
    );

    let path = PathBuilder::from_circle(200.0, 200.0, 180.0).unwrap();

    let mut pixmap = Pixmap::new(400, 400).unwrap();
    pixmap.fill_path(
        &path,
        &paint,
        FillRule::Winding,
        Transform::identity(),
        None,
    );
    pixmap.save_png("image.png").unwrap();
}

fn crate_triangle() -> Pixmap {
    let mut paint = Paint::default();
    paint.set_color_rgba8(50, 127, 150, 200);
    paint.anti_alias = true;

    let mut pb = PathBuilder::new();
    pb.move_to(0.0, 20.0);
    pb.line_to(20.0, 20.0);
    pb.line_to(10.0, 0.0);
    pb.close();
    let path = pb.finish().unwrap();

    let mut pixmap = Pixmap::new(20, 20).unwrap();
    pixmap.fill_path(
        &path,
        &paint,
        FillRule::Winding,
        Transform::identity(),
        None,
    );
    pixmap
}
More examples
Hide additional examples
examples/hairline.rs (line 16)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn main() {
    let mut pb = PathBuilder::new();
    pb.move_to(50.0, 100.0);
    pb.cubic_to(130.0, 20.0, 390.0, 120.0, 450.0, 30.0);
    let path = pb.finish().unwrap();

    let mut paint = Paint::default();
    paint.set_color_rgba8(50, 127, 150, 200);
    paint.anti_alias = true;

    let mut pixmap = Pixmap::new(500, 500).unwrap();
    let mut transform = Transform::identity();
    for i in 0..20 {
        let mut stroke = Stroke::default();
        stroke.width = 2.0 - (i as f32 / 10.0);
        pixmap.stroke_path(&path, &paint, &stroke, transform, None);
        transform = transform.pre_translate(0.0, 20.0);
    }

    pixmap.save_png("image.png").unwrap();
}
examples/image_on_image.rs (line 48)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
fn create_triangle() -> Pixmap {
    let mut paint = Paint::default();
    paint.set_color_rgba8(50, 127, 150, 200);
    paint.anti_alias = true;

    let mut pb = PathBuilder::new();
    pb.move_to(0.0, 200.0);
    pb.line_to(200.0, 200.0);
    pb.line_to(100.0, 0.0);
    pb.close();
    let path = pb.finish().unwrap();

    let mut pixmap = Pixmap::new(200, 200).unwrap();

    pixmap.fill_path(
        &path,
        &paint,
        FillRule::Winding,
        Transform::identity(),
        None,
    );

    let path = PathBuilder::from_rect(Rect::from_ltrb(0.0, 0.0, 200.0, 200.0).unwrap());
    let stroke = Stroke::default();
    paint.set_color_rgba8(200, 0, 0, 220);

    pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None); // TODO: stroke_rect

    pixmap
}
examples/mask.rs (line 26)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
fn main() {
    let clip_path = {
        let mut pb = PathBuilder::new();
        pb.push_circle(250.0, 250.0, 200.0);
        pb.push_circle(250.0, 250.0, 100.0);
        pb.finish().unwrap()
    };

    let clip_path = clip_path
        .transform(Transform::from_row(1.0, -0.3, 0.0, 1.0, 0.0, 75.0))
        .unwrap();

    let mut mask = Mask::new(500, 500).unwrap();
    mask.fill_path(&clip_path, FillRule::EvenOdd, true, Transform::default());

    let mut paint = Paint::default();
    paint.anti_alias = false;
    paint.set_color_rgba8(50, 127, 150, 200);

    let mut pixmap = Pixmap::new(500, 500).unwrap();
    pixmap.fill_rect(
        Rect::from_xywh(0.0, 0.0, 500.0, 500.0).unwrap(),
        &paint,
        Transform::identity(),
        Some(&mask),
    );
    pixmap.save_png("image.png").unwrap();
}
examples/stroke.rs (line 28)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
fn main() {
    let mut paint = Paint::default();
    paint.set_color_rgba8(0, 127, 0, 200);
    paint.anti_alias = true;

    let path = {
        let mut pb = PathBuilder::new();
        const RADIUS: f32 = 250.0;
        const CENTER: f32 = 250.0;
        pb.move_to(CENTER + RADIUS, CENTER);
        for i in 1..8 {
            let a = 2.6927937 * i as f32;
            pb.line_to(CENTER + RADIUS * a.cos(), CENTER + RADIUS * a.sin());
        }
        pb.finish().unwrap()
    };

    let mut stroke = Stroke::default();
    stroke.width = 6.0;
    stroke.line_cap = LineCap::Round;
    stroke.dash = StrokeDash::new(vec![20.0, 40.0], 0.0);

    let mut pixmap = Pixmap::new(500, 500).unwrap();
    pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
    pixmap.save_png("image.png").unwrap();
}
examples/linear_gradient.rs (line 14)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
fn main() {
    let mut paint = Paint::default();
    paint.anti_alias = false;
    paint.shader = LinearGradient::new(
        Point::from_xy(100.0, 100.0),
        Point::from_xy(900.0, 900.0),
        vec![
            GradientStop::new(0.0, Color::from_rgba8(50, 127, 150, 200)),
            GradientStop::new(1.0, Color::from_rgba8(220, 140, 75, 180)),
        ],
        SpreadMode::Pad,
        Transform::identity(),
    )
    .unwrap();

    let mut pb = PathBuilder::new();
    pb.move_to(60.0, 60.0);
    pb.line_to(160.0, 940.0);
    pb.cubic_to(380.0, 840.0, 660.0, 800.0, 940.0, 800.0);
    pb.cubic_to(740.0, 460.0, 440.0, 160.0, 60.0, 60.0);
    pb.close();
    let path = pb.finish().unwrap();

    let mut pixmap = Pixmap::new(1000, 1000).unwrap();
    pixmap.fill_path(
        &path,
        &paint,
        FillRule::Winding,
        Transform::identity(),
        None,
    );
    pixmap.save_png("image.png").unwrap();
}
source

pub fn from_row( sx: f32, ky: f32, kx: f32, sy: f32, tx: f32, ty: f32 ) -> Transform

Creates a new Transform.

We are using column-major-column-vector matrix notation, therefore it’s ky-kx, not kx-ky.

Examples found in repository?
examples/image_on_image.rs (line 18)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
fn main() {
    let triangle = create_triangle();

    let mut pixmap = Pixmap::new(400, 400).unwrap();

    let now = std::time::Instant::now();

    let mut paint = PixmapPaint::default();
    paint.quality = FilterQuality::Bicubic;

    pixmap.draw_pixmap(
        20,
        20,
        triangle.as_ref(),
        &paint,
        Transform::from_row(1.2, 0.5, 0.5, 1.2, 0.0, 0.0),
        None,
    );

    println!(
        "Rendered in {:.2}ms",
        now.elapsed().as_micros() as f64 / 1000.0
    );

    pixmap.save_png("image.png").unwrap();
}
More examples
Hide additional examples
examples/pattern.rs (line 13)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
fn main() {
    let triangle = crate_triangle();

    let mut paint = Paint::default();
    paint.anti_alias = true;
    paint.shader = Pattern::new(
        triangle.as_ref(),
        SpreadMode::Repeat,
        FilterQuality::Bicubic,
        1.0,
        Transform::from_row(1.5, -0.4, 0.0, -0.8, 5.0, 1.0),
    );

    let path = PathBuilder::from_circle(200.0, 200.0, 180.0).unwrap();

    let mut pixmap = Pixmap::new(400, 400).unwrap();
    pixmap.fill_path(
        &path,
        &paint,
        FillRule::Winding,
        Transform::identity(),
        None,
    );
    pixmap.save_png("image.png").unwrap();
}
examples/mask.rs (line 12)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
fn main() {
    let clip_path = {
        let mut pb = PathBuilder::new();
        pb.push_circle(250.0, 250.0, 200.0);
        pb.push_circle(250.0, 250.0, 100.0);
        pb.finish().unwrap()
    };

    let clip_path = clip_path
        .transform(Transform::from_row(1.0, -0.3, 0.0, 1.0, 0.0, 75.0))
        .unwrap();

    let mut mask = Mask::new(500, 500).unwrap();
    mask.fill_path(&clip_path, FillRule::EvenOdd, true, Transform::default());

    let mut paint = Paint::default();
    paint.anti_alias = false;
    paint.set_color_rgba8(50, 127, 150, 200);

    let mut pixmap = Pixmap::new(500, 500).unwrap();
    pixmap.fill_rect(
        Rect::from_xywh(0.0, 0.0, 500.0, 500.0).unwrap(),
        &paint,
        Transform::identity(),
        Some(&mask),
    );
    pixmap.save_png("image.png").unwrap();
}
source

pub fn from_translate(tx: f32, ty: f32) -> Transform

Creates a new translating Transform.

source

pub fn from_scale(sx: f32, sy: f32) -> Transform

Creates a new scaling Transform.

source

pub fn from_skew(kx: f32, ky: f32) -> Transform

Creates a new skewing Transform.

source

pub fn from_rotate(angle: f32) -> Transform

Creates a new rotating Transform.

angle in degrees.

source

pub fn from_rotate_at(angle: f32, tx: f32, ty: f32) -> Transform

Creates a new rotating Transform at the specified position.

angle in degrees.

source

pub fn from_bbox(bbox: NonZeroRect) -> Transform

Converts Rect into a bounding box Transform.

source

pub fn is_finite(&self) -> bool

Checks that transform is finite.

source

pub fn is_valid(&self) -> bool

Checks that transform is finite and has non-zero scale.

source

pub fn is_identity(&self) -> bool

Checks that transform is identity.

source

pub fn is_scale(&self) -> bool

Checks that transform is scale-only.

source

pub fn is_skew(&self) -> bool

Checks that transform is skew-only.

source

pub fn is_translate(&self) -> bool

Checks that transform is translate-only.

source

pub fn is_scale_translate(&self) -> bool

Checks that transform contains only scale and translate.

source

pub fn has_scale(&self) -> bool

Checks that transform contains a scale part.

source

pub fn has_skew(&self) -> bool

Checks that transform contains a skew part.

source

pub fn has_translate(&self) -> bool

Checks that transform contains a translate part.

source

pub fn get_scale(&self) -> (f32, f32)

Returns transform’s scale part.

source

pub fn pre_scale(&self, sx: f32, sy: f32) -> Transform

Pre-scales the current transform.

source

pub fn post_scale(&self, sx: f32, sy: f32) -> Transform

Post-scales the current transform.

source

pub fn pre_translate(&self, tx: f32, ty: f32) -> Transform

Pre-translates the current transform.

Examples found in repository?
examples/hairline.rs (line 21)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn main() {
    let mut pb = PathBuilder::new();
    pb.move_to(50.0, 100.0);
    pb.cubic_to(130.0, 20.0, 390.0, 120.0, 450.0, 30.0);
    let path = pb.finish().unwrap();

    let mut paint = Paint::default();
    paint.set_color_rgba8(50, 127, 150, 200);
    paint.anti_alias = true;

    let mut pixmap = Pixmap::new(500, 500).unwrap();
    let mut transform = Transform::identity();
    for i in 0..20 {
        let mut stroke = Stroke::default();
        stroke.width = 2.0 - (i as f32 / 10.0);
        pixmap.stroke_path(&path, &paint, &stroke, transform, None);
        transform = transform.pre_translate(0.0, 20.0);
    }

    pixmap.save_png("image.png").unwrap();
}
source

pub fn post_translate(&self, tx: f32, ty: f32) -> Transform

Post-translates the current transform.

source

pub fn pre_rotate(&self, angle: f32) -> Transform

Pre-rotates the current transform.

angle in degrees.

source

pub fn post_rotate(&self, angle: f32) -> Transform

Post-rotates the current transform.

angle in degrees.

source

pub fn pre_rotate_at(&self, angle: f32, tx: f32, ty: f32) -> Transform

Pre-rotates the current transform by the specified position.

angle in degrees.

source

pub fn post_rotate_at(&self, angle: f32, tx: f32, ty: f32) -> Transform

Post-rotates the current transform by the specified position.

angle in degrees.

source

pub fn pre_concat(&self, other: Transform) -> Transform

Pre-concats the current transform.

source

pub fn post_concat(&self, other: Transform) -> Transform

Post-concats the current transform.

source

pub fn map_point(&self, point: &mut Point)

Transforms a points using the current transform.

source

pub fn map_points(&self, points: &mut [Point])

Transforms a slice of points using the current transform.

source

pub fn invert(&self) -> Option<Transform>

Returns an inverted transform.

Trait Implementations§

source§

impl Clone for Transform

source§

fn clone(&self) -> Transform

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Transform

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Default for Transform

source§

fn default() -> Transform

Returns the “default value” for a type. Read more
source§

impl PartialEq for Transform

source§

fn eq(&self, other: &Transform) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Copy for Transform

source§

impl StructuralPartialEq for Transform

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.