      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

    /// A module that contains functions and objects relating to fontconfig
    pub mod fontconfig;

    use rusttype::{point, Font, Scale, SharedBytes, VMetrics};
    use std::fs::File;
    use std::io::Read;
    use std::path::PathBuf;
    use Canvas;
    use Drawable;

    /// A drawable object that represents text
    pub struct Text<'a> {
        /// The position of the text on the canvas
        pub pos: (usize, usize),
        /// The color of the text
        pub color: [u8; 4],
        /// The text that is rendered to the canvas on draw
        pub text: String,
        /// The font used in rendering the text
        pub font: Font<'a>,
        /// The scale that is applied to the text
        pub scale: Scale,
        /// The vertical metrics of the text
        pub v_metrics: VMetrics,
    }

    /// Loads a font file into a `Vec<u8>`
    pub fn load_font_file<P: Into<PathBuf>>(path: P) -> Vec<u8> {
        let mut data: Vec<u8> = Vec::new();
        let mut file = File::open(path.into()).expect("Could not open font file");
        file.read_to_end(&mut data)
            .expect("Could not read font file");
        data
    }

    impl<'a> Text<'a> {
        /// Creates a new Text object
        pub fn new<P: Into<SharedBytes<'a>>, T: Into<String>>(
            pos: (usize, usize),
            color: [u8; 4],
            font_data: P,
            height: f32,
            width_scale: f32,
            text: T,
        ) -> Text<'a> {
            let text = text.into();
            // Create font
            let font = Font::from_bytes(font_data).expect("Error constructing Font");
            // Create scale
            let scale = Scale {
                x: height * width_scale,
                y: height,
            };
            // Create needed metrics
            let v_metrics = font.v_metrics(scale);
            Text {
                pos,
                color,
                text: text.clone(),
                scale,
                v_metrics,
                font,
            }
        }

        fn draw_text(&self, canvas: &mut Canvas) {
            let glyphs: Vec<_> = self
                .font
                .layout(&self.text, self.scale, point(0.0, self.v_metrics.ascent))
                .collect();
            for glyph in glyphs {
                if let Some(bounding_box) = glyph.pixel_bounding_box() {
                    glyph.draw(|x, y, v| {
                        let x = ((x as usize + self.pos.0) as i32 + bounding_box.min.x) as usize;
                        let y = ((y as usize + self.pos.1) as i32 + bounding_box.min.y) as usize;

                        if x < canvas.width && y < canvas.height {
                            let mut color = self.color;
                            color[0] = (f32::from(color[0]) * v) as u8;
                            canvas.draw_point(x, y, color);
                        }
                    });
                }
            }
        }

        /// Calculates the width in pixels of the text
        pub fn get_width(&self) -> usize {
            let glyphs: Vec<_> = self
                .font
                .layout(&self.text, self.scale, point(0.0, self.v_metrics.ascent))
                .collect();
            let min_x = glyphs
                .first()
                .map(|g| {
                    if let Some(bb) = g.pixel_bounding_box() {
                        bb.min.x
                    } else {
                        g.position().x as i32
                    }
                })
                .unwrap_or(0);
            let max_x = glyphs
                .last()
                .map(|g| {
                    if let Some(bb) = g.pixel_bounding_box() {
                        bb.max.x
                    } else {
                        (g.position().x + g.unpositioned().h_metrics().advance_width) as i32
                    }
                })
                .unwrap_or(0);
            (max_x - min_x) as usize
        }
    }

    impl<'a> Drawable for Text<'a> {
        fn draw(&self, canvas: &mut Canvas) {
            self.draw_text(canvas);
        }
    }

# 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`)