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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::rc::Rc;
use image::*;

pub mod pages;
pub mod paths;
pub mod images_map;
pub mod letter;
pub mod word;
pub mod line;

pub use pages::PageProps;
pub use images_map::ImagesMap;
pub use letter::Letter;
pub use word::Word;
pub use line::Line;


pub static CHARS_ONLY_UPPER : [char; 32] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '?', '!', ',', '.', ';', ':'];

pub static CHARS_UNDER : [char; 6] = ['g', 'j', 'p', 'q', 'y', ','];

pub static CHARS : [char; 58] = ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h', 'I', 'i', 'J', 'j', 'K', 'k', 'L', 'l', 'M', 'm', 'N', 'n', 'O', 'o', 'P', 'p', 'Q', 'q', 'R', 'r', 'S', 's', 'T', 't', 'U', 'u', 'V', 'v', 'W', 'w', 'X', 'x', 'Y', 'y', 'Z', 'z', '?', '!', ',', '.', ';', ':'];

pub struct Text<'a> {
    raw: String,
    lines: Vec<Line<'a>>,
    page_props: &'a PageProps<'a>,
    imgs_map: Rc<ImagesMap<'a>>,
}

impl<'a> Text<'a> {
    pub fn new(page_props : &'a PageProps) -> Text<'a> {
        Text {
            raw: String::new(),
            page_props,
            lines: Vec::new(),
            imgs_map: Rc::new(ImagesMap::new(page_props))
        }
    }

    pub fn new_with_map(page_props : &'a PageProps, imgs_map : Rc<ImagesMap<'a>>) -> Text<'a> {
        Text {
            raw: String::new(),
            page_props,
            lines: Vec::new(),
            imgs_map,
        }
    }

    pub fn new_with_dic_name(page_props : &'a PageProps, dic_name: &'a str) -> Text<'a> {
        Text {
            raw: String::new(),
            page_props,
            lines: Vec::new(),
            imgs_map: Rc::new(ImagesMap::new_with_dic_name(page_props, dic_name))
        }
    }

    pub fn push_word(&mut self, s_word : &str) {
        match self.lines.last_mut() {
            Some(actual_line) => {
                let word = Word::new(s_word, self.page_props, Rc::clone(&self.imgs_map));

                if actual_line.width + word.width + self.page_props.space_width > self.page_props.line_max_width() {
                    self.lines.push(Line::new(self.page_props, Rc::clone(&self.imgs_map)));
                    self.push_word(s_word);
                } else {
                    actual_line.push(word);
                }
            },
            None => {
                self.lines.push(Line::new(self.page_props, Rc::clone(&self.imgs_map)));
                self.push_word(s_word);
            }
        }
    }

    pub fn imgs_map(&self) -> &ImagesMap {
        &self.imgs_map
    }

    pub fn parse(&mut self, string: String) {
        for s_word in string.split(' ') {
            self.push_word(s_word);
        }

        self.raw = string;
    }

    pub fn parse_str(&mut self, str : &str) {
        self.parse(String::from(str));
    }

    pub fn print(&self) {
        for line in &self.lines {
            for word in &line.words {
                print!("{} ", word.get_raw());
            }
            println!();
        }
    }

    pub fn to_img(&mut self) -> Vec<RgbaImage> {
        let mut pages = Vec::new();

        let mut page = self.page_props.white_page();

        let mut y = self.page_props.margins;
        for line in self.lines.iter_mut() {
            let mut x = self.page_props.margins;
            for word in line.words.iter_mut() {
                for letter in word.letters.iter_mut() {
                    let l_img = &*letter.img();
                    imageops::overlay(&mut page, l_img, x as u32, y as u32);
                    x += letter.width();
                }

                x += self.page_props.space_width;
            }

            y += self.page_props.line_height;

            if y + self.page_props.line_height >= self.page_props.canvas.height as f32 - self.page_props.margins {
                pages.push(page);
                page = self.page_props.white_page();
                y = self.page_props.margins;
            }

        }

        pages.push(page);
        pages
    }

    pub fn to_files(&mut self, files_name : Option<&str>) {
        let images = self.to_img();

        match std::fs::create_dir(paths::output_dir()) {
            Ok(_) => (),
            Err(_) => ()
        };

        for (i, img) in images.iter().enumerate() {
            img.save(paths::page_path(i + 1, files_name)).unwrap();
        }
    }

    pub fn parse_to_png(&mut self, str : &str, files_name : Option<&str>) {
        self.parse_str(str);
        self.to_files(files_name);
    }
}