[go: up one dir, main page]

Affine

Struct Affine 

Source
pub struct Affine(/* private fields */);
Expand description

A 2D affine transform.

Implementations§

Source§

impl Affine

Source

pub const IDENTITY: Affine

The identity transform.

Source

pub const FLIP_Y: Affine

A transform that is flipped on the y-axis. Useful for converting between y-up and y-down spaces.

Source

pub const FLIP_X: Affine

A transform that is flipped on the x-axis.

Source

pub const fn new(c: [f64; 6]) -> Affine

Construct an affine transform from coefficients.

If the coefficients are (a, b, c, d, e, f), then the resulting transformation represents this augmented matrix:

| a c e |
| b d f |
| 0 0 1 |

Note that this convention is transposed from PostScript and Direct2D, but is consistent with the Wikipedia formulation of affine transformation as augmented matrix. The idea is that (A * B) * v == A * (B * v), where * is the Mul trait.

Source

pub const fn scale(s: f64) -> Affine

An affine transform representing uniform scaling.

Examples found in repository?
examples/sub_window.rs (line 283)
274    fn paint(&mut self, ctx: &mut PaintCtx, _data: &(), env: &Env) {
275        let sz = ctx.size();
276
277        let monitors = Screen::get_monitors();
278        let all = monitors
279            .iter()
280            .map(|x| x.virtual_rect())
281            .fold(Rect::ZERO, |s, r| r.union(s));
282        if all.width() > 0. && all.height() > 0. {
283            let trans = Affine::scale(f64::min(sz.width / all.width(), sz.height / all.height()))
284                * Affine::translate(all.origin().to_vec2()).inverse();
285            let font = env.get(theme::UI_FONT).family;
286
287            for (i, mon) in monitors.iter().enumerate() {
288                let vr = mon.virtual_rect();
289                let tr = trans.transform_rect_bbox(vr);
290                ctx.stroke(tr, &Color::WHITE, 1.0);
291
292                if let Ok(tl) = ctx
293                    .text()
294                    .new_text_layout(format!(
295                        "{}:{}x{}@{},{}",
296                        i,
297                        vr.width(),
298                        vr.height(),
299                        vr.x0,
300                        vr.y0
301                    ))
302                    .max_width(tr.width() - 5.)
303                    .font(font.clone(), env.get(theme::TEXT_SIZE_NORMAL))
304                    .text_color(Color::WHITE)
305                    .build()
306                {
307                    ctx.draw_text(&tl, tr.center() - tl.size().to_vec2() * 0.5);
308                }
309            }
310        }
311    }
Source

pub const fn scale_non_uniform(s_x: f64, s_y: f64) -> Affine

An affine transform representing non-uniform scaling with different scale values for x and y

Source

pub fn rotate(th: f64) -> Affine

An affine transform representing rotation.

The convention for rotation is that a positive angle rotates a positive X direction into positive Y. Thus, in a Y-down coordinate system (as is common for graphics), it is a clockwise rotation, and in Y-up (traditional for math), it is anti-clockwise.

The angle, th, is expressed in radians.

