From 77f2d6e853f1ad54e6dc844a811b78daeb463e76 Mon Sep 17 00:00:00 2001 From: lbonn Date: Tue, 12 May 2020 15:23:35 +0200 Subject: [PATCH] Fix emojis being blended with background Fixes #1864. --- CHANGELOG.md | 1 + alacritty/src/renderer/mod.rs | 30 +++++++++++++++++++----------- font/src/darwin/mod.rs | 4 ++-- font/src/lib.rs | 3 +++ res/text.f.glsl | 21 ++++++++++++++++++--- res/text.v.glsl | 15 ++++++++++----- 6 files changed, 53 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 440b07ac..ce8b7a47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Resize lag on launch under some X11 wms - Increased input latency due to vsync behavior on X11 - Freeze when application is invisible on Wayland +- Emoji colors blending with terminal background ## 0.4.2 diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index 2be68892..296e4169 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -418,6 +418,8 @@ struct InstanceData { bg_g: f32, bg_b: f32, bg_a: f32, + // Flag indicating that glyph uses multiple colors, like an Emoji. + multicolor: u8, } #[derive(Debug)] @@ -465,19 +467,11 @@ impl Batch { Self { tex: 0, instances: Vec::with_capacity(BATCH_MAX) } } - pub fn add_item(&mut self, mut cell: RenderableCell, glyph: &Glyph) { + pub fn add_item(&mut self, cell: RenderableCell, glyph: &Glyph) { if self.is_empty() { self.tex = glyph.tex_id; } - if glyph.colored { - // XXX Temporary workaround to prevent emojis being rendered with a wrong colors on, at - // least, dark backgrounds. For more info see #1864. - cell.fg.r = 255; - cell.fg.g = 255; - cell.fg.b = 255; - } - self.instances.push(InstanceData { col: cell.column.0 as f32, row: cell.line.0 as f32, @@ -500,6 +494,7 @@ impl Batch { bg_g: f32::from(cell.bg.g), bg_b: f32::from(cell.bg.b), bg_a: cell.bg_alpha, + multicolor: glyph.colored as u8, }); } @@ -643,6 +638,17 @@ impl QuadRenderer { ); gl::EnableVertexAttribArray(4); gl::VertexAttribDivisor(4, 1); + // Multicolor flag. + gl::VertexAttribPointer( + 5, + 1, + gl::BYTE, + gl::FALSE, + size_of::() as i32, + (17 * size_of::()) as *const _, + ); + gl::EnableVertexAttribArray(5); + gl::VertexAttribDivisor(5, 1); // Rectangle setup. gl::GenVertexArrays(1, &mut rect_vao); @@ -1513,14 +1519,16 @@ impl Atlas { gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1); gl::GenTextures(1, &mut id); gl::BindTexture(gl::TEXTURE_2D, id); + // Use RGBA texture for both normal and emoji glyphs, since it has no performance + // impact. gl::TexImage2D( gl::TEXTURE_2D, 0, - gl::RGB as i32, + gl::RGBA as i32, size, size, 0, - gl::RGB, + gl::RGBA, gl::UNSIGNED_BYTE, ptr::null(), ); diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs index 26e98e53..19371c9b 100644 --- a/font/src/darwin/mod.rs +++ b/font/src/darwin/mod.rs @@ -488,8 +488,8 @@ impl Font { kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, ); - // Give the context an opaque, black background. - cg_context.set_rgb_fill_color(0.0, 0.0, 0.0, 1.0); + // Set background color for graphics context. + cg_context.set_rgb_fill_color(0.0, 0.0, 0.0, 0.0); let context_rect = CGRect::new( &CGPoint::new(0.0, 0.0), &CGSize::new(f64::from(rasterized_width), f64::from(rasterized_height)), diff --git a/font/src/lib.rs b/font/src/lib.rs index 2a19f620..d5b9716e 100644 --- a/font/src/lib.rs +++ b/font/src/lib.rs @@ -173,7 +173,10 @@ pub struct RasterizedGlyph { #[derive(Clone, Debug)] pub enum BitmapBuffer { + /// RGB alphamask. RGB(Vec), + + /// RGBA pixels with premultiplied alpha. RGBA(Vec), } diff --git a/res/text.f.glsl b/res/text.f.glsl index 70ad3d19..cf477eb0 100644 --- a/res/text.f.glsl +++ b/res/text.f.glsl @@ -15,6 +15,7 @@ in vec2 TexCoords; flat in vec3 fg; flat in vec4 bg; +flat in int colored; uniform int backgroundPass; layout(location = 0, index = 0) out vec4 color; @@ -31,8 +32,22 @@ void main() alphaMask = vec4(1.0); color = vec4(bg.rgb, 1.0); } else { - vec3 textColor = texture(mask, TexCoords).rgb; - alphaMask = vec4(textColor, textColor.r); - color = vec4(fg, 1.0); + if (colored != 0) { + // Color glyphs, like emojis. + vec4 glyphColor = texture(mask, TexCoords); + alphaMask = vec4(glyphColor.a); + + // Revert alpha premultiplication. + if (glyphColor.a != 0) { + glyphColor.rgb = vec3(glyphColor.rgb / glyphColor.a); + } + + color = vec4(glyphColor.rgb, 1.0); + } else { + // Regular text glyphs. + vec3 textColor = texture(mask, TexCoords).rgb; + alphaMask = vec4(textColor, textColor.r); + color = vec4(fg, 1.0); + } } } diff --git a/res/text.v.glsl b/res/text.v.glsl index 5189980f..8978c111 100644 --- a/res/text.v.glsl +++ b/res/text.v.glsl @@ -12,24 +12,28 @@ // See the License for the specific language governing permissions and // limitations under the License. #version 330 core -// Cell properties +// Cell properties. layout (location = 0) in vec2 gridCoords; -// glyph properties +// Glyph properties. layout (location = 1) in vec4 glyph; -// uv mapping +// uv mapping. layout (location = 2) in vec4 uv; -// text fg color +// Text fg color. layout (location = 3) in vec3 textColor; -// Background color +// Background color. layout (location = 4) in vec4 backgroundColor; +// Set to 1 if the glyph colors should be kept. +layout (location = 5) in int coloredGlyph; + out vec2 TexCoords; flat out vec3 fg; flat out vec4 bg; +flat out int colored; // Terminal properties uniform vec2 cellDim; @@ -71,4 +75,5 @@ void main() bg = vec4(backgroundColor.rgb / 255.0, backgroundColor.a); fg = textColor / vec3(255.0, 255.0, 255.0); + colored = coloredGlyph; }