pub struct Affine(/* private fields */);Expand description
A 2D affine transform.
Implementations§
Source§impl Affine
impl Affine
Sourcepub const FLIP_Y: Affine
pub const FLIP_Y: Affine
A transform that is flipped on the y-axis. Useful for converting between y-up and y-down spaces.
Sourcepub const fn new(c: [f64; 6]) -> Affine
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.
Sourcepub const fn scale(s: f64) -> Affine
pub const fn scale(s: f64) -> Affine
An affine transform representing uniform scaling.
Examples found in repository?
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 }Sourcepub const fn scale_non_uniform(s_x: f64, s_y: f64) -> Affine
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
Sourcepub fn rotate(th: f64) -> Affine
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?
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 }Sourcepub fn rotate_about(th: f64, center: Point) -> Affine
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.
Sourcepub fn translate<V>(p: V) -> Affine
pub fn translate<V>(p: V) -> Affine
An affine transform representing translation.
Examples found in repository?
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 }Sourcepub fn skew(skew_x: f64, skew_y: f64) -> Affine
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);Sourcepub fn pre_rotate(self, th: f64) -> Affine
pub fn pre_rotate(self, th: f64) -> Affine
A rotation by th followed by self.
Equivalent to self * Affine::rotate(th)
Sourcepub fn pre_rotate_about(self, th: f64, center: Point) -> Affine
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)
Sourcepub fn pre_scale(self, scale: f64) -> Affine
pub fn pre_scale(self, scale: f64) -> Affine
A scale by scale followed by self.
Equivalent to self * Affine::scale(scale)
Sourcepub fn pre_scale_non_uniform(self, scale_x: f64, scale_y: f64) -> Affine
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)
Sourcepub fn pre_translate(self, trans: Vec2) -> Affine
pub fn pre_translate(self, trans: Vec2) -> Affine
A translation of trans followed by self.
Equivalent to self * Affine::translate(trans)
Sourcepub fn then_rotate(self, th: f64) -> Affine
pub fn then_rotate(self, th: f64) -> Affine
self followed by a rotation of th.
Equivalent to Affine::rotate(th) * self
Sourcepub fn then_rotate_about(self, th: f64, center: Point) -> Affine
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
Sourcepub fn then_scale(self, scale: f64) -> Affine
pub fn then_scale(self, scale: f64) -> Affine
self followed by a scale of scale.
Equivalent to Affine::scale(scale) * self
Sourcepub fn then_scale_non_uniform(self, scale_x: f64, scale_y: f64) -> Affine
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
Sourcepub fn then_translate(self, trans: Vec2) -> Affine
pub fn then_translate(self, trans: Vec2) -> Affine
self followed by a translation of trans.
Equivalent to Affine::translate(trans) * self
Sourcepub fn map_unit_square(rect: Rect) -> Affine
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.
Sourcepub fn determinant(self) -> f64
pub fn determinant(self) -> f64
Compute the determinant of this transform.
Sourcepub fn inverse(self) -> Affine
pub fn inverse(self) -> Affine
Compute the inverse transform.
Produces NaN values when the determinant is zero.
Examples found in repository?
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 }Sourcepub fn transform_rect_bbox(self, rect: Rect) -> Rect
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?
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 }Sourcepub fn translation(self) -> Vec2
pub fn translation(self) -> Vec2
Returns the translation part of this affine map ((self.0[4], self.0[5])).
Sourcepub fn with_translation(self, trans: Vec2) -> Affine
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 From<TranslateScale> for Affine
impl From<TranslateScale> for Affine
Source§fn from(ts: TranslateScale) -> Affine
fn from(ts: TranslateScale) -> Affine
Source§impl MulAssign for Affine
impl MulAssign for Affine
Source§fn mul_assign(&mut self, other: Affine)
fn mul_assign(&mut self, other: Affine)
*= operation. Read more