fixed some issues with text rendering and line wrapping
This commit is contained in:
@@ -198,13 +198,45 @@ impl TerminalText {
|
|||||||
|
|
||||||
fn get_line_bounds(&self, line: usize) -> TextBounds {
|
fn get_line_bounds(&self, line: usize) -> TextBounds {
|
||||||
// Calculate the bounds for a specific line
|
// Calculate the bounds for a specific line
|
||||||
|
if line >= self.buffer.lines.len() {
|
||||||
|
// Return default bounds for invalid line
|
||||||
|
return TextBounds {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let line_height = self.buffer.metrics().line_height;
|
let line_height = self.buffer.metrics().line_height;
|
||||||
let viewport_width = self.viewport.resolution().width;
|
let viewport_width = self.viewport.resolution().width;
|
||||||
|
|
||||||
// Calculate floating point values first
|
// Use layout_runs to get information about wrapped lines
|
||||||
let top_f32 = (line as f32 * line_height).floor();
|
let layout_iter = self.buffer.layout_runs();
|
||||||
let bottom_f32 = ((line as f32 + 1.0) * line_height).ceil();
|
let mut top_line = 0;
|
||||||
|
let mut bottom_line = 0;
|
||||||
|
let mut found_line = false;
|
||||||
|
|
||||||
|
// Iterate through layout runs to find our target line
|
||||||
|
for (visual_line_count, run) in layout_iter.enumerate() {
|
||||||
|
if run.line_i == line {
|
||||||
|
// This run belongs to our target line
|
||||||
|
if !found_line {
|
||||||
|
// First run of our target line
|
||||||
|
top_line = visual_line_count;
|
||||||
|
found_line = true;
|
||||||
|
}
|
||||||
|
// Update bottom line for each run we find for this line
|
||||||
|
bottom_line = visual_line_count + 1;
|
||||||
|
} else if found_line {
|
||||||
|
// We've processed all runs for our target line
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate bounds based on visual line positions
|
||||||
|
let top_f32 = (top_line as f32 * line_height).floor();
|
||||||
|
let bottom_f32 = (bottom_line as f32 * line_height).ceil();
|
||||||
|
|
||||||
// Safe conversions with overflow checks
|
// Safe conversions with overflow checks
|
||||||
let top = if top_f32 > i32::MAX as f32 {
|
let top = if top_f32 > i32::MAX as f32 {
|
||||||
@@ -241,15 +273,26 @@ impl TerminalText {
|
|||||||
// Start from line 0 (no scrolling yet)
|
// Start from line 0 (no scrolling yet)
|
||||||
let start_line = 0;
|
let start_line = 0;
|
||||||
|
|
||||||
// Calculate how many complete lines fit in the viewport
|
// Calculate visible lines based on wrapped text
|
||||||
// Add 1 to include partially visible lines at the bottom
|
let layout_iter = self.buffer.layout_runs();
|
||||||
let visible_lines = (viewport_height / line_height).ceil() as usize + 1;
|
let mut last_logical_line = 0;
|
||||||
|
|
||||||
// Make sure we don't go beyond the actual number of lines
|
// Count how many visual lines we have and map to logical lines
|
||||||
|
for (visual_line_count, run) in layout_iter.enumerate() {
|
||||||
|
last_logical_line = run.line_i;
|
||||||
|
|
||||||
|
// If we've exceeded the viewport height, we can stop counting
|
||||||
|
if ((start_line + visual_line_count) as f32 * line_height) > viewport_height {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add 1 to include partially visible lines at the bottom
|
||||||
let end_line = if self.buffer.lines.is_empty() {
|
let end_line = if self.buffer.lines.is_empty() {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
(start_line + visible_lines).min(self.buffer.lines.len())
|
// Make sure we include at least the last logical line that has content in the viewport
|
||||||
|
(last_logical_line + 1).min(self.buffer.lines.len())
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!("visible line range goes from {start_line} to {end_line}");
|
trace!("visible line range goes from {start_line} to {end_line}");
|
||||||
|
|||||||
Reference in New Issue
Block a user