      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
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134

    //! Andrew is a crate for drawing objects
    #![warn(missing_docs)]
    extern crate line_drawing;
    extern crate rusttype;
    extern crate walkdir;
    extern crate xdg;
    extern crate xml;

    #[macro_use]
    extern crate bitflags;

    /// A module that contains functions and objects relating to lines
    pub mod line;
    /// A module that contains functions and objects relating to shapes
    pub mod shapes;
    /// A module that contains functions and objects relating to text
    pub mod text;

    /// The Drawable trait allows object to be drawn to a buffer or canvas
    pub trait Drawable {
        /// A function that draws the object to a canvas
        fn draw(&self, canvas: &mut Canvas);
    }

    /// Describes an endianness (aka byte order)
    #[derive(Debug, PartialEq)]
    pub enum Endian {
        /// Little Endian
        Little,
        /// Big Endian
        Big,
    }

    impl Endian {
        /// Returns the native endianness
        pub fn native() -> Endian {
            if cfg!(target_endian = "little") {
                Endian::Little
            } else {
                Endian::Big
            }
        }
    }

    /// The canvas object acts as a wrapper around a buffer, providing information and functions
    /// for drawing
    pub struct Canvas<'a> {
        /// A buffer for the canvas to draw to
        pub buffer: &'a mut [u8],
        /// The width in pixels of the canvas
        pub width: usize,
        /// The height in pixels of the canvas
        pub height: usize,
        /// The number of bytes between each line of pixels on the canvas
        pub stride: usize,
        /// The number of bytes contained in each pixel
        pub pixel_size: usize,
        /// The endianness of the canvas
        pub endianness: Endian,
    }

    impl<'a> Canvas<'a> {
        /// Creates a new canvas object
        pub fn new(
            buffer: &'a mut [u8],
            width: usize,
            height: usize,
            stride: usize,
            endianness: Endian,
        ) -> Canvas<'a> {
            assert!(
                stride % width == 0,
                "Incorrect Dimensions - Stride is not a multiple of width"
            );
            assert!(buffer.len() == stride * height);
            let pixel_size = stride / width;
            Canvas {
                buffer,
                width,
                height,
                stride,
                pixel_size,
                endianness,
            }
        }

        /// Draws an object that implements the Drawable trait to the buffer
        pub fn draw<D: Drawable>(&mut self, drawable: &D) {
            drawable.draw(self);
        }

        /// Draws a pixel at the x and y coordinate
        pub fn draw_point(&mut self, x: usize, y: usize, color: [u8; 4]) {
            let base = self.stride * y + self.pixel_size * x;
            if self.endianness == Endian::Little {
                if color[0] == 255 {
                    self.buffer[base + 3] = color[0];
                    self.buffer[base + 2] = color[1];
                    self.buffer[base + 1] = color[2];
                    self.buffer[base] = color[3];
                } else {
                    for c in 0..3 {
                        let alpha = f32::from(color[0]) / 255.0;
                        let color_diff =
                            (color[3 - c] as isize - self.buffer[base + c] as isize) as f32 * alpha;
                        let new_color = (f32::from(self.buffer[base + c]) + color_diff) as u8;
                        self.buffer[base + c] = new_color as u8;
                    }
                    self.buffer[base + 3] = 255 as u8;
                }
            } else if color[0] == 255 {
                self.buffer[base] = color[0];
                self.buffer[base + 1] = color[1];
                self.buffer[base + 2] = color[2];
                self.buffer[base + 3] = color[3];
            } else {
                for c in 1..4 {
                    let alpha = f32::from(color[0]) / 255.0;
                    let color_diff =
                        (color[c] as isize - self.buffer[base + c] as isize) as f32 * alpha;
                    let new_color = (f32::from(self.buffer[base + c]) + color_diff) as u8;
                    self.buffer[base + c] = new_color as u8;
                }
                self.buffer[base] = 255 as u8;
            }
        }

        /// Clears the entire canvas buffer by zeroing it
        pub fn clear(&mut self) {
            for i in 0..self.width * self.height * 4 {
                self.buffer[i] = 0x00;
            }
        }
    }

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g., `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g., `str,u8` or `String,struct:Vec,test`)