Examples found in repository?
examples/custom_widget.rs (line 131)
77    fn paint(&mut self, ctx: &mut PaintCtx, data: &String, env: &Env) {
78        // Clear the whole widget with the color of your choice
79        // (ctx.size() returns the size of the layout rect we're painting in)
80        // Note: ctx also has a `clear` method, but that clears the whole context,
81        // and we only want to clear this widget's area.
82        let size = ctx.size();
83        let rect = size.to_rect();
84        ctx.fill(rect, &Color::WHITE);
85
86        // We can paint with a Z index, this indicates that this code will be run
87        // after the rest of the painting. Painting with z-index is done in order,
88        // so first everything with z-index 1 is painted and then with z-index 2 etc.
89        // As you can see this(red) curve is drawn on top of the green curve
90        ctx.paint_with_z_index(1, move |ctx| {
91            let mut path = BezPath::new();
92            path.move_to((0.0, size.height));
93            path.quad_to((40.0, 50.0), (size.width, 0.0));
94            // Create a color
95            let stroke_color = Color::rgb8(128, 0, 0);
96            // Stroke the path with thickness 1.0
97            ctx.stroke(path, &stroke_color, 5.0);
98        });
99
100        // Create an arbitrary bezier path
101        let mut path = BezPath::new();
102        path.move_to(Point::ORIGIN);
103        path.quad_to((40.0, 50.0), (size.width, size.height));
104        // Create a color
105        let stroke_color = Color::rgb8(0, 128, 0);
106        // Stroke the path with thickness 5.0
107        ctx.stroke(path, &stroke_color, 5.0);
108
109        // Rectangles: the path for practical people
110        let rect = Rect::from_origin_size((10.0, 10.0), (100.0, 100.0));
111        // Note the Color:rgba8 which includes an alpha channel (7F in this case)
112        let fill_color = Color::rgba8(0x00, 0x00, 0x00, 0x7F);
113        ctx.fill(rect, &fill_color);
114
115        // Text is easy; in real use TextLayout should either be stored in the
116        // widget and reused, or a label child widget to manage it all.
117        // This is one way of doing it, you can also use a builder-style way.
118        let mut layout = TextLayout::<String>::from_text(data);
119        layout.set_font(FontDescriptor::new(FontFamily::SERIF).with_size(24.0));
120        layout.set_text_color(fill_color);
121        layout.rebuild_if_needed(ctx.text(), env);
122
123        // Let's rotate our text slightly. First we save our current (default) context:
124        ctx.with_save(|ctx| {
125            // Now we can rotate the context (or set a clip path, for instance):
126            // This makes it so that anything drawn after this (in the closure) is
127            // transformed.
128            // The transformation is in radians, but be aware it transforms the canvas,
129            // not just the part you are drawing. So we draw at (80.0, 40.0) on the rotated
130            // canvas, this is NOT the same position as (80.0, 40.0) on the original canvas.
131            ctx.transform(Affine::rotate(std::f64::consts::FRAC_PI_4));
132            layout.draw(ctx, (80.0, 40.0));
133        });
134        // When we exit with_save, the original context's rotation is restored
135
136        // This is the builder-style way of drawing text.
137        let text = ctx.text();
138        let layout = text
139            .new_text_layout(data.clone())
140            .font(FontFamily::SERIF, 24.0)
141            .text_color(Color::rgb8(128, 0, 0))
142            .build()
143            .unwrap();
144        ctx.draw_text(&layout, (100.0, 25.0));
145
146        // Let's burn some CPU to make a (partially transparent) image buffer
147        let image_data = make_image_data(256, 256);
148        let image = ctx
149            .make_image(256, 256, &image_data, ImageFormat::RgbaSeparate)
150            .unwrap();
151        // The image is automatically scaled to fit the rect you pass to draw_image
152        ctx.draw_image(&image, size.to_rect(), InterpolationMode::Bilinear);
153    }
Source

pub fn rotate_about(th: f64, center: Point) -> Affine

An affine transform representing a rotation of th radians about center.

See Affine::rotate for more info.

Source

pub fn translate<V>(p: V) -> Affine
where V: Into<Vec2>,

An affine transform representing translation.

