Use line height from attrs
This commit is contained in:
parent
8638ec29bb
commit
37688747e1
6 changed files with 44 additions and 60 deletions
|
|
@ -26,6 +26,7 @@ fn set_buffer_text<'a>(buffer: &mut BorrowedWithFontSystem<'a, Buffer>) {
|
||||||
let comic_attrs = attrs.family(Family::Name("Comic Neue"));
|
let comic_attrs = attrs.family(Family::Name("Comic Neue"));
|
||||||
|
|
||||||
let spans: &[(&str, Attrs)] = &[
|
let spans: &[(&str, Attrs)] = &[
|
||||||
|
("Font size 64 ", attrs.metrics(Metrics::relative(64.0, 1.2))),
|
||||||
("Font size 8 ", attrs.metrics(Metrics::relative(8.0, 1.2))),
|
("Font size 8 ", attrs.metrics(Metrics::relative(8.0, 1.2))),
|
||||||
("Font size 20 ", attrs.metrics(Metrics::relative(20.0, 1.2))),
|
("Font size 20 ", attrs.metrics(Metrics::relative(20.0, 1.2))),
|
||||||
("Font size 14 ", attrs.metrics(Metrics::relative(14.0, 1.2))),
|
("Font size 14 ", attrs.metrics(Metrics::relative(14.0, 1.2))),
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ pub struct LayoutRun<'a> {
|
||||||
pub line_y: f32,
|
pub line_y: f32,
|
||||||
/// Y offset to top of line
|
/// Y offset to top of line
|
||||||
pub line_top: f32,
|
pub line_top: f32,
|
||||||
|
/// Y offset to next line
|
||||||
|
pub line_height: f32,
|
||||||
/// Width of line
|
/// Width of line
|
||||||
pub line_w: f32,
|
pub line_w: f32,
|
||||||
}
|
}
|
||||||
|
|
@ -92,43 +94,18 @@ pub struct LayoutRunIter<'b> {
|
||||||
buffer: &'b Buffer,
|
buffer: &'b Buffer,
|
||||||
line_i: usize,
|
line_i: usize,
|
||||||
layout_i: usize,
|
layout_i: usize,
|
||||||
remaining_len: usize,
|
|
||||||
total_layout: i32,
|
total_layout: i32,
|
||||||
|
line_top: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> LayoutRunIter<'b> {
|
impl<'b> LayoutRunIter<'b> {
|
||||||
pub fn new(buffer: &'b Buffer) -> Self {
|
pub fn new(buffer: &'b Buffer) -> Self {
|
||||||
let total_layout_lines: usize = buffer
|
|
||||||
.lines
|
|
||||||
.iter()
|
|
||||||
.skip(buffer.scroll.line)
|
|
||||||
.map(|line| {
|
|
||||||
line.layout_opt()
|
|
||||||
.as_ref()
|
|
||||||
.map(|layout| layout.len())
|
|
||||||
.unwrap_or_default()
|
|
||||||
})
|
|
||||||
.sum();
|
|
||||||
let top_cropped_layout_lines =
|
|
||||||
total_layout_lines.saturating_sub(buffer.scroll.layout.try_into().unwrap_or_default());
|
|
||||||
let maximum_lines = if buffer.metrics.line_height == 0.0 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
(buffer.height / buffer.metrics.line_height) as i32
|
|
||||||
};
|
|
||||||
let bottom_cropped_layout_lines =
|
|
||||||
if top_cropped_layout_lines > maximum_lines.try_into().unwrap_or_default() {
|
|
||||||
maximum_lines.try_into().unwrap_or_default()
|
|
||||||
} else {
|
|
||||||
top_cropped_layout_lines
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
buffer,
|
buffer,
|
||||||
line_i: buffer.scroll.line,
|
line_i: buffer.scroll.line,
|
||||||
layout_i: 0,
|
layout_i: 0,
|
||||||
remaining_len: bottom_cropped_layout_lines,
|
|
||||||
total_layout: 0,
|
total_layout: 0,
|
||||||
|
line_top: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -136,10 +113,6 @@ impl<'b> LayoutRunIter<'b> {
|
||||||
impl<'b> Iterator for LayoutRunIter<'b> {
|
impl<'b> Iterator for LayoutRunIter<'b> {
|
||||||
type Item = LayoutRun<'b>;
|
type Item = LayoutRun<'b>;
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
||||||
(self.remaining_len, Some(self.remaining_len))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let Some(line) = self.buffer.lines.get(self.line_i) {
|
while let Some(line) = self.buffer.lines.get(self.line_i) {
|
||||||
let shape = line.shape_opt().as_ref()?;
|
let shape = line.shape_opt().as_ref()?;
|
||||||
|
|
@ -153,30 +126,33 @@ impl<'b> Iterator for LayoutRunIter<'b> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let line_top = self
|
let mut line_height = self.buffer.metrics.line_height;
|
||||||
.total_layout
|
for glyph in layout_line.glyphs.iter() {
|
||||||
.saturating_sub(self.buffer.scroll.layout)
|
if let Some(glyph_line_height) = glyph.line_height_opt {
|
||||||
.saturating_sub(1) as f32
|
line_height = line_height.max(glyph_line_height);
|
||||||
* self.buffer.metrics.line_height;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let line_top = self.line_top;
|
||||||
let glyph_height = layout_line.max_ascent + layout_line.max_descent;
|
let glyph_height = layout_line.max_ascent + layout_line.max_descent;
|
||||||
let centering_offset = (self.buffer.metrics.line_height - glyph_height) / 2.0;
|
let centering_offset = (line_height - glyph_height) / 2.0;
|
||||||
let line_y = line_top + centering_offset + layout_line.max_ascent;
|
let line_y = line_top + centering_offset + layout_line.max_ascent;
|
||||||
|
|
||||||
if line_top + centering_offset > self.buffer.height {
|
if line_top + centering_offset > self.buffer.height {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.remaining_len.checked_sub(1).map(|num| {
|
self.line_top += line_height;
|
||||||
self.remaining_len = num;
|
|
||||||
LayoutRun {
|
return Some(LayoutRun {
|
||||||
line_i: self.line_i,
|
line_i: self.line_i,
|
||||||
text: line.text(),
|
text: line.text(),
|
||||||
rtl: shape.rtl,
|
rtl: shape.rtl,
|
||||||
glyphs: &layout_line.glyphs,
|
glyphs: &layout_line.glyphs,
|
||||||
line_y,
|
line_y,
|
||||||
line_top,
|
line_top,
|
||||||
line_w: layout_line.w,
|
line_height,
|
||||||
}
|
line_w: layout_line.w,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.line_i += 1;
|
self.line_i += 1;
|
||||||
|
|
@ -187,8 +163,6 @@ impl<'b> Iterator for LayoutRunIter<'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> ExactSizeIterator for LayoutRunIter<'b> {}
|
|
||||||
|
|
||||||
/// Metrics of text
|
/// Metrics of text
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
pub struct Metrics {
|
pub struct Metrics {
|
||||||
|
|
@ -798,21 +772,19 @@ impl Buffer {
|
||||||
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
|
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
|
||||||
let instant = std::time::Instant::now();
|
let instant = std::time::Instant::now();
|
||||||
|
|
||||||
let font_size = self.metrics.font_size;
|
|
||||||
let line_height = self.metrics.line_height;
|
|
||||||
|
|
||||||
let mut new_cursor_opt = None;
|
let mut new_cursor_opt = None;
|
||||||
|
|
||||||
let mut runs = self.layout_runs().peekable();
|
let mut runs = self.layout_runs().peekable();
|
||||||
let mut first_run = true;
|
let mut first_run = true;
|
||||||
while let Some(run) = runs.next() {
|
while let Some(run) = runs.next() {
|
||||||
let line_y = run.line_y;
|
let line_top = run.line_top;
|
||||||
|
let line_height = run.line_height;
|
||||||
|
|
||||||
if first_run && y < line_y - font_size {
|
if first_run && y < line_top {
|
||||||
first_run = false;
|
first_run = false;
|
||||||
let new_cursor = Cursor::new(run.line_i, 0);
|
let new_cursor = Cursor::new(run.line_i, 0);
|
||||||
new_cursor_opt = Some(new_cursor);
|
new_cursor_opt = Some(new_cursor);
|
||||||
} else if y >= line_y - font_size && y < line_y - font_size + line_height {
|
} else if y >= line_top && y < line_top + line_height {
|
||||||
let mut new_cursor_glyph = run.glyphs.len();
|
let mut new_cursor_glyph = run.glyphs.len();
|
||||||
let mut new_cursor_char = 0;
|
let mut new_cursor_char = 0;
|
||||||
let mut new_cursor_affinity = Affinity::After;
|
let mut new_cursor_affinity = Affinity::After;
|
||||||
|
|
@ -1128,7 +1100,7 @@ impl Buffer {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Motion::Vertical(px) => {
|
Motion::Vertical(px) => {
|
||||||
// TODO more efficient
|
// TODO more efficient, use layout run line height
|
||||||
let lines = px / self.metrics().line_height as i32;
|
let lines = px / self.metrics().line_height as i32;
|
||||||
match lines.cmp(&0) {
|
match lines.cmp(&0) {
|
||||||
cmp::Ordering::Less => {
|
cmp::Ordering::Less => {
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,11 @@ impl<'buffer> Editor<'buffer> {
|
||||||
F: FnMut(i32, i32, u32, u32, Color),
|
F: FnMut(i32, i32, u32, u32, Color),
|
||||||
{
|
{
|
||||||
self.with_buffer(|buffer| {
|
self.with_buffer(|buffer| {
|
||||||
let line_height = buffer.metrics().line_height;
|
|
||||||
for run in buffer.layout_runs() {
|
for run in buffer.layout_runs() {
|
||||||
let line_i = run.line_i;
|
let line_i = run.line_i;
|
||||||
let line_y = run.line_y;
|
let line_y = run.line_y;
|
||||||
let line_top = run.line_top;
|
let line_top = run.line_top;
|
||||||
|
let line_height = run.line_height;
|
||||||
|
|
||||||
let cursor_glyph_opt = |cursor: &Cursor| -> Option<(usize, f32)> {
|
let cursor_glyph_opt = |cursor: &Cursor| -> Option<(usize, f32)> {
|
||||||
if cursor.line == line_i {
|
if cursor.line == line_i {
|
||||||
|
|
|
||||||
|
|
@ -312,11 +312,11 @@ impl<'syntax_system, 'buffer> ViEditor<'syntax_system, 'buffer> {
|
||||||
let size = buffer.size();
|
let size = buffer.size();
|
||||||
f(0, 0, size.0 as u32, size.1 as u32, background_color);
|
f(0, 0, size.0 as u32, size.1 as u32, background_color);
|
||||||
let font_size = buffer.metrics().font_size;
|
let font_size = buffer.metrics().font_size;
|
||||||
let line_height = buffer.metrics().line_height;
|
|
||||||
for run in buffer.layout_runs() {
|
for run in buffer.layout_runs() {
|
||||||
let line_i = run.line_i;
|
let line_i = run.line_i;
|
||||||
let line_y = run.line_y;
|
let line_y = run.line_y;
|
||||||
let line_top = run.line_top;
|
let line_top = run.line_top;
|
||||||
|
let line_height = run.line_height;
|
||||||
|
|
||||||
let cursor_glyph_opt = |cursor: &Cursor| -> Option<(usize, f32, f32)> {
|
let cursor_glyph_opt = |cursor: &Cursor| -> Option<(usize, f32, f32)> {
|
||||||
//TODO: better calculation of width
|
//TODO: better calculation of width
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ pub struct LayoutGlyph {
|
||||||
pub end: usize,
|
pub end: usize,
|
||||||
/// Font size of the glyph
|
/// Font size of the glyph
|
||||||
pub font_size: f32,
|
pub font_size: f32,
|
||||||
|
/// Line height of the glyph, will override buffer setting
|
||||||
|
pub line_height_opt: Option<f32>,
|
||||||
/// Font id of the glyph
|
/// Font id of the glyph
|
||||||
pub font_id: fontdb::ID,
|
pub font_id: fontdb::ID,
|
||||||
/// Font id of the glyph
|
/// Font id of the glyph
|
||||||
|
|
|
||||||
11
src/shape.rs
11
src/shape.rs
|
|
@ -494,6 +494,7 @@ impl ShapeGlyph {
|
||||||
fn layout(
|
fn layout(
|
||||||
&self,
|
&self,
|
||||||
font_size: f32,
|
font_size: f32,
|
||||||
|
line_height_opt: Option<f32>,
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
w: f32,
|
w: f32,
|
||||||
|
|
@ -503,6 +504,7 @@ impl ShapeGlyph {
|
||||||
start: self.start,
|
start: self.start,
|
||||||
end: self.end,
|
end: self.end,
|
||||||
font_size,
|
font_size,
|
||||||
|
line_height_opt,
|
||||||
font_id: self.font_id,
|
font_id: self.font_id,
|
||||||
glyph_id: self.glyph_id,
|
glyph_id: self.glyph_id,
|
||||||
x,
|
x,
|
||||||
|
|
@ -1418,7 +1420,14 @@ impl ShapeLine {
|
||||||
x -= x_advance;
|
x -= x_advance;
|
||||||
}
|
}
|
||||||
let y_advance = glyph_font_size * glyph.y_advance;
|
let y_advance = glyph_font_size * glyph.y_advance;
|
||||||
glyphs.push(glyph.layout(glyph_font_size, x, y, x_advance, span.level));
|
glyphs.push(glyph.layout(
|
||||||
|
glyph_font_size,
|
||||||
|
glyph.metrics_opt.map(|x| x.line_height),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
x_advance,
|
||||||
|
span.level,
|
||||||
|
));
|
||||||
if !self.rtl {
|
if !self.rtl {
|
||||||
x += x_advance;
|
x += x_advance;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue