diff options
-rw-r--r-- | res/text.f.glsl | 23 | ||||
-rw-r--r-- | src/grid.rs | 8 | ||||
-rw-r--r-- | src/main.rs | 45 | ||||
-rw-r--r-- | src/renderer/mod.rs | 18 | ||||
-rw-r--r-- | src/text.rs | 21 |
5 files changed, 93 insertions, 22 deletions
diff --git a/res/text.f.glsl b/res/text.f.glsl index ce9dd41e..7e80a11c 100644 --- a/res/text.f.glsl +++ b/res/text.f.glsl @@ -3,9 +3,28 @@ in vec2 TexCoords; uniform sampler2D mask; uniform vec3 textColor; +uniform vec3 bgColor; + +// SRC = SRC_ALPHA; DST = 1 - SRC_ALPHA +void MyBlend(in vec3 srcValue, + in vec3 dstValue, + in vec3 srcAlpha, + out vec3 blended) +{ + vec3 dstAlpha = vec3(1.0, 1.0, 1.0) - srcAlpha; + vec3 preBlended = (srcValue * srcAlpha + dstValue * dstAlpha); + + blended = vec3(min(1.0, preBlended.x), + min(1.0, preBlended.y), + min(1.0, preBlended.z)); +} void main() { - vec4 sampled = vec4(1.0, 1.0, 1.0, texture(mask, TexCoords).r); - gl_FragColor = vec4(textColor, 1.0) * sampled; + // vec4 red = vec4(sampled.rgb, sampled.r * sampled.g * sampled.b); + // vec4 sampled = vec4(1.0, 1.0, 1.0, texture(mask, TexCoords)); + vec3 blended = vec3(1.0, 1.0, 1.0); + MyBlend(textColor, bgColor, texture(mask, TexCoords).rgb, blended); + + gl_FragColor = vec4(blended, 1.0); } diff --git a/src/grid.rs b/src/grid.rs index 93d9cd28..0418ed53 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -26,7 +26,7 @@ pub struct Grid { raw: Vec<Row>, /// Number of columns - _cols: usize, + cols: usize, /// Number of rows. /// @@ -43,7 +43,7 @@ impl Grid { Grid { raw: raw, - _cols: cols, + cols: cols, rows: rows, } } @@ -51,6 +51,10 @@ impl Grid { pub fn rows(&self) -> usize { self.rows } + + pub fn cols(&self) -> usize { + self.cols + } } impl Index<usize> for Grid { diff --git a/src/main.rs b/src/main.rs index 1845bb94..48aaf11b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,7 @@ use grid::Grid; static INIT_LIST: &'static str = "abcdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\ 01234567890\ - ~`!@#$%^&*()[]{}-_=+\\|\"/?.,<>"; + ~`!@#$%^&*()[]{}-_=+\\|\"/?.,<>;:"; fn main() { let window = glutin::Window::new().unwrap(); @@ -37,12 +37,12 @@ fn main() { let (dpi_x, dpi_y) = window.get_dpi().unwrap(); let dpr = window.hidpi_factor(); - let font_size = 12.0; + let font_size = 11.0; let sep_x = 2; - let sep_y = 2; + let sep_y = 5; - let desc = FontDesc::new("Ubuntu Mono", "Regular"); + let desc = FontDesc::new("DejaVu Sans Mono", "Book"); let mut rasterizer = text::Rasterizer::new(dpi_x, dpi_y, dpr); let (cell_width, cell_height) = rasterizer.box_size_for_font(&desc, font_size); @@ -54,10 +54,35 @@ fn main() { let mut grid = Grid::new(num_rows as usize, num_cols as usize); - grid[0][0] = grid::Cell::new(Some(String::from("R"))); - grid[0][1] = grid::Cell::new(Some(String::from("u"))); - grid[0][2] = grid::Cell::new(Some(String::from("s"))); - grid[0][3] = grid::Cell::new(Some(String::from("t"))); + // let contents = [ + // "for (row, line) in contents.iter().enumerate() {", + // " for (i, c) in line.chars().enumerate() {", + // " grid[row][i] = grid::Cell::new(Some(c.escape_default().collect()));", + // " }", + // "}"]; + + let contents = include_str!("grid.rs"); + let mut row = 0usize; + let mut col = 0; + + for (i, c) in contents.chars().enumerate() { + if c == '\n' { + row += 1; + col = 0; + continue; + } + + if row >= (num_rows as usize) { + break; + } + + if col >= grid.cols() { + continue; + } + + grid[row][col] = grid::Cell::new(Some(c.escape_default().collect())); + col += 1; + } let mut glyph_cache = HashMap::new(); for c in INIT_LIST.chars() { @@ -67,8 +92,8 @@ fn main() { } unsafe { - gl::Enable(gl::BLEND); - gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); + // gl::Enable(gl::BLEND); + // gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); gl::Enable(gl::MULTISAMPLE); } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index b84ed1ee..001cb40f 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -97,6 +97,7 @@ impl QuadRenderer { unsafe { // set color gl::Uniform3f(self.program.u_color, 1., 1., 0.5); + gl::Uniform3f(self.program.u_bg_color, 0.08, 0.08, 0.08); } let rect = get_rect(glyph, x, y); @@ -134,7 +135,7 @@ impl QuadRenderer { fn get_rect(glyph: &Glyph, x: f32, y: f32) -> Rect<f32> { Rect::new( - Point2D::new(x, y), + Point2D::new(x + glyph.left as f32, y - (glyph.height - glyph.top) as f32), Size2D::new(glyph.width as f32, glyph.height as f32) ) } @@ -152,6 +153,8 @@ pub struct ShaderProgram { u_projection: GLint, /// color uniform u_color: GLint, + /// background color uniform + u_bg_color: GLint, } impl ShaderProgram { @@ -180,11 +183,13 @@ impl ShaderProgram { // get uniform locations let projection_str = CString::new("projection").unwrap(); let color_str = CString::new("textColor").unwrap(); + let bg_color_str = CString::new("bgColor").unwrap(); - let (projection, color) = unsafe { + let (projection, color, bg_color) = unsafe { ( gl::GetUniformLocation(program, projection_str.as_ptr()), - gl::GetUniformLocation(program, color_str.as_ptr()) + gl::GetUniformLocation(program, color_str.as_ptr()), + gl::GetUniformLocation(program, bg_color_str.as_ptr()), ) }; @@ -192,11 +197,14 @@ impl ShaderProgram { assert!(projection != gl::INVALID_OPERATION as i32); assert!(color != gl::INVALID_VALUE as i32); assert!(color != gl::INVALID_OPERATION as i32); + assert!(bg_color != gl::INVALID_VALUE as i32); + assert!(bg_color != gl::INVALID_OPERATION as i32); let shader = ShaderProgram { id: program, u_projection: projection, u_color: color, + u_bg_color: bg_color, }; // set projection uniform @@ -287,11 +295,11 @@ impl Glyph { gl::TexImage2D( gl::TEXTURE_2D, 0, - gl::RED as i32, + gl::RGB as i32, rasterized.width as i32, rasterized.height as i32, 0, - gl::RED, + gl::RGB, gl::UNSIGNED_BYTE, rasterized.buf.as_ptr() as *const _ ); diff --git a/src/text.rs b/src/text.rs index ea0df76a..ca414342 100644 --- a/src/text.rs +++ b/src/text.rs @@ -87,15 +87,30 @@ impl Rasterizer { pub fn get_glyph(&mut self, desc: &FontDesc, size: f32, c: char) -> RasterizedGlyph { let face = self.get_face(desc).expect("TODO handle get_face error"); face.set_char_size(to_freetype_26_6(size * self.dpr), 0, self.dpi_x, self.dpi_y).unwrap(); - face.load_char(c as usize, freetype::face::RENDER).unwrap(); + face.load_char(c as usize, freetype::face::TARGET_LIGHT).unwrap(); let glyph = face.glyph(); + glyph.render_glyph(freetype::render_mode::RenderMode::Lcd).unwrap(); + + // FIXME need LCD filtering to reduce color fringes with subpixel rendering. The freetype + // bindings don't currently expose this! + + let bitmap = glyph.bitmap(); + let buf = bitmap.buffer(); + let pitch = bitmap.pitch() as usize; + + let mut packed = Vec::with_capacity((bitmap.rows() * bitmap.width()) as usize); + for i in 0..bitmap.rows() { + let start = (i as usize) * pitch; + let stop = start + bitmap.width() as usize; + packed.extend_from_slice(&buf[start..stop]); + } RasterizedGlyph { top: glyph.bitmap_top() as usize, left: glyph.bitmap_left() as usize, - width: glyph.bitmap().width() as usize, + width: glyph.bitmap().width() as usize / 3, height: glyph.bitmap().rows() as usize, - buf: glyph.bitmap().buffer().to_vec(), + buf: packed, } } } |