Examples found in repository?
examples/sub_window.rs (line 284)
274    fn paint(&mut self, ctx: &mut PaintCtx, _data: &(), env: &Env) {
275        let sz = ctx.size();
276
277        let monitors = Screen::get_monitors();
278        let all = monitors
279            .iter()
280            .map(|x| x.virtual_rect())
281            .fold(Rect::ZERO, |s, r| r.union(s));
282        if all.width() > 0. && all.height() > 0. {
283            let trans = Affine::scale(f64::min(sz.width / all.width(), sz.height / all.height()))
284                * Affine::translate(all.origin().to_vec2()).inverse();
285            let font = env.get(theme::UI_FONT).family;
286
287            for (i, mon) in monitors.iter().enumerate() {
288                let vr = mon.virtual_rect();
289                let tr = trans.transform_rect_bbox(vr);
290                ctx.stroke(tr, &Color::WHITE, 1.0);
291
292                if let Ok(tl) = ctx
293                    .text()
294                    .new_text_layout(format!(
295                        "{}:{}x{}@{},{}",
296                        i,
297                        vr.width(),
298                        vr.height(),
299                        vr.x0,
300                        vr.y0
301                    ))
302                    .max_width(tr.width() - 5.)
303                    .font(font.clone(), env.get(theme::TEXT_SIZE_NORMAL))
304                    .text_color(Color::WHITE)
305                    .build()
306                {
307                    ctx.draw_text(&tl, tr.center() - tl.size().to_vec2() * 0.5);
308                }
309            }
310        }
311    }
Source

pub fn skew(skew_x: f64, skew_y: f64) -> Affine

An affine transformation representing a skew.

The skew_x and skew_y parameters represent skew factors for the horizontal and vertical directions, respectively.

This is commonly used to generate a faux oblique transform for font rendering. In this case, you can slant the glyph 20 degrees clockwise in the horizontal direction (assuming a Y-up coordinate system):

let oblique_transform = kurbo::Affine::skew(20f64.to_radians().tan(), 0.0);
Source

pub fn pre_rotate(self, th: f64) -> Affine

A rotation by th followed by self.

Equivalent to self * Affine::rotate(th)

Source

pub fn pre_rotate_about(self, th: f64, center: Point) -> Affine

A rotation by th about center followed by self.

Equivalent to self * Affine::rotate_about(th)

Source

pub fn pre_scale(self, scale: f64) -> Affine

A scale by scale followed by self.

Equivalent to self * Affine::scale(scale)

Source

pub fn pre_scale_non_uniform(self, scale_x: f64, scale_y: f64) -> Affine

A scale by (scale_x, scale_y) followed by self.

Equivalent to self * Affine::scale_non_uniform(scale_x, scale_y)

Source

pub fn pre_translate(self, trans: Vec2) -> Affine

A translation of trans followed by self.

Equivalent to self * Affine::translate(trans)

Source

pub fn then_rotate(self, th: f64) -> Affine

self followed by a rotation of th.

Equivalent to Affine::rotate(th) * self

Source

pub fn then_rotate_about(self, th: f64, center: Point) -> Affine

