move ShapeBuffer to FontSystem
This commit is contained in:
parent
0935f549ee
commit
9dc024616b
5 changed files with 69 additions and 186 deletions
|
|
@ -1,14 +1,12 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
use alloc::{string::String, vec::Vec};
|
|
||||||
use core::{cmp, fmt};
|
use core::{cmp, fmt};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Affinity, Align, Attrs, AttrsList, BidiParagraphs, BorrowedWithFontSystem, BufferLine, Color,
|
Affinity, Align, Attrs, AttrsList, BidiParagraphs, BorrowedWithFontSystem, BufferLine, Color,
|
||||||
Cursor, FontSystem, LayoutCursor, LayoutGlyph, LayoutLine, LineEnding, LineIter, Motion,
|
Cursor, FontSystem, LayoutCursor, LayoutGlyph, LayoutLine, LineEnding, LineIter, Motion,
|
||||||
Scroll, ShapeBuffer, ShapeLine, Shaping, Wrap,
|
Scroll, ShapeLine, Shaping, Wrap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A line of visible text for rendering
|
/// A line of visible text for rendering
|
||||||
|
|
@ -213,9 +211,6 @@ pub struct Buffer {
|
||||||
wrap: Wrap,
|
wrap: Wrap,
|
||||||
monospace_width: Option<f32>,
|
monospace_width: Option<f32>,
|
||||||
tab_width: u16,
|
tab_width: u16,
|
||||||
|
|
||||||
/// Scratch buffer for shaping and laying out.
|
|
||||||
scratch: ShapeBuffer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Buffer {
|
impl Clone for Buffer {
|
||||||
|
|
@ -230,7 +225,6 @@ impl Clone for Buffer {
|
||||||
wrap: self.wrap,
|
wrap: self.wrap,
|
||||||
monospace_width: self.monospace_width,
|
monospace_width: self.monospace_width,
|
||||||
tab_width: self.tab_width,
|
tab_width: self.tab_width,
|
||||||
scratch: ShapeBuffer::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +251,6 @@ impl Buffer {
|
||||||
scroll: Scroll::default(),
|
scroll: Scroll::default(),
|
||||||
redraw: false,
|
redraw: false,
|
||||||
wrap: Wrap::WordOrGlyph,
|
wrap: Wrap::WordOrGlyph,
|
||||||
scratch: ShapeBuffer::default(),
|
|
||||||
monospace_width: None,
|
monospace_width: None,
|
||||||
tab_width: 8,
|
tab_width: 8,
|
||||||
}
|
}
|
||||||
|
|
@ -292,8 +285,7 @@ impl Buffer {
|
||||||
for line in &mut self.lines {
|
for line in &mut self.lines {
|
||||||
if line.shape_opt().is_some() {
|
if line.shape_opt().is_some() {
|
||||||
line.reset_layout();
|
line.reset_layout();
|
||||||
line.layout_in_buffer(
|
line.layout(
|
||||||
&mut self.scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
self.metrics.font_size,
|
self.metrics.font_size,
|
||||||
self.width_opt,
|
self.width_opt,
|
||||||
|
|
@ -521,7 +513,7 @@ impl Buffer {
|
||||||
line_i: usize,
|
line_i: usize,
|
||||||
) -> Option<&ShapeLine> {
|
) -> Option<&ShapeLine> {
|
||||||
let line = self.lines.get_mut(line_i)?;
|
let line = self.lines.get_mut(line_i)?;
|
||||||
Some(line.shape_in_buffer(&mut self.scratch, font_system, self.tab_width))
|
Some(line.shape(font_system, self.tab_width))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lay out the provided line index and return the result
|
/// Lay out the provided line index and return the result
|
||||||
|
|
@ -531,8 +523,7 @@ impl Buffer {
|
||||||
line_i: usize,
|
line_i: usize,
|
||||||
) -> Option<&[LayoutLine]> {
|
) -> Option<&[LayoutLine]> {
|
||||||
let line = self.lines.get_mut(line_i)?;
|
let line = self.lines.get_mut(line_i)?;
|
||||||
Some(line.layout_in_buffer(
|
Some(line.layout(
|
||||||
&mut self.scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
self.metrics.font_size,
|
self.metrics.font_size,
|
||||||
self.width_opt,
|
self.width_opt,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
use alloc::{string::String, vec::Vec};
|
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Align, Attrs, AttrsList, Cached, FontSystem, LayoutLine, LineEnding, ShapeBuffer, ShapeLine,
|
Align, Attrs, AttrsList, Cached, FontSystem, LayoutLine, LineEnding, ShapeLine, Shaping, Wrap,
|
||||||
Shaping, Wrap,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A line (or paragraph) of text that is shaped and laid out
|
/// A line (or paragraph) of text that is shaped and laid out
|
||||||
|
|
@ -205,23 +202,12 @@ impl BufferLine {
|
||||||
|
|
||||||
/// Shape line, will cache results
|
/// Shape line, will cache results
|
||||||
pub fn shape(&mut self, font_system: &mut FontSystem, tab_width: u16) -> &ShapeLine {
|
pub fn shape(&mut self, font_system: &mut FontSystem, tab_width: u16) -> &ShapeLine {
|
||||||
self.shape_in_buffer(&mut ShapeBuffer::default(), font_system, tab_width)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shape a line using a pre-existing shape buffer, will cache results
|
|
||||||
pub fn shape_in_buffer(
|
|
||||||
&mut self,
|
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
|
||||||
tab_width: u16,
|
|
||||||
) -> &ShapeLine {
|
|
||||||
if self.shape_opt.is_unused() {
|
if self.shape_opt.is_unused() {
|
||||||
let mut line = self
|
let mut line = self
|
||||||
.shape_opt
|
.shape_opt
|
||||||
.take_unused()
|
.take_unused()
|
||||||
.unwrap_or_else(ShapeLine::empty);
|
.unwrap_or_else(ShapeLine::empty);
|
||||||
line.build_in_buffer(
|
line.build(
|
||||||
scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
&self.text,
|
&self.text,
|
||||||
&self.attrs_list,
|
&self.attrs_list,
|
||||||
|
|
@ -248,28 +234,6 @@ impl BufferLine {
|
||||||
wrap: Wrap,
|
wrap: Wrap,
|
||||||
match_mono_width: Option<f32>,
|
match_mono_width: Option<f32>,
|
||||||
tab_width: u16,
|
tab_width: u16,
|
||||||
) -> &[LayoutLine] {
|
|
||||||
self.layout_in_buffer(
|
|
||||||
&mut ShapeBuffer::default(),
|
|
||||||
font_system,
|
|
||||||
font_size,
|
|
||||||
width_opt,
|
|
||||||
wrap,
|
|
||||||
match_mono_width,
|
|
||||||
tab_width,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Layout a line using a pre-existing shape buffer, will cache results
|
|
||||||
pub fn layout_in_buffer(
|
|
||||||
&mut self,
|
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
|
||||||
font_size: f32,
|
|
||||||
width_opt: Option<f32>,
|
|
||||||
wrap: Wrap,
|
|
||||||
match_mono_width: Option<f32>,
|
|
||||||
tab_width: u16,
|
|
||||||
) -> &[LayoutLine] {
|
) -> &[LayoutLine] {
|
||||||
if self.layout_opt.is_unused() {
|
if self.layout_opt.is_unused() {
|
||||||
let align = self.align;
|
let align = self.align;
|
||||||
|
|
@ -277,9 +241,9 @@ impl BufferLine {
|
||||||
.layout_opt
|
.layout_opt
|
||||||
.take_unused()
|
.take_unused()
|
||||||
.unwrap_or_else(|| Vec::with_capacity(1));
|
.unwrap_or_else(|| Vec::with_capacity(1));
|
||||||
let shape = self.shape_in_buffer(scratch, font_system, tab_width);
|
let shape = self.shape(font_system, tab_width);
|
||||||
shape.layout_to_buffer(
|
shape.layout_to_buffer(
|
||||||
scratch,
|
&mut font_system.shape_buffer,
|
||||||
font_size,
|
font_size,
|
||||||
width_opt,
|
width_opt,
|
||||||
wrap,
|
wrap,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use alloc::vec::Vec;
|
||||||
use fontdb::Family;
|
use fontdb::Family;
|
||||||
use unicode_script::Script;
|
use unicode_script::Script;
|
||||||
|
|
||||||
use crate::{Font, FontMatchKey, FontSystem, ShapePlanCache};
|
use crate::{Font, FontMatchKey, FontSystem, ShapeBuffer, ShapePlanCache};
|
||||||
|
|
||||||
use self::platform::*;
|
use self::platform::*;
|
||||||
|
|
||||||
|
|
@ -119,8 +119,11 @@ impl<'a> FontFallbackIter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shape_plan_cache(&mut self) -> &mut ShapePlanCache {
|
pub fn shape_caches(&mut self) -> (&mut ShapeBuffer, &mut ShapePlanCache) {
|
||||||
self.font_system.shape_plan_cache()
|
(
|
||||||
|
&mut self.font_system.shape_buffer,
|
||||||
|
&mut self.font_system.shape_plan_cache,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn face_contains_family(&self, id: fontdb::ID, family_name: &str) -> bool {
|
fn face_contains_family(&self, id: fontdb::ID, family_name: &str) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{Attrs, Font, FontMatchAttrs, HashMap, ShapePlanCache};
|
use crate::{Attrs, Font, FontMatchAttrs, HashMap, ShapeBuffer, ShapePlanCache};
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
@ -101,7 +101,10 @@ pub struct FontSystem {
|
||||||
font_matches_cache: HashMap<FontMatchAttrs, Arc<Vec<FontMatchKey>>>,
|
font_matches_cache: HashMap<FontMatchAttrs, Arc<Vec<FontMatchKey>>>,
|
||||||
|
|
||||||
/// Cache for rustybuzz shape plans.
|
/// Cache for rustybuzz shape plans.
|
||||||
shape_plan_cache: ShapePlanCache,
|
pub(crate) shape_plan_cache: ShapePlanCache,
|
||||||
|
|
||||||
|
/// Scratch buffer for shaping and laying out.
|
||||||
|
pub(crate) shape_buffer: ShapeBuffer,
|
||||||
|
|
||||||
/// Cache for shaped runs
|
/// Cache for shaped runs
|
||||||
#[cfg(feature = "shape-run-cache")]
|
#[cfg(feature = "shape-run-cache")]
|
||||||
|
|
@ -171,6 +174,7 @@ impl FontSystem {
|
||||||
shape_plan_cache: ShapePlanCache::default(),
|
shape_plan_cache: ShapePlanCache::default(),
|
||||||
#[cfg(feature = "shape-run-cache")]
|
#[cfg(feature = "shape-run-cache")]
|
||||||
shape_run_cache: crate::ShapeRunCache::default(),
|
shape_run_cache: crate::ShapeRunCache::default(),
|
||||||
|
shape_buffer: ShapeBuffer::default(),
|
||||||
};
|
};
|
||||||
ret.cache_fonts(cloned_monospace_font_ids.clone());
|
ret.cache_fonts(cloned_monospace_font_ids.clone());
|
||||||
cloned_monospace_font_ids.into_iter().for_each(|id| {
|
cloned_monospace_font_ids.into_iter().for_each(|id| {
|
||||||
|
|
@ -196,11 +200,6 @@ impl FontSystem {
|
||||||
&self.db
|
&self.db
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the shape plan cache.
|
|
||||||
pub(crate) fn shape_plan_cache(&mut self) -> &mut ShapePlanCache {
|
|
||||||
&mut self.shape_plan_cache
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a mutable reference to the database.
|
/// Get a mutable reference to the database.
|
||||||
pub fn db_mut(&mut self) -> &mut fontdb::Database {
|
pub fn db_mut(&mut self) -> &mut fontdb::Database {
|
||||||
self.font_matches_cache.clear();
|
self.font_matches_cache.clear();
|
||||||
|
|
|
||||||
172
src/shape.rs
172
src/shape.rs
|
|
@ -40,7 +40,6 @@ pub enum Shaping {
|
||||||
impl Shaping {
|
impl Shaping {
|
||||||
fn run(
|
fn run(
|
||||||
self,
|
self,
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
glyphs: &mut Vec<ShapeGlyph>,
|
glyphs: &mut Vec<ShapeGlyph>,
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
|
@ -54,7 +53,6 @@ impl Shaping {
|
||||||
Self::Basic => shape_skip(font_system, glyphs, line, attrs_list, start_run, end_run),
|
Self::Basic => shape_skip(font_system, glyphs, line, attrs_list, start_run, end_run),
|
||||||
#[cfg(not(feature = "shape-run-cache"))]
|
#[cfg(not(feature = "shape-run-cache"))]
|
||||||
Self::Advanced => shape_run(
|
Self::Advanced => shape_run(
|
||||||
scratch,
|
|
||||||
glyphs,
|
glyphs,
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
|
|
@ -65,7 +63,6 @@ impl Shaping {
|
||||||
),
|
),
|
||||||
#[cfg(feature = "shape-run-cache")]
|
#[cfg(feature = "shape-run-cache")]
|
||||||
Self::Advanced => shape_run_cached(
|
Self::Advanced => shape_run_cached(
|
||||||
scratch,
|
|
||||||
glyphs,
|
glyphs,
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
|
|
@ -109,8 +106,8 @@ impl fmt::Debug for ShapeBuffer {
|
||||||
|
|
||||||
fn shape_fallback(
|
fn shape_fallback(
|
||||||
scratch: &mut ShapeBuffer,
|
scratch: &mut ShapeBuffer,
|
||||||
glyphs: &mut Vec<ShapeGlyph>,
|
|
||||||
shape_plan_cache: &mut ShapePlanCache,
|
shape_plan_cache: &mut ShapePlanCache,
|
||||||
|
glyphs: &mut Vec<ShapeGlyph>,
|
||||||
font: &Font,
|
font: &Font,
|
||||||
line: &str,
|
line: &str,
|
||||||
attrs_list: &AttrsList,
|
attrs_list: &AttrsList,
|
||||||
|
|
@ -217,7 +214,6 @@ fn shape_fallback(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shape_run(
|
fn shape_run(
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
glyphs: &mut Vec<ShapeGlyph>,
|
glyphs: &mut Vec<ShapeGlyph>,
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
|
@ -228,7 +224,7 @@ fn shape_run(
|
||||||
) {
|
) {
|
||||||
// Re-use the previous script buffer if possible.
|
// Re-use the previous script buffer if possible.
|
||||||
let mut scripts = {
|
let mut scripts = {
|
||||||
let mut scripts = mem::take(&mut scratch.scripts);
|
let mut scripts = mem::take(&mut font_system.shape_buffer.scripts);
|
||||||
scripts.clear();
|
scripts.clear();
|
||||||
scripts
|
scripts
|
||||||
};
|
};
|
||||||
|
|
@ -261,17 +257,20 @@ fn shape_run(
|
||||||
let font = font_iter.next().expect("no default font found");
|
let font = font_iter.next().expect("no default font found");
|
||||||
|
|
||||||
let glyph_start = glyphs.len();
|
let glyph_start = glyphs.len();
|
||||||
let mut missing = shape_fallback(
|
let mut missing = {
|
||||||
scratch,
|
let (scratch, shape_plan_cache) = font_iter.shape_caches();
|
||||||
glyphs,
|
shape_fallback(
|
||||||
font_iter.shape_plan_cache(),
|
scratch,
|
||||||
&font,
|
shape_plan_cache,
|
||||||
line,
|
glyphs,
|
||||||
attrs_list,
|
&font,
|
||||||
start_run,
|
line,
|
||||||
end_run,
|
attrs_list,
|
||||||
span_rtl,
|
start_run,
|
||||||
);
|
end_run,
|
||||||
|
span_rtl,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
//TODO: improve performance!
|
//TODO: improve performance!
|
||||||
while !missing.is_empty() {
|
while !missing.is_empty() {
|
||||||
|
|
@ -285,10 +284,11 @@ fn shape_run(
|
||||||
font_iter.face_name(font.id())
|
font_iter.face_name(font.id())
|
||||||
);
|
);
|
||||||
let mut fb_glyphs = Vec::new();
|
let mut fb_glyphs = Vec::new();
|
||||||
|
let (scratch, shape_plan_cache) = font_iter.shape_caches();
|
||||||
let fb_missing = shape_fallback(
|
let fb_missing = shape_fallback(
|
||||||
scratch,
|
scratch,
|
||||||
|
shape_plan_cache,
|
||||||
&mut fb_glyphs,
|
&mut fb_glyphs,
|
||||||
font_iter.shape_plan_cache(),
|
|
||||||
&font,
|
&font,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
@ -362,12 +362,11 @@ fn shape_run(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Restore the scripts buffer.
|
// Restore the scripts buffer.
|
||||||
scratch.scripts = scripts;
|
font_system.shape_buffer.scripts = scripts;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "shape-run-cache")]
|
#[cfg(feature = "shape-run-cache")]
|
||||||
fn shape_run_cached(
|
fn shape_run_cached(
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
glyphs: &mut Vec<ShapeGlyph>,
|
glyphs: &mut Vec<ShapeGlyph>,
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
|
@ -413,7 +412,6 @@ fn shape_run_cached(
|
||||||
// Fill in cache if not already set
|
// Fill in cache if not already set
|
||||||
let mut cache_glyphs = Vec::new();
|
let mut cache_glyphs = Vec::new();
|
||||||
shape_run(
|
shape_run(
|
||||||
scratch,
|
|
||||||
&mut cache_glyphs,
|
&mut cache_glyphs,
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
|
|
@ -562,6 +560,8 @@ impl ShapeWord {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shape a word into a set of glyphs.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
|
@ -570,34 +570,9 @@ impl ShapeWord {
|
||||||
level: unicode_bidi::Level,
|
level: unicode_bidi::Level,
|
||||||
blank: bool,
|
blank: bool,
|
||||||
shaping: Shaping,
|
shaping: Shaping,
|
||||||
) -> Self {
|
|
||||||
Self::new_in_buffer(
|
|
||||||
&mut ShapeBuffer::default(),
|
|
||||||
font_system,
|
|
||||||
line,
|
|
||||||
attrs_list,
|
|
||||||
word_range,
|
|
||||||
level,
|
|
||||||
blank,
|
|
||||||
shaping,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shape a word into a set of glyphs, using a scratch buffer.
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn new_in_buffer(
|
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
|
||||||
line: &str,
|
|
||||||
attrs_list: &AttrsList,
|
|
||||||
word_range: Range<usize>,
|
|
||||||
level: unicode_bidi::Level,
|
|
||||||
blank: bool,
|
|
||||||
shaping: Shaping,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut empty = Self::empty();
|
let mut empty = Self::empty();
|
||||||
empty.build_in_buffer(
|
empty.build(
|
||||||
scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
@ -609,13 +584,12 @@ impl ShapeWord {
|
||||||
empty
|
empty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`Self::new_in_buffer`].
|
/// See [`Self::new`].
|
||||||
///
|
///
|
||||||
/// Reuses as much of the pre-existing internal allocations as possible.
|
/// Reuses as much of the pre-existing internal allocations as possible.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn build_in_buffer(
|
pub fn build(
|
||||||
&mut self,
|
&mut self,
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
attrs_list: &AttrsList,
|
attrs_list: &AttrsList,
|
||||||
|
|
@ -644,7 +618,6 @@ impl ShapeWord {
|
||||||
let attrs_egc = attrs_list.get_span(start_egc);
|
let attrs_egc = attrs_list.get_span(start_egc);
|
||||||
if !attrs.compatible(&attrs_egc) {
|
if !attrs.compatible(&attrs_egc) {
|
||||||
shaping.run(
|
shaping.run(
|
||||||
scratch,
|
|
||||||
&mut glyphs,
|
&mut glyphs,
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
|
|
@ -660,7 +633,6 @@ impl ShapeWord {
|
||||||
}
|
}
|
||||||
if start_run < word_range.end {
|
if start_run < word_range.end {
|
||||||
shaping.run(
|
shaping.run(
|
||||||
scratch,
|
|
||||||
&mut glyphs,
|
&mut glyphs,
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
|
|
@ -703,6 +675,7 @@ impl ShapeSpan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shape a span into a set of words.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
|
@ -711,33 +684,9 @@ impl ShapeSpan {
|
||||||
line_rtl: bool,
|
line_rtl: bool,
|
||||||
level: unicode_bidi::Level,
|
level: unicode_bidi::Level,
|
||||||
shaping: Shaping,
|
shaping: Shaping,
|
||||||
) -> Self {
|
|
||||||
Self::new_in_buffer(
|
|
||||||
&mut ShapeBuffer::default(),
|
|
||||||
font_system,
|
|
||||||
line,
|
|
||||||
attrs_list,
|
|
||||||
span_range,
|
|
||||||
line_rtl,
|
|
||||||
level,
|
|
||||||
shaping,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shape a span into a set of words, using a scratch buffer.
|
|
||||||
pub fn new_in_buffer(
|
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
|
||||||
line: &str,
|
|
||||||
attrs_list: &AttrsList,
|
|
||||||
span_range: Range<usize>,
|
|
||||||
line_rtl: bool,
|
|
||||||
level: unicode_bidi::Level,
|
|
||||||
shaping: Shaping,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut empty = Self::empty();
|
let mut empty = Self::empty();
|
||||||
empty.build_in_buffer(
|
empty.build(
|
||||||
scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
@ -749,12 +698,11 @@ impl ShapeSpan {
|
||||||
empty
|
empty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`Self::new_in_buffer`].
|
/// See [`Self::new`].
|
||||||
///
|
///
|
||||||
/// Reuses as much of the pre-existing internal allocations as possible.
|
/// Reuses as much of the pre-existing internal allocations as possible.
|
||||||
pub fn build_in_buffer(
|
pub fn build(
|
||||||
&mut self,
|
&mut self,
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
attrs_list: &AttrsList,
|
attrs_list: &AttrsList,
|
||||||
|
|
@ -774,11 +722,11 @@ impl ShapeSpan {
|
||||||
let mut words = mem::take(&mut self.words);
|
let mut words = mem::take(&mut self.words);
|
||||||
|
|
||||||
// Cache the shape words in reverse order so they can be popped for reuse in the same order.
|
// Cache the shape words in reverse order so they can be popped for reuse in the same order.
|
||||||
let mut cached_words = mem::take(&mut scratch.words);
|
let mut cached_words = mem::take(&mut font_system.shape_buffer.words);
|
||||||
cached_words.clear();
|
cached_words.clear();
|
||||||
if line_rtl != level.is_rtl() {
|
if line_rtl != level.is_rtl() {
|
||||||
// Un-reverse previous words so the internal glyph counts match accurately when rewriting memory.
|
// Un-reverse previous words so the internal glyph counts match accurately when rewriting memory.
|
||||||
cached_words.extend(words.drain(..));
|
cached_words.append(&mut words);
|
||||||
} else {
|
} else {
|
||||||
cached_words.extend(words.drain(..).rev());
|
cached_words.extend(words.drain(..).rev());
|
||||||
}
|
}
|
||||||
|
|
@ -799,8 +747,7 @@ impl ShapeSpan {
|
||||||
}
|
}
|
||||||
if start_word < start_lb {
|
if start_word < start_lb {
|
||||||
let mut word = cached_words.pop().unwrap_or_else(ShapeWord::empty);
|
let mut word = cached_words.pop().unwrap_or_else(ShapeWord::empty);
|
||||||
word.build_in_buffer(
|
word.build(
|
||||||
scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
@ -815,8 +762,7 @@ impl ShapeSpan {
|
||||||
for (i, c) in span[start_lb..end_lb].char_indices() {
|
for (i, c) in span[start_lb..end_lb].char_indices() {
|
||||||
// assert!(c.is_whitespace());
|
// assert!(c.is_whitespace());
|
||||||
let mut word = cached_words.pop().unwrap_or_else(ShapeWord::empty);
|
let mut word = cached_words.pop().unwrap_or_else(ShapeWord::empty);
|
||||||
word.build_in_buffer(
|
word.build(
|
||||||
scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
@ -848,7 +794,7 @@ impl ShapeSpan {
|
||||||
self.words = words;
|
self.words = words;
|
||||||
|
|
||||||
// Cache buffer for future reuse.
|
// Cache buffer for future reuse.
|
||||||
scratch.words = cached_words;
|
font_system.shape_buffer.words = cached_words;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -890,9 +836,12 @@ impl ShapeLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shape a line into a set of spans, using a scratch buffer. If [`unicode_bidi::BidiInfo`]
|
||||||
|
/// detects multiple paragraphs, they will be joined.
|
||||||
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Will panic if `line` contains more than one paragraph.
|
/// Will panic if `line` contains multiple paragraphs that do not have matching direction
|
||||||
pub fn new(
|
pub fn new(
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
|
@ -900,41 +849,20 @@ impl ShapeLine {
|
||||||
shaping: Shaping,
|
shaping: Shaping,
|
||||||
tab_width: u16,
|
tab_width: u16,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_in_buffer(
|
let mut empty = Self::empty();
|
||||||
&mut ShapeBuffer::default(),
|
empty.build(font_system, line, attrs_list, shaping, tab_width);
|
||||||
font_system,
|
empty
|
||||||
line,
|
|
||||||
attrs_list,
|
|
||||||
shaping,
|
|
||||||
tab_width,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shape a line into a set of spans, using a scratch buffer. If [`unicode_bidi::BidiInfo`]
|
/// See [`Self::new`].
|
||||||
/// detects multiple paragraphs, they will be joined.
|
///
|
||||||
|
/// Reuses as much of the pre-existing internal allocations as possible.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Will panic if `line` contains multiple paragraphs that do not have matching direction
|
/// Will panic if `line` contains multiple paragraphs that do not have matching direction
|
||||||
pub fn new_in_buffer(
|
pub fn build(
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
|
||||||
line: &str,
|
|
||||||
attrs_list: &AttrsList,
|
|
||||||
shaping: Shaping,
|
|
||||||
tab_width: u16,
|
|
||||||
) -> Self {
|
|
||||||
let mut empty = Self::empty();
|
|
||||||
empty.build_in_buffer(scratch, font_system, line, attrs_list, shaping, tab_width);
|
|
||||||
empty
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [`Self::new_in_buffer`].
|
|
||||||
///
|
|
||||||
/// Reuses as much of the pre-existing internal allocations as possible.
|
|
||||||
pub fn build_in_buffer(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
scratch: &mut ShapeBuffer,
|
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
line: &str,
|
line: &str,
|
||||||
attrs_list: &AttrsList,
|
attrs_list: &AttrsList,
|
||||||
|
|
@ -944,7 +872,7 @@ impl ShapeLine {
|
||||||
let mut spans = mem::take(&mut self.spans);
|
let mut spans = mem::take(&mut self.spans);
|
||||||
|
|
||||||
// Cache the shape spans in reverse order so they can be popped for reuse in the same order.
|
// Cache the shape spans in reverse order so they can be popped for reuse in the same order.
|
||||||
let mut cached_spans = mem::take(&mut scratch.spans);
|
let mut cached_spans = mem::take(&mut font_system.shape_buffer.spans);
|
||||||
cached_spans.clear();
|
cached_spans.clear();
|
||||||
cached_spans.extend(spans.drain(..).rev());
|
cached_spans.extend(spans.drain(..).rev());
|
||||||
|
|
||||||
|
|
@ -979,8 +907,7 @@ impl ShapeLine {
|
||||||
if new_level != run_level {
|
if new_level != run_level {
|
||||||
// End of the previous run, start of a new one.
|
// End of the previous run, start of a new one.
|
||||||
let mut span = cached_spans.pop().unwrap_or_else(ShapeSpan::empty);
|
let mut span = cached_spans.pop().unwrap_or_else(ShapeSpan::empty);
|
||||||
span.build_in_buffer(
|
span.build(
|
||||||
scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
@ -995,8 +922,7 @@ impl ShapeLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut span = cached_spans.pop().unwrap_or_else(ShapeSpan::empty);
|
let mut span = cached_spans.pop().unwrap_or_else(ShapeSpan::empty);
|
||||||
span.build_in_buffer(
|
span.build(
|
||||||
scratch,
|
|
||||||
font_system,
|
font_system,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
@ -1029,7 +955,7 @@ impl ShapeLine {
|
||||||
self.metrics_opt = attrs_list.defaults().metrics_opt.map(|x| x.into());
|
self.metrics_opt = attrs_list.defaults().metrics_opt.map(|x| x.into());
|
||||||
|
|
||||||
// Return the buffer for later reuse.
|
// Return the buffer for later reuse.
|
||||||
scratch.spans = cached_spans;
|
font_system.shape_buffer.spans = cached_spans;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A modified version of first part of unicode_bidi::bidi_info::visual_run
|
// A modified version of first part of unicode_bidi::bidi_info::visual_run
|
||||||
|
|
@ -1705,7 +1631,7 @@ impl ShapeLine {
|
||||||
|
|
||||||
// Restore the buffer to the scratch set to prevent reallocations.
|
// Restore the buffer to the scratch set to prevent reallocations.
|
||||||
scratch.visual_lines = visual_lines;
|
scratch.visual_lines = visual_lines;
|
||||||
scratch.visual_lines.extend(cached_visual_lines.drain(..));
|
scratch.visual_lines.append(&mut cached_visual_lines);
|
||||||
scratch.cached_visual_lines = cached_visual_lines;
|
scratch.cached_visual_lines = cached_visual_lines;
|
||||||
scratch.glyph_sets = cached_glyph_sets;
|
scratch.glyph_sets = cached_glyph_sets;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue