Skip to content

Commit ef74395

Browse files
authored
fix(canvas): add clipping for each cell to avoid overflow (#76)
Previously the drawn characters in the cells used to overflow the available cell area and causing visual glitches due to the leftover areas are not being redrawn. This commit introduces clipping for each cell and makes sure the text does not overflows from the cell. This might lead to visually disconnecting blocks in some cases but overall improves the rendering. Fixes #28
1 parent ab31bbd commit ef74395

1 file changed

Lines changed: 37 additions & 14 deletions

File tree

src/backend/canvas.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,31 @@ impl CanvasBackend {
126126
for (x, cell) in line.iter().enumerate() {
127127
if cell != &self.prev_buffer[y][x] || force_redraw {
128128
let colors = get_cell_color_for_canvas(cell, self.canvas.background_color);
129+
// Save the current state of the canvas context
130+
self.canvas.context.save();
131+
132+
// Background
129133
self.canvas.context.set_fill_style_str(colors.1.as_str());
130134
self.canvas
131135
.context
132136
.fill_rect(x as f64 * xmul, y as f64 * ymul, xmul, ymul);
137+
138+
// Apply clipping for the text
139+
self.canvas.context.begin_path();
140+
self.canvas
141+
.context
142+
.rect(x as f64 * xmul, y as f64 * ymul, xmul, ymul);
143+
self.canvas.context.clip();
144+
145+
// Foreground & text
133146
self.canvas.context.set_fill_style_str(colors.0.as_str());
134147
self.canvas.context.fill_text(
135148
cell.symbol(),
136149
x as f64 * xmul,
137150
y as f64 * ymul,
138151
)?;
152+
153+
self.canvas.context.restore();
139154
}
140155
}
141156
}
@@ -160,6 +175,28 @@ impl Backend for CanvasBackend {
160175
Ok(())
161176
}
162177

178+
/// Flush the content to the screen.
179+
///
180+
/// This function is called after the [`CanvasBackend::draw`] function to
181+
/// actually render the content to the screen.
182+
fn flush(&mut self) -> IoResult<()> {
183+
// Only runs once.
184+
if !self.initialized {
185+
self.update_grid(true)?;
186+
self.prev_buffer = self.buffer.clone();
187+
self.initialized = true;
188+
return Ok(());
189+
}
190+
191+
if self.buffer != self.prev_buffer {
192+
self.update_grid(false)?;
193+
}
194+
195+
self.prev_buffer = self.buffer.clone();
196+
197+
Ok(())
198+
}
199+
163200
fn hide_cursor(&mut self) -> IoResult<()> {
164201
Ok(())
165202
}
@@ -192,20 +229,6 @@ impl Backend for CanvasBackend {
192229
unimplemented!()
193230
}
194231

195-
fn flush(&mut self) -> IoResult<()> {
196-
if !self.initialized {
197-
self.update_grid(true)?;
198-
self.prev_buffer = self.buffer.clone();
199-
self.initialized = true;
200-
return Ok(());
201-
}
202-
if self.buffer != self.prev_buffer {
203-
self.update_grid(false)?;
204-
}
205-
self.prev_buffer = self.buffer.clone();
206-
Ok(())
207-
}
208-
209232
fn get_cursor_position(&mut self) -> IoResult<Position> {
210233
unimplemented!()
211234
}

0 commit comments

Comments
 (0)