self followed by a rotation of th about `center.

Equivalent to Affine::rotate_about(th, center) * self

Source

pub fn then_scale(self, scale: f64) -> Affine

self followed by a scale of scale.

Equivalent to Affine::scale(scale) * self

Source

pub fn then_scale_non_uniform(self, scale_x: f64, scale_y: f64) -> Affine

self followed by a scale of (scale_x, scale_y).

Equivalent to Affine::scale_non_uniform(scale_x, scale_y) * self

Source

pub fn then_translate(self, trans: Vec2) -> Affine

self followed by a translation of trans.

Equivalent to Affine::translate(trans) * self

Source

pub fn map_unit_square(rect: Rect) -> Affine

Creates an affine transformation that takes the unit square to the given rectangle.

Useful when you want to draw into the unit square but have your output fill any rectangle. In this case push the Affine onto the transform stack.

Source

pub fn as_coeffs(self) -> [f64; 6]

Get the coefficients of the transform.

Source

pub fn determinant(self) -> f64

Compute the determinant of this transform.

Source

pub fn inverse(self) -> Affine

Compute the inverse transform.

Produces NaN values when the determinant is zero.

Examples found in repository?
examples/sub_window.rs (line 284)
274    fn paint(&mut self, ctx: &mut PaintCtx, _data: &(), env: &Env) {
275        let sz = ctx.size();
276
277        let monitors = Screen::get_monitors();
278        let all = monitors
279            .iter()
280            .map(|x| x.virtual_rect())
281            .fold(Rect::ZERO, |s, r| r.union(s));
282        if all.width() > 0. && all.height() > 0. {
283            let trans = Affine::scale(f64::min(sz.width / all.width(), sz.height / all.height()))
284                * Affine::translate(all.origin().to_vec2()).inverse();
285            let font = env.get(theme::UI_FONT).family;
286
287            for (i, mon) in monitors.iter().enumerate() {
288                let vr = mon.virtual_rect();
289                let tr = trans.transform_rect_bbox(vr);
290                ctx.stroke(tr, &Color::WHITE, 1.0);
291
292                if let Ok(tl) = ctx
293                    .text()
294                    .new_text_layout(format!(
295                        "{}:{}x{}@{},{}",
296                        i,
297                        vr.width(),
298                        vr.height(),
299                        vr.x0,
300                        vr.y0
301                    ))
302                    .max_width(tr.width() - 5.)
303                    .font(font.clone(), env.get(theme::TEXT_SIZE_NORMAL))
304                    .text_color(Color::WHITE)
305                    .build()
306                {
307                    ctx.draw_text(&tl, tr.center() - tl.size().to_vec2() * 0.5);
308                }
309            }
310        }
311    }
Source

pub fn transform_rect_bbox(self, rect: Rect) -> Rect

Compute the bounding box of a transformed rectangle.

Returns the minimal Rect that encloses the given Rect after affine transformation. If the transform is axis-aligned, then this bounding box is “tight”, in other words the returned Rect is the transformed rectangle.

The returned rectangle always has non-negative width and height.

Examples found in repository?
examples/sub_window.rs (line 289)
274    fn paint(&mut self, ctx: &mut PaintCtx, _data: &(), env: &Env) {
275        let sz = ctx.size();
276
277        let monitors = Screen::get_monitors();
278        let all = monitors
279            .iter()
280            .map(|x| x.virtual_rect())
281            .fold(Rect::ZERO, |s, r| r.union(s));
282        if all.width() > 0. && all.height() > 0. {
283            let trans = Affine::scale(f64::min(sz.width / all.width(), sz.height / all.height()))
284                * Affine::translate(all.origin().to_vec2()).inverse();
285            let font = env.get(theme::UI_FONT).family;
286
287            for (i, mon) in monitors.iter().enumerate() {
288                let vr = mon.virtual_rect();
289                let tr = trans.transform_rect_bbox(vr);
290                ctx.stroke(tr, &Color::WHITE, 1.0);
291
292                if let Ok(tl) = ctx
293                    .text()
294                    .new_text_layout(format!(
295                        "{}:{}x{}@{},{}",
296                        i,
297                        vr.width(),
298                        vr.height(),
299                        vr.x0,
300                        vr.y0
301                    ))
302                    .max_width(tr.width() - 5.)
303                    .font(font.clone(), env.get(theme::TEXT_SIZE_NORMAL))
304                    .text_color(Color::WHITE)
305                    .build()
306                {
307                    ctx.draw_text(&tl, tr.center() - tl.size().to_vec2() * 0.5);
308                }
309            }
310        }
311    }
Source

pub fn is_finite(&self) -> bool

Is this map finite?

Source

pub fn is_nan(&self) -> bool

Is this map NaN?

Source

pub fn translation(self) -> Vec2

Returns the translation part of this affine map ((self.0[4], self.0[5])).

Source

pub fn with_translation(self, trans: Vec2) -> Affine

Replaces the translation portion of this affine map

The translation can be seen as being applied after the linear part of the map.

Trait Implementations§

Source§

impl Clone for Affine

Source§

fn clone(&self) -> Affine

Returns a duplicate 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 Data for Affine

Source§

fn same(&self, other: &Self) -> bool

Determine whether two values are the same. Read more
Source§

impl Debug for Affine

Source§

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

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

impl Default for Affine

Source§

fn default() -> Affine

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

impl From<TranslateScale> for Affine

Source§

fn from(ts: TranslateScale) -> Affine

Converts to this type from the input type.
Source§

impl<'a> Mul<&'a BezPath> for Affine

Source§

type Output = BezPath

The resulting type after applying the * operator.
Source§

fn mul(self, other: &BezPath) -> BezPath

Performs the * operation. Read more
Source§

impl Mul<Arc> for Affine

Source§

type Output = Arc

The resulting type after applying the * operator.
Source§

fn mul(self, arc: Arc) -> <Affine as Mul<Arc>>::Output

Performs the * operation. Read more
Source§

impl Mul<BezPath> for Affine

Source§

type Output = BezPath

The resulting type after applying the * operator.
Source§

fn mul(self, other: BezPath) -> BezPath

Performs the * operation. Read more
Source§

impl Mul<Circle> for Affine

Source§

type Output = Ellipse

The resulting type after applying the * operator.
Source§

fn mul(self, other: Circle) -> <Affine as Mul<Circle>>::Output

Performs the * operation. Read more
Source§

impl Mul<CubicBez> for Affine

Source§

type Output = CubicBez

The resulting type after applying the * operator.
Source§

fn mul(self, c: CubicBez) -> CubicBez

Performs the * operation. Read more
Source§

impl Mul<Ellipse> for Affine

Source§

type Output = Ellipse

The resulting type after applying the * operator.
Source§

fn mul(self, other: Ellipse) -> <Affine as Mul<Ellipse>>::Output

Performs the * operation. Read more
Source§

impl Mul<Line> for Affine

Source§

type Output = Line

The resulting type after applying the * operator.
Source§

fn mul(self, other: Line) -> Line

Performs the * operation. Read more
Source§

impl Mul<PathEl> for Affine

Source§

type Output = PathEl

The resulting type after applying the * operator.
Source§

fn mul(self, other: PathEl) -> PathEl

Performs the * operation. Read more
Source§

impl Mul<PathSeg> for Affine

Source§

type Output = PathSeg

The resulting type after applying the * operator.
Source§

fn mul(self, other: PathSeg) -> PathSeg

Performs the * operation. Read more
Source§

impl Mul<Point> for Affine

Source§

type Output = Point

The resulting type after applying the * operator.
Source§

fn mul(self, other: Point) -> Point

Performs the * operation. Read more
Source§

impl Mul<QuadBez> for Affine

Source§

type Output = QuadBez

The resulting type after applying the * operator.
Source§

fn mul(self, other: QuadBez) -> QuadBez

Performs the * operation. Read more
Source§

impl Mul for Affine

Source§

type Output = Affine

The resulting type after applying the * operator.
Source§

fn mul(self, other: Affine) -> Affine

Performs the * operation. Read more
Source§

impl MulAssign for Affine

Source§

fn mul_assign(&mut self, other: Affine)

Performs the *= operation. Read more
Source§

impl PartialEq for Affine

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Affine

Source§

impl StructuralPartialEq for Affine

Auto Trait Implementations§

§

impl Freeze for Affine

§

impl RefUnwindSafe for Affine

§

impl Send for Affine

§

impl Sync for Affine

§

impl Unpin for Affine

§

impl UnwindSafe for Affine

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> AnyEq for T
where T: Any + PartialEq,

Source§

fn equals(&self, other: &(dyn Any + 'static)) -> bool

Source§

fn as_any(&self) -> &(dyn Any + 'static)

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IsDefault for T
where T: Default + PartialEq + Copy,

Source§

fn is_default(&self) -> bool

Checks that type has a default value.
Source§

impl<T> RoundFrom<T> for T

Source§

fn round_from(x: T) -> T

Performs the conversion.
Source§

impl<T, U> RoundInto<U> for T
where U: RoundFrom<T>,

Source§

fn round_into(self) -> U

Performs the conversion.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

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>,

Source§

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>,

Source§

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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more