Files
ab_glyph_rasterizer
adler
adler32
andrew
bitflags
bytemuck
byteorder
calloop
cfg_if
color_quant
crc32fast
crossbeam_channel
crossbeam_deque
crossbeam_epoch
crossbeam_utils
deflate
dlib
downcast_rs
draw_state
either
event_loop
float
fnv
gfx
gfx_core
gfx_device_gl
gfx_gl
gfx_graphics
gfx_texture
gif
gl
glutin
glutin_egl_sys
glutin_glx_sys
glutin_window
graphics
graphics_api_version
image
input
instant
interpolation
iovec
jpeg_decoder
lazy_static
lazycell
libc
libloading
lock_api
log
maybe_uninit
memchr
memmap2
memoffset
miniz_oxide
mio
mio_extras
net2
nix
nom
num_cpus
num_integer
num_iter
num_rational
num_traits
once_cell
osmesa_sys
owned_ttf_parser
parking_lot
parking_lot_core
percent_encoding
piston
piston_window
png
proc_macro2
quote
raw_window_handle
rayon
rayon_core
read_color
rusttype
same_file
scoped_threadpool
scoped_tls
scopeguard
serde
serde_derive
shader_version
shaders_graphics2d
colored
textured
textured_color
shared_library
slab
smallvec
smithay_client_toolkit
spin_sleep
syn
texture
tiff
ttf_parser
unicode_xid
vecmath
viewport
walkdir
wayland_client
wayland_commons
wayland_cursor
wayland_egl
wayland_protocols
wayland_sys
weezl
window
winit
x11_dl
xcursor
xdg
xml
 1
 2
 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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#![deny(missing_docs)]

//! A library for storing viewport information

extern crate float;

use float::*;

/// Stores viewport information.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Viewport {
    /// Viewport in pixels.
    /// ```[x, y, width height]``` where ```(x, y)``` is lower left corner.
    pub rect: [i32; 4],
    /// The size of frame buffer in pixels.
    pub draw_size: [u32; 2],
    /// The size of window in points.
    pub window_size: [f64; 2],
}

impl Viewport {
    /// Computes absolute transform for 2D graphics,
    /// which uses a row major 2x3 matrix.
    ////
    /// The origin is in the upper left corner of the viewport rectangle.
    /// The x axis points to the right, and the y axis points down.
    /// The units are in points (window coordinates).
    ///
    /// It is assumed that the underlying coordinate system is normalized
    /// with the origin in the center, such that ```(-1.0, 1.0)``` in the
    /// underlying coordinate system corresponds to the
    /// upper left corner of the viewport.
    pub fn abs_transform<T: Float>(&self) -> [[T; 3]; 2] {
        let (dw, dh) = (self.draw_size[0] as f64, self.draw_size[1] as f64);
        let sx = 2.0 * (dw / self.window_size[0]) / self.rect[2] as f64;
        let sy = -2.0 * (dh / self.window_size[1]) / self.rect[3] as f64;
        let f = |x| FromPrimitive::from_f64(x);
        [
            [f(sx), f(0.0), f(-1.0)],
            [f(0.0), f(sy), f(1.0)]
        ]
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn abs() {
        let transform = |mat: [[f64; 3]; 2], (px, py)| -> (f64, f64) {
            (mat[0][0] * px + mat[0][1] * py + mat[0][2],
            mat[1][0] * px + mat[1][1] * py + mat[1][2])
         };

        let viewport = Viewport {
            rect: [0, 0, 100, 200],
            draw_size: [100, 200],
            window_size: [100.0, 200.0],
        };
        let abs = viewport.abs_transform();
        assert_eq!(abs, [
                [0.02, 0.0, -1.0],
                [0.0, -0.01, 1.0]
            ]);
        assert_eq!(transform(abs, (0.0, 0.0)), (-1.0, 1.0));
        assert_eq!(transform(abs, (50.0, 100.0)), (0.0, 0.0));
        assert_eq!(transform(abs, (100.0, 200.0)), (1.0, -1.0));

        let viewport = Viewport {
            rect: [10, 10, 80, 80],
            draw_size: [100, 100],
            window_size: [50.0, 50.0],
        };
        let abs = viewport.abs_transform();
        assert_eq!(abs, [
                [0.05, 0.0, -1.0],
                [0.0, -0.05, 1.0]
            ]);
        assert_eq!(transform(abs, (0.0, 0.0)), (-1.0, 1.0));
        // The viewport size is 80 pixels, 40 points, therefore center is 20.
        assert_eq!(transform(abs, (20.0, 20.0)), (0.0, 0.0));
        assert_eq!(transform(abs, (40.0, 40.0)), (1.0, -1.0));
    }
}