1use self::ft::{
9 bitmap::PixelMode,
10 face::{Face, LoadFlag},
11 library::Library,
12};
13use super::Vector;
14use rect::Rect;
15use std::{collections::HashMap, error::Error, fmt};
16use texture::{RgbMode, Texture};
17
18extern crate freetype as ft;
19
20static SIZE: u32 = 10;
21
22type FontMap = HashMap<u32, GlyphMap>;
24
25type Utf8Map = HashMap<u32, CharInfo>;
27
28#[derive(Debug)]
29struct GlyphMap {
41 pub texture: Texture,
42 pub rows: Vec<Row>,
43 pub map: Utf8Map,
44}
45
46#[derive(Debug, Clone)]
47struct Row {
48 pub width: u32,
49 pub height: u32,
50 pub pos: u32,
51}
52
53impl Row {
54 pub fn new(height: u32, pos: u32) -> Row {
55 Row {
56 width: 0,
57 height,
58 pos,
59 }
60 }
61}
62
63impl GlyphMap {
65 pub fn new() -> GlyphMap {
67 let mut data: Vec<u8> = vec![255; 128 * 128 * 4];
68 for elem in data.chunks_mut(4) {
69 elem[3] = 0
70 }
71
72 GlyphMap {
73 texture: Texture::from_slice(data.as_mut_slice(), RgbMode::RGBA, 128, 128),
74 rows: Vec::with_capacity(1),
75 map: Utf8Map::with_capacity(10),
76 }
77 }
78
79 pub fn get_texture_rect(&mut self, width: u32, height: u32) -> Rect<u32> {
83 let mut ret: Option<Rect<u32>> = None;
84 for mut row in self.rows.iter_mut() {
86 if (row.width + width > self.texture.width()) || (row.height < height) {
87 continue;
88 }
89 ret = Some(Rect::new(row.width, row.pos, width, height));
90 row.width += width + 1;
91 }
92
93 if let Some(rect) = ret {
94 rect
96 } else {
97 let last_pos = self.rows.iter().map(|x| x.height).sum();
99
100 while last_pos + (height + height / 10) > self.texture.height()
102 || width > self.texture.width()
103 {
104 let mut new = Texture::from_size(Vector::new(
105 self.texture.width() * 2,
106 self.texture.height() * 2,
107 ));
108 new.update_from_texture(&self.texture, Vector::new(0, 0))
109 .unwrap();
110 self.texture = new;
111 }
112 let mut new_row = Row::new(height + height / 10, last_pos);
113 let new_ret = Rect::new(new_row.width, last_pos, width, height + height / 10);
114 new_row.width += width + 1;
115 self.rows.push(new_row);
116 new_ret
117 }
118 }
119
120 pub fn update_texture(&mut self, char_info: &CharInfo, data: &[u8]) -> Result<(), Box<Error>> {
122 self.texture.update_block(
123 data,
124 Vector::new(char_info.tex_coord.width, char_info.tex_coord.height),
125 Vector::new(char_info.tex_coord.left, char_info.tex_coord.top),
126 RgbMode::RGBA,
127 )?;
128 Ok(())
129 }
130}
131
132#[derive(Debug, Default)]
133pub struct CharInfo {
142 pub rect: Rect<f32>,
143 pub tex_coord: Rect<u32>,
144 pub advance: f32,
145}
146
147impl CharInfo {
148 pub fn new() -> CharInfo {
150 CharInfo {
151 rect: Default::default(),
152 tex_coord: Default::default(),
153 advance: 0.0,
154 }
155 }
156
157 pub fn from_data(rect: Rect<f32>, tex_coord: Rect<u32>, advance: f32) -> CharInfo {
159 CharInfo {
160 rect,
161 tex_coord,
162 advance,
163 }
164 }
165}
166
167pub struct Font {
171 face: Face,
172 lib: Library,
173 map: FontMap,
174}
175
176impl fmt::Display for Font {
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178 write!(f, "Face: {:?}", self.face)
179 }
180}
181
182impl fmt::Debug for Font {
183 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184 write!(f, "Face: {:?}", self.face)
185 }
186}
187
188impl Font {
189 pub fn from_path(path: &str) -> Option<Font> {
191 let lib = Library::init().unwrap();
192 match lib.new_face(path, 0) {
193 Err(err) => {
194 println!("Font loading error: {}", err);
195 None
196 }
197 Ok(face) => {
198 face.set_pixel_sizes(0, 30).unwrap();
199 Some(Font {
200 face,
201 lib,
202 map: FontMap::with_capacity(1),
203 })
204 }
205 }
206 }
207
208 pub fn glyph_exist(&mut self, size: u32, code: u32) -> bool {
210 if let Some(ref mut map_size) = self.map.get(&size) {
211 if let Some(ref mut _char_info) = map_size.map.get(&code) {
212 return true;
213 }
214 }
215 false
216 }
217
218 fn get_map_mut(&mut self) -> &mut FontMap {
220 &mut self.map
221 }
222
223 fn create_glyph<'a>(&'a mut self, size: u32, code: u32) -> Result<&'a CharInfo, Box<Error>> {
226 {
227 let glyph_map = self.map.entry(size).or_insert_with(GlyphMap::new);
229
230 self.face.load_char(code as usize, LoadFlag::RENDER)?;
232
233 let metrics = self.face.glyph().metrics();
234 let bitmap = self.face.glyph().bitmap();
235 let height = bitmap.rows();
238 let width = bitmap.width();
239
240 let mut to_insert = CharInfo::new();
242 to_insert.rect.left = metrics.horiBearingX as f32 / (1 << 6) as f32;
243 to_insert.rect.top = -metrics.horiBearingY as f32 / (1 << 6) as f32;
244 to_insert.rect.width = metrics.width as f32 / (1 << 6) as f32;
245 to_insert.rect.height = metrics.height as f32 / (1 << 6) as f32;
246 to_insert.advance = (metrics.horiAdvance + 2) as f32 / (1 << 6) as f32;
247
248 to_insert.tex_coord = glyph_map.get_texture_rect(width as u32, height as u32);
250
251 let mut data = vec![255; (height * width * 4) as usize];
253 for elem in &mut data.chunks_mut(4) {
254 elem[3] = 0;
255 }
256
257 let pixels: Vec<u8> = Vec::from(bitmap.buffer());
259 let mut offset = 0;
260 match bitmap.pixel_mode().unwrap() {
261 PixelMode::None => {
262 panic!("Error while creating glyph");
263 }
264 PixelMode::Mono => {
265 for y in 0..height {
267 for x in 0..width {
268 let index = ((x + y * width) * 4 + 3) as usize;
269 let pix = pixels[(offset + (x / 8)) as usize];
270
271 data[index] = if (pix & (1 << (7 - (x % 8)))) != 0 {
272 255
273 } else {
274 0
275 };
276 }
277 offset += bitmap.pitch();
278 }
279 }
280 _ => {
281 for y in 0..height {
283 for x in 0..width {
284 let index = ((x + y * width) * 4 + 3) as usize;
285 let pix = pixels[(offset + x) as usize];
286
287 data[index] = pix;
288 }
289 offset += bitmap.pitch();
290 }
291 }
292 }
293
294 glyph_map.update_texture(&to_insert, data.as_slice())?;
296
297 glyph_map.map.insert(code, to_insert);
299 }
300
301 Ok(&self.get_map_mut()[&size].map[&code])
303 }
304
305 pub fn glyph(&mut self, size: u32, code: u32) -> &CharInfo {
309 let glyph_exist: bool = self.glyph_exist(size, code);
310
311 if glyph_exist {
312 &self.map[&size].map[&code]
313 } else {
314 self.create_glyph(size, code).unwrap()
315 }
316 }
317
318 pub fn texture(&self, font_size: u32) -> Result<&Texture, TextError> {
319 if let Some(t) = &self.map.get(&font_size) {
320 Ok(&t.texture)
321 } else {
322 Err(TextError::NoTexture)
323 }
324 }
325}
326
327#[derive(Debug)]
328pub enum TextError {
329 NoTexture,
330}
331
332impl fmt::Display for TextError {
333 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
334 match self {
335 TextError::NoTexture => write!(f, "No texture try updating before."),
336 }
337 }
338}
339
340impl Error for TextError {
341 fn cause(&self) -> Option<&Error> {
342 match self {
343 TextError::NoTexture => None,
344 }
345 }
346}