aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2020-11-17 17:49:05 +0300
committerGitHub <noreply@github.com>2020-11-17 17:49:05 +0300
commit9724418d350df881afe8453bde6eb88643e7211e (patch)
treee3f2cac36404430df1f5093226dcc9f944f66cc0 /alacritty/src
parent8b10e5e77840c0477a4b1575f91a4549d010af04 (diff)
downloadr-alacritty-9724418d350df881afe8453bde6eb88643e7211e.tar.gz
r-alacritty-9724418d350df881afe8453bde6eb88643e7211e.tar.bz2
r-alacritty-9724418d350df881afe8453bde6eb88643e7211e.zip
Fix wide characters being cut off
Fixes #791.
Diffstat (limited to 'alacritty/src')
-rw-r--r--alacritty/src/renderer/mod.rs37
-rw-r--r--alacritty/src/renderer/rects.rs10
-rw-r--r--alacritty/src/url.rs31
3 files changed, 65 insertions, 13 deletions
diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs
index b347556d..f63f92fd 100644
--- a/alacritty/src/renderer/mod.rs
+++ b/alacritty/src/renderer/mod.rs
@@ -9,6 +9,7 @@ use std::ptr;
use std::sync::mpsc;
use std::time::Duration;
+use bitflags::bitflags;
use crossfont::{
BitmapBuffer, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Rasterizer, Size, Slant,
Style, Weight,
@@ -123,7 +124,7 @@ pub struct RectShaderProgram {
#[derive(Copy, Debug, Clone)]
pub struct Glyph {
tex_id: GLuint,
- multicolor: u8,
+ multicolor: bool,
top: i16,
left: i16,
width: i16,
@@ -359,30 +360,46 @@ impl GlyphCache {
}
}
+// NOTE: These flags must be in sync with their usage in the text.*.glsl shaders.
+bitflags! {
+ #[repr(C)]
+ struct RenderingGlyphFlags: u8 {
+ const WIDE_CHAR = 0b0000_0001;
+ const COLORED = 0b0000_0010;
+ }
+}
+
#[derive(Debug)]
#[repr(C)]
struct InstanceData {
// Coords.
col: u16,
row: u16,
+
// Glyph offset.
left: i16,
top: i16,
+
// Glyph size.
width: i16,
height: i16,
+
// UV offset.
uv_left: f32,
uv_bot: f32,
+
// uv scale.
uv_width: f32,
uv_height: f32,
+
// Color.
r: u8,
g: u8,
b: u8,
- // Flag indicating that a glyph uses multiple colors; like an Emoji.
- multicolor: u8,
+
+ // Cell flags like multicolor or fullwidth character.
+ cell_flags: RenderingGlyphFlags,
+
// Background color.
bg_r: u8,
bg_g: u8,
@@ -441,6 +458,10 @@ impl Batch {
self.tex = glyph.tex_id;
}
+ let mut cell_flags = RenderingGlyphFlags::empty();
+ cell_flags.set(RenderingGlyphFlags::COLORED, glyph.multicolor);
+ cell_flags.set(RenderingGlyphFlags::WIDE_CHAR, cell.flags.contains(Flags::WIDE_CHAR));
+
self.instances.push(InstanceData {
col: cell.column.0 as u16,
row: cell.line.0 as u16,
@@ -458,12 +479,12 @@ impl Batch {
r: cell.fg.r,
g: cell.fg.g,
b: cell.fg.b,
+ cell_flags,
bg_r: cell.bg.r,
bg_g: cell.bg.g,
bg_b: cell.bg.b,
bg_a: (cell.bg_alpha * 255.0) as u8,
- multicolor: glyph.multicolor,
});
}
@@ -586,10 +607,10 @@ impl QuadRenderer {
// UV offset.
add_attr!(4, gl::FLOAT, f32);
- // Color and multicolor flag.
+ // Color and cell flags.
//
// These are packed together because of an OpenGL driver issue on macOS, which caused a
- // `vec3(u8)` text color and a `u8` multicolor flag to increase the rendering time by a
+ // `vec3(u8)` text color and a `u8` cell flags to increase the rendering time by a
// huge margin.
add_attr!(4, gl::UNSIGNED_BYTE, u8);
@@ -1067,7 +1088,7 @@ fn load_glyph(
},
Err(AtlasInsertError::GlyphTooLarge) => Glyph {
tex_id: atlas[*current_atlas].id,
- multicolor: 0,
+ multicolor: false,
top: 0,
left: 0,
width: 0,
@@ -1581,7 +1602,7 @@ impl Atlas {
Glyph {
tex_id: self.id,
- multicolor: multicolor as u8,
+ multicolor,
top: glyph.top as i16,
left: glyph.left as i16,
width: width as i16,
diff --git a/alacritty/src/renderer/rects.rs b/alacritty/src/renderer/rects.rs
index fcd8c82e..2a727b4c 100644
--- a/alacritty/src/renderer/rects.rs
+++ b/alacritty/src/renderer/rects.rs
@@ -162,6 +162,12 @@ impl RenderLines {
return;
}
+ // Include wide char spacer if the current cell is a wide char.
+ let mut end: Point = cell.into();
+ if cell.flags.contains(Flags::WIDE_CHAR) {
+ end.col += 1;
+ }
+
// Check if there's an active line.
if let Some(line) = self.inner.get_mut(&flag).and_then(|lines| lines.last_mut()) {
if cell.fg == line.color
@@ -169,13 +175,13 @@ impl RenderLines {
&& cell.line == line.end.line
{
// Update the length of the line.
- line.end = cell.into();
+ line.end = end;
return;
}
}
// Start new line if there currently is none.
- let line = RenderLine { start: cell.into(), end: cell.into(), color: cell.fg };
+ let line = RenderLine { start: cell.into(), end, color: cell.fg };
match self.inner.get_mut(&flag) {
Some(lines) => lines.push(line),
None => {
diff --git a/alacritty/src/url.rs b/alacritty/src/url.rs
index 5d35667d..b33b532e 100644
--- a/alacritty/src/url.rs
+++ b/alacritty/src/url.rs
@@ -79,7 +79,12 @@ impl Urls {
};
let point: Point = cell.into();
- let end = point;
+ let mut end = point;
+
+ // Include the following wide char spacer.
+ if cell.flags.contains(Flags::WIDE_CHAR) {
+ end.col += 1;
+ }
// Reset URL when empty cells have been skipped.
if point != Point::default() && Some(point.sub(num_cols, 1)) != self.last_point {
@@ -88,8 +93,8 @@ impl Urls {
self.last_point = Some(end);
- // Extend current state if a wide char spacer is encountered.
- if cell.flags.intersects(Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER) {
+ // Extend current state if a leading wide char spacer is encountered.
+ if cell.flags.intersects(Flags::LEADING_WIDE_CHAR_SPACER) {
if let UrlLocation::Url(_, mut end_offset) = self.state {
if end_offset != 0 {
end_offset += 1;
@@ -252,4 +257,24 @@ mod tests {
assert_eq!(urls.urls[2].start().col, Column(17));
assert_eq!(urls.urls[2].end().col, Column(21));
}
+
+ #[test]
+ fn wide_urls() {
+ let input = text_to_cells("test https://こんにちは (http:여보세요) ing");
+ let num_cols = input.len() + 9;
+
+ let mut urls = Urls::new();
+
+ for cell in input {
+ urls.update(Column(num_cols), &cell);
+ }
+
+ assert_eq!(urls.urls.len(), 2);
+
+ assert_eq!(urls.urls[0].start().col, Column(5));
+ assert_eq!(urls.urls[0].end().col, Column(17));
+
+ assert_eq!(urls.urls[1].start().col, Column(20));
+ assert_eq!(urls.urls[1].end().col, Column(28));
+ }
}