Extract borrow of FontSystem from Buffer
This commit is contained in:
parent
bff5aaaea3
commit
057b5b6fa9
12 changed files with 381 additions and 216 deletions
207
src/buffer.rs
207
src/buffer.rs
|
|
@ -10,7 +10,10 @@ use unicode_segmentation::UnicodeSegmentation;
|
|||
|
||||
#[cfg(feature = "swash")]
|
||||
use crate::Color;
|
||||
use crate::{Attrs, AttrsList, BufferLine, FontSystem, LayoutGlyph, LayoutLine, ShapeLine, Wrap};
|
||||
use crate::{
|
||||
Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, FontSystem, LayoutGlyph, LayoutLine,
|
||||
ShapeLine, Wrap,
|
||||
};
|
||||
|
||||
/// Current cursor location
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
|
||||
|
|
@ -169,8 +172,8 @@ impl<'a> LayoutRun<'a> {
|
|||
}
|
||||
|
||||
/// An iterator of visible text lines, see [`LayoutRun`]
|
||||
pub struct LayoutRunIter<'a, 'b> {
|
||||
buffer: &'b Buffer<'a>,
|
||||
pub struct LayoutRunIter<'b> {
|
||||
buffer: &'b Buffer,
|
||||
line_i: usize,
|
||||
layout_i: usize,
|
||||
remaining_len: usize,
|
||||
|
|
@ -178,8 +181,8 @@ pub struct LayoutRunIter<'a, 'b> {
|
|||
total_layout: i32,
|
||||
}
|
||||
|
||||
impl<'a, 'b> LayoutRunIter<'a, 'b> {
|
||||
pub fn new(buffer: &'b Buffer<'a>) -> Self {
|
||||
impl<'b> LayoutRunIter<'b> {
|
||||
pub fn new(buffer: &'b Buffer) -> Self {
|
||||
let total_layout_lines: usize = buffer
|
||||
.lines
|
||||
.iter()
|
||||
|
|
@ -215,7 +218,7 @@ impl<'a, 'b> LayoutRunIter<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Iterator for LayoutRunIter<'a, 'b> {
|
||||
impl<'b> Iterator for LayoutRunIter<'b> {
|
||||
type Item = LayoutRun<'b>;
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
|
|
@ -258,7 +261,7 @@ impl<'a, 'b> Iterator for LayoutRunIter<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> ExactSizeIterator for LayoutRunIter<'a, 'b> {}
|
||||
impl<'b> ExactSizeIterator for LayoutRunIter<'b> {}
|
||||
|
||||
/// Metrics of text
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
|
|
@ -296,8 +299,7 @@ impl fmt::Display for Metrics {
|
|||
}
|
||||
|
||||
/// A buffer of text that is shaped and laid out
|
||||
pub struct Buffer<'a> {
|
||||
font_system: &'a FontSystem,
|
||||
pub struct Buffer {
|
||||
/// [BufferLine]s (or paragraphs) of text in the buffer
|
||||
pub lines: Vec<BufferLine>,
|
||||
metrics: Metrics,
|
||||
|
|
@ -309,17 +311,16 @@ pub struct Buffer<'a> {
|
|||
wrap: Wrap,
|
||||
}
|
||||
|
||||
impl<'a> Buffer<'a> {
|
||||
impl Buffer {
|
||||
/// Create a new [`Buffer`] with the provided [`FontSystem`] and [`Metrics`]
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Will panic if `metrics.line_height` is zero.
|
||||
pub fn new(font_system: &'a FontSystem, metrics: Metrics) -> Self {
|
||||
pub fn new(font_system: &FontSystem, metrics: Metrics) -> Self {
|
||||
assert_ne!(metrics.line_height, 0.0, "line height cannot be 0");
|
||||
|
||||
let mut buffer = Self {
|
||||
font_system,
|
||||
lines: Vec::new(),
|
||||
metrics,
|
||||
width: 0.0,
|
||||
|
|
@ -328,23 +329,28 @@ impl<'a> Buffer<'a> {
|
|||
redraw: false,
|
||||
wrap: Wrap::Word,
|
||||
};
|
||||
buffer.set_text("", Attrs::new());
|
||||
buffer.set_text(font_system, "", Attrs::new());
|
||||
buffer
|
||||
}
|
||||
|
||||
fn relayout(&mut self) {
|
||||
pub fn borrow_with<'a>(
|
||||
&'a mut self,
|
||||
font_system: &'a FontSystem,
|
||||
) -> BorrowedWithFontSystem<'a, Buffer> {
|
||||
BorrowedWithFontSystem {
|
||||
inner: self,
|
||||
font_system,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn relayout(&mut self, font_system: &FontSystem) {
|
||||
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
|
||||
let instant = std::time::Instant::now();
|
||||
|
||||
for line in &mut self.lines {
|
||||
if line.shape_opt().is_some() {
|
||||
line.reset_layout();
|
||||
line.layout(
|
||||
self.font_system,
|
||||
self.metrics.font_size,
|
||||
self.width,
|
||||
self.wrap,
|
||||
);
|
||||
line.layout(font_system, self.metrics.font_size, self.width, self.wrap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,8 +360,7 @@ impl<'a> Buffer<'a> {
|
|||
log::debug!("relayout: {:?}", instant.elapsed());
|
||||
}
|
||||
|
||||
/// Pre-shape lines in the buffer, up to `lines`, return actual number of layout lines
|
||||
pub fn shape_until(&mut self, lines: i32) -> i32 {
|
||||
pub(crate) fn shape_until(&mut self, font_system: &FontSystem, lines: i32) -> i32 {
|
||||
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
|
||||
let instant = std::time::Instant::now();
|
||||
|
||||
|
|
@ -369,12 +374,7 @@ impl<'a> Buffer<'a> {
|
|||
if line.shape_opt().is_none() {
|
||||
reshaped += 1;
|
||||
}
|
||||
let layout = line.layout(
|
||||
self.font_system,
|
||||
self.metrics.font_size,
|
||||
self.width,
|
||||
self.wrap,
|
||||
);
|
||||
let layout = line.layout(font_system, self.metrics.font_size, self.width, self.wrap);
|
||||
total_layout += layout.len() as i32;
|
||||
}
|
||||
|
||||
|
|
@ -387,8 +387,7 @@ impl<'a> Buffer<'a> {
|
|||
total_layout
|
||||
}
|
||||
|
||||
/// Shape lines until cursor, also scrolling to include cursor in view
|
||||
pub fn shape_until_cursor(&mut self, cursor: Cursor) {
|
||||
pub(crate) fn shape_until_cursor(&mut self, font_system: &FontSystem, cursor: Cursor) {
|
||||
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
|
||||
let instant = std::time::Instant::now();
|
||||
|
||||
|
|
@ -402,12 +401,7 @@ impl<'a> Buffer<'a> {
|
|||
if line.shape_opt().is_none() {
|
||||
reshaped += 1;
|
||||
}
|
||||
let layout = line.layout(
|
||||
self.font_system,
|
||||
self.metrics.font_size,
|
||||
self.width,
|
||||
self.wrap,
|
||||
);
|
||||
let layout = line.layout(font_system, self.metrics.font_size, self.width, self.wrap);
|
||||
if line_i == cursor.line {
|
||||
let layout_cursor = self.layout_cursor(&cursor);
|
||||
layout_i += layout_cursor.layout as i32;
|
||||
|
|
@ -430,15 +424,14 @@ impl<'a> Buffer<'a> {
|
|||
self.scroll = layout_i - (lines - 1);
|
||||
}
|
||||
|
||||
self.shape_until_scroll();
|
||||
self.shape_until_scroll(font_system);
|
||||
}
|
||||
|
||||
/// Shape lines until scroll
|
||||
pub fn shape_until_scroll(&mut self) {
|
||||
pub(crate) fn shape_until_scroll(&mut self, font_system: &FontSystem) {
|
||||
let lines = self.visible_lines();
|
||||
|
||||
let scroll_end = self.scroll + lines;
|
||||
let total_layout = self.shape_until(scroll_end);
|
||||
let total_layout = self.shape_until(font_system, scroll_end);
|
||||
|
||||
self.scroll = cmp::max(0, cmp::min(total_layout - (lines - 1), self.scroll));
|
||||
}
|
||||
|
|
@ -473,26 +466,22 @@ impl<'a> Buffer<'a> {
|
|||
LayoutCursor::new(cursor.line, 0, 0)
|
||||
}
|
||||
|
||||
/// Get [`FontSystem`] used by this [`Buffer`]
|
||||
pub fn font_system(&self) -> &'a FontSystem {
|
||||
self.font_system
|
||||
pub(crate) fn line_shape(
|
||||
&mut self,
|
||||
font_system: &FontSystem,
|
||||
line_i: usize,
|
||||
) -> Option<&ShapeLine> {
|
||||
let line = self.lines.get_mut(line_i)?;
|
||||
Some(line.shape(font_system))
|
||||
}
|
||||
|
||||
/// Shape the provided line index and return the result
|
||||
pub fn line_shape(&mut self, line_i: usize) -> Option<&ShapeLine> {
|
||||
pub(crate) fn line_layout(
|
||||
&mut self,
|
||||
font_system: &FontSystem,
|
||||
line_i: usize,
|
||||
) -> Option<&[LayoutLine]> {
|
||||
let line = self.lines.get_mut(line_i)?;
|
||||
Some(line.shape(self.font_system))
|
||||
}
|
||||
|
||||
/// Lay out the provided line index and return the result
|
||||
pub fn line_layout(&mut self, line_i: usize) -> Option<&[LayoutLine]> {
|
||||
let line = self.lines.get_mut(line_i)?;
|
||||
Some(line.layout(
|
||||
self.font_system,
|
||||
self.metrics.font_size,
|
||||
self.width,
|
||||
self.wrap,
|
||||
))
|
||||
Some(line.layout(font_system, self.metrics.font_size, self.width, self.wrap))
|
||||
}
|
||||
|
||||
/// Get the current [`Metrics`]
|
||||
|
|
@ -500,17 +489,12 @@ impl<'a> Buffer<'a> {
|
|||
self.metrics
|
||||
}
|
||||
|
||||
/// Set the current [`Metrics`]
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Will panic if `metrics.font_size` is zero.
|
||||
pub fn set_metrics(&mut self, metrics: Metrics) {
|
||||
fn set_metrics(&mut self, font_system: &FontSystem, metrics: Metrics) {
|
||||
if metrics != self.metrics {
|
||||
assert_ne!(metrics.font_size, 0.0, "font size cannot be 0");
|
||||
self.metrics = metrics;
|
||||
self.relayout();
|
||||
self.shape_until_scroll();
|
||||
self.relayout(font_system);
|
||||
self.shape_until_scroll(font_system);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -519,12 +503,11 @@ impl<'a> Buffer<'a> {
|
|||
self.wrap
|
||||
}
|
||||
|
||||
/// Set the current [`Wrap`]
|
||||
pub fn set_wrap(&mut self, wrap: Wrap) {
|
||||
pub(crate) fn set_wrap(&mut self, font_system: &FontSystem, wrap: Wrap) {
|
||||
if wrap != self.wrap {
|
||||
self.wrap = wrap;
|
||||
self.relayout();
|
||||
self.shape_until_scroll();
|
||||
self.relayout(font_system);
|
||||
self.shape_until_scroll(font_system);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,16 +516,15 @@ impl<'a> Buffer<'a> {
|
|||
(self.width, self.height)
|
||||
}
|
||||
|
||||
/// Set the current buffer dimensions
|
||||
pub fn set_size(&mut self, width: f32, height: f32) {
|
||||
pub(crate) fn set_size(&mut self, font_system: &FontSystem, width: f32, height: f32) {
|
||||
let clamped_width = width.max(0.0);
|
||||
let clamped_height = height.max(0.0);
|
||||
|
||||
if clamped_width != self.width || clamped_height != self.height {
|
||||
self.width = clamped_width;
|
||||
self.height = clamped_height;
|
||||
self.relayout();
|
||||
self.shape_until_scroll();
|
||||
self.relayout(font_system);
|
||||
self.shape_until_scroll(font_system);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -564,8 +546,7 @@ impl<'a> Buffer<'a> {
|
|||
(self.height / self.metrics.line_height) as i32
|
||||
}
|
||||
|
||||
/// Set text of buffer, using provided attributes for each line by default
|
||||
pub fn set_text(&mut self, text: &str, attrs: Attrs<'a>) {
|
||||
pub(crate) fn set_text(&mut self, font_system: &FontSystem, text: &str, attrs: Attrs) {
|
||||
self.lines.clear();
|
||||
for line in text.lines() {
|
||||
self.lines
|
||||
|
|
@ -579,7 +560,7 @@ impl<'a> Buffer<'a> {
|
|||
|
||||
self.scroll = 0;
|
||||
|
||||
self.shape_until_scroll();
|
||||
self.shape_until_scroll(font_system);
|
||||
}
|
||||
|
||||
/// True if a redraw is needed
|
||||
|
|
@ -593,7 +574,7 @@ impl<'a> Buffer<'a> {
|
|||
}
|
||||
|
||||
/// Get the visible layout runs for rendering and other tasks
|
||||
pub fn layout_runs<'b>(&'b self) -> LayoutRunIter<'a, 'b> {
|
||||
pub fn layout_runs(&self) -> LayoutRunIter {
|
||||
LayoutRunIter::new(self)
|
||||
}
|
||||
|
||||
|
|
@ -698,10 +679,14 @@ impl<'a> Buffer<'a> {
|
|||
new_cursor_opt
|
||||
}
|
||||
|
||||
/// Draw the buffer
|
||||
#[cfg(feature = "swash")]
|
||||
pub fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, mut f: F)
|
||||
where
|
||||
pub(crate) fn draw<F>(
|
||||
&self,
|
||||
font_system: &FontSystem,
|
||||
cache: &mut crate::SwashCache,
|
||||
color: Color,
|
||||
mut f: F,
|
||||
) where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
for run in self.layout_runs() {
|
||||
|
|
@ -713,10 +698,70 @@ impl<'a> Buffer<'a> {
|
|||
None => color,
|
||||
};
|
||||
|
||||
cache.with_pixels(self.font_system, cache_key, glyph_color, |x, y, color| {
|
||||
cache.with_pixels(font_system, cache_key, glyph_color, |x, y, color| {
|
||||
f(x_int + x, run.line_y as i32 + y_int + y, 1, 1, color);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BorrowedWithFontSystem<'a, Buffer> {
|
||||
/// Pre-shape lines in the buffer, up to `lines`, return actual number of layout lines
|
||||
pub fn shape_until(&mut self, lines: i32) -> i32 {
|
||||
self.inner.shape_until(self.font_system, lines)
|
||||
}
|
||||
|
||||
/// Shape lines until cursor, also scrolling to include cursor in view
|
||||
pub fn shape_until_cursor(&mut self, cursor: Cursor) {
|
||||
self.inner.shape_until_cursor(self.font_system, cursor);
|
||||
}
|
||||
|
||||
/// Shape lines until scroll
|
||||
pub fn shape_until_scroll(&mut self) {
|
||||
self.inner.shape_until_scroll(self.font_system);
|
||||
}
|
||||
|
||||
/// Shape the provided line index and return the result
|
||||
pub fn line_shape(&mut self, line_i: usize) -> Option<&ShapeLine> {
|
||||
self.inner.line_shape(self.font_system, line_i)
|
||||
}
|
||||
|
||||
/// Lay out the provided line index and return the result
|
||||
pub fn line_layout(&mut self, line_i: usize) -> Option<&[LayoutLine]> {
|
||||
self.inner.line_layout(self.font_system, line_i)
|
||||
}
|
||||
|
||||
/// Set the current [`Metrics`]
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Will panic if `metrics.font_size` is zero.
|
||||
pub fn set_metrics(&mut self, metrics: Metrics) {
|
||||
self.inner.set_metrics(self.font_system, metrics);
|
||||
}
|
||||
|
||||
/// Set the current [`Wrap`]
|
||||
pub fn set_wrap(&mut self, wrap: Wrap) {
|
||||
self.inner.set_wrap(self.font_system, wrap);
|
||||
}
|
||||
|
||||
/// Set the current buffer dimensions
|
||||
pub fn set_size(&mut self, width: f32, height: f32) {
|
||||
self.inner.set_size(self.font_system, width, height);
|
||||
}
|
||||
|
||||
/// Set text of buffer, using provided attributes for each line by default
|
||||
pub fn set_text(&mut self, text: &str, attrs: Attrs) {
|
||||
self.inner.set_text(self.font_system, text, attrs);
|
||||
}
|
||||
|
||||
/// Draw the buffer
|
||||
#[cfg(feature = "swash")]
|
||||
pub fn draw<F>(&self, cache: &mut crate::SwashCache, color: Color, f: F)
|
||||
where
|
||||
F: FnMut(i32, i32, u32, u32, Color),
|
||||
{
|
||||
self.inner.draw(self.font_system, cache, color, f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue