Replace skip_shaping boolean with Shaping enum

This commit is contained in:
Héctor Ramón Jiménez 2023-04-21 20:24:44 +02:00
parent ad111a1df1
commit 0f055c0a13
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
5 changed files with 67 additions and 62 deletions

View file

@ -12,7 +12,7 @@ use unicode_segmentation::UnicodeSegmentation;
use crate::Color; use crate::Color;
use crate::{ use crate::{
Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, FontSystem, LayoutGlyph, LayoutLine, Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, FontSystem, LayoutGlyph, LayoutLine,
ShapeLine, Wrap, ShapeLine, Shaping, Wrap,
}; };
/// Current cursor location /// Current cursor location
@ -331,7 +331,7 @@ impl Buffer {
redraw: false, redraw: false,
wrap: Wrap::Word, wrap: Wrap::Word,
}; };
buffer.set_text(font_system, "", Attrs::new(), true); buffer.set_text(font_system, "", Attrs::new(), Shaping::Basic);
buffer buffer
} }
@ -567,14 +567,14 @@ impl Buffer {
font_system: &mut FontSystem, font_system: &mut FontSystem,
text: &str, text: &str,
attrs: Attrs, attrs: Attrs,
skip_shaping: bool, shaping: Shaping,
) { ) {
self.lines.clear(); self.lines.clear();
for line in text.lines() { for line in text.lines() {
self.lines.push(BufferLine::new( self.lines.push(BufferLine::new(
line.to_string(), line.to_string(),
AttrsList::new(attrs), AttrsList::new(attrs),
skip_shaping, shaping,
)); ));
} }
// Make sure there is always one line // Make sure there is always one line
@ -582,7 +582,7 @@ impl Buffer {
self.lines.push(BufferLine::new( self.lines.push(BufferLine::new(
String::new(), String::new(),
AttrsList::new(attrs), AttrsList::new(attrs),
skip_shaping, shaping,
)); ));
} }
@ -781,9 +781,8 @@ impl<'a> BorrowedWithFontSystem<'a, Buffer> {
} }
/// Set text of buffer, using provided attributes for each line by default /// Set text of buffer, using provided attributes for each line by default
pub fn set_text(&mut self, text: &str, attrs: Attrs, skip_shaping: bool) { pub fn set_text(&mut self, text: &str, attrs: Attrs, shaping: Shaping) {
self.inner self.inner.set_text(self.font_system, text, attrs, shaping);
.set_text(self.font_system, text, attrs, skip_shaping);
} }
/// Draw the buffer /// Draw the buffer

View file

@ -1,7 +1,7 @@
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec}; use alloc::{string::String, vec::Vec};
use crate::{Align, AttrsList, FontSystem, LayoutLine, ShapeLine, Wrap}; use crate::{Align, AttrsList, FontSystem, LayoutLine, ShapeLine, 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
pub struct BufferLine { pub struct BufferLine {
@ -12,14 +12,14 @@ pub struct BufferLine {
align: Option<Align>, align: Option<Align>,
shape_opt: Option<ShapeLine>, shape_opt: Option<ShapeLine>,
layout_opt: Option<Vec<LayoutLine>>, layout_opt: Option<Vec<LayoutLine>>,
skip_shaping: bool, shaping: Shaping,
} }
impl BufferLine { impl BufferLine {
/// Create a new line with the given text and attributes list /// Create a new line with the given text and attributes list
/// Cached shaping and layout can be done using the [`Self::shape`] and /// Cached shaping and layout can be done using the [`Self::shape`] and
/// [`Self::layout`] functions /// [`Self::layout`] functions
pub fn new<T: Into<String>>(text: T, attrs_list: AttrsList, skip_shaping: bool) -> Self { pub fn new<T: Into<String>>(text: T, attrs_list: AttrsList, shaping: Shaping) -> Self {
Self { Self {
text: text.into(), text: text.into(),
attrs_list, attrs_list,
@ -27,7 +27,7 @@ impl BufferLine {
align: None, align: None,
shape_opt: None, shape_opt: None,
layout_opt: None, layout_opt: None,
skip_shaping, shaping,
} }
} }
@ -144,7 +144,7 @@ impl BufferLine {
let attrs_list = self.attrs_list.split_off(index); let attrs_list = self.attrs_list.split_off(index);
self.reset(); self.reset();
let mut new = Self::new(text, attrs_list, self.skip_shaping); let mut new = Self::new(text, attrs_list, self.shaping);
new.wrap = self.wrap; new.wrap = self.wrap;
new new
} }
@ -173,7 +173,7 @@ impl BufferLine {
font_system, font_system,
&self.text, &self.text,
&self.attrs_list, &self.attrs_list,
self.skip_shaping, self.shaping,
)); ));
self.layout_opt = None; self.layout_opt = None;
} }

View file

@ -12,6 +12,7 @@ use unicode_segmentation::UnicodeSegmentation;
use crate::Color; use crate::Color;
use crate::{ use crate::{
Action, Affinity, AttrsList, Buffer, BufferLine, Cursor, Edit, FontSystem, LayoutCursor, Action, Affinity, AttrsList, Buffer, BufferLine, Cursor, Edit, FontSystem, LayoutCursor,
Shaping,
}; };
/// A wrapper of [`Buffer`] for easy editing /// A wrapper of [`Buffer`] for easy editing
@ -245,7 +246,7 @@ impl Edit for Editor {
.strip_suffix(char::is_control) .strip_suffix(char::is_control)
.unwrap_or(data_line), .unwrap_or(data_line),
these_attrs, these_attrs,
false, Shaping::Advanced,
)); ));
} else { } else {
panic!("str::lines() did not yield any elements"); panic!("str::lines() did not yield any elements");
@ -257,7 +258,7 @@ impl Edit for Editor {
.strip_suffix(char::is_control) .strip_suffix(char::is_control)
.unwrap_or(data_line), .unwrap_or(data_line),
final_attrs.split_off(remaining_split_len), final_attrs.split_off(remaining_split_len),
false, Shaping::Advanced,
); );
tmp.append(after); tmp.append(after);
self.buffer.lines.insert(insert_line, tmp); self.buffer.lines.insert(insert_line, tmp);
@ -272,7 +273,7 @@ impl Edit for Editor {
.strip_suffix(char::is_control) .strip_suffix(char::is_control)
.unwrap_or(data_line), .unwrap_or(data_line),
final_attrs.split_off(remaining_split_len), final_attrs.split_off(remaining_split_len),
false, Shaping::Advanced,
); );
self.buffer.lines.insert(insert_line, tmp); self.buffer.lines.insert(insert_line, tmp);
self.cursor.line += 1; self.cursor.line += 1;

View file

@ -12,7 +12,7 @@
//! point, you can use the `SwashCache` to rasterize glyphs into either images or pixels. //! point, you can use the `SwashCache` to rasterize glyphs into either images or pixels.
//! //!
//! ``` //! ```
//! use cosmic_text::{Attrs, Color, FontSystem, SwashCache, Buffer, Metrics}; //! use cosmic_text::{Attrs, Color, FontSystem, SwashCache, Buffer, Metrics, Shaping};
//! //!
//! // A FontSystem provides access to detected system fonts, create one per application //! // A FontSystem provides access to detected system fonts, create one per application
//! let mut font_system = FontSystem::new(); //! let mut font_system = FontSystem::new();
@ -36,7 +36,7 @@
//! let attrs = Attrs::new(); //! let attrs = Attrs::new();
//! //!
//! // Add some text! //! // Add some text!
//! buffer.set_text("Hello, Rust! 🦀\n", attrs, false); //! buffer.set_text("Hello, Rust! 🦀\n", attrs, Shaping::Advanced);
//! //!
//! // Perform shaping as desired //! // Perform shaping as desired
//! buffer.shape_until_scroll(); //! buffer.shape_until_scroll();

View file

@ -11,6 +11,31 @@ use unicode_segmentation::UnicodeSegmentation;
use crate::fallback::FontFallbackIter; use crate::fallback::FontFallbackIter;
use crate::{Align, AttrsList, CacheKey, Color, Font, FontSystem, LayoutGlyph, LayoutLine, Wrap}; use crate::{Align, AttrsList, CacheKey, Color, Font, FontSystem, LayoutGlyph, LayoutLine, Wrap};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Shaping {
Basic,
Advanced,
}
impl Shaping {
fn run(
self,
font_system: &mut FontSystem,
line: &str,
attrs_list: &AttrsList,
start_run: usize,
end_run: usize,
span_rtl: bool,
) -> Vec<ShapeGlyph> {
match self {
Self::Basic => shape_skip(font_system, line, attrs_list, start_run, end_run),
Self::Advanced => {
shape_run(font_system, line, attrs_list, start_run, end_run, span_rtl)
}
}
}
}
fn shape_fallback( fn shape_fallback(
font: &Font, font: &Font,
line: &str, line: &str,
@ -321,7 +346,7 @@ impl ShapeWord {
word_range: Range<usize>, word_range: Range<usize>,
level: unicode_bidi::Level, level: unicode_bidi::Level,
blank: bool, blank: bool,
skip_shaping: bool, shaping: Shaping,
) -> Self { ) -> Self {
let word = &line[word_range.clone()]; let word = &line[word_range.clone()];
@ -341,24 +366,14 @@ 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) {
//TODO: more efficient //TODO: more efficient
if skip_shaping { glyphs.append(&mut shaping.run(
glyphs.append(&mut shape_skip( font_system,
font_system, line,
line, attrs_list,
attrs_list, start_run,
start_run, start_egc,
start_egc, span_rtl,
)); ));
} else {
glyphs.append(&mut shape_run(
font_system,
line,
attrs_list,
start_run,
start_egc,
span_rtl,
));
};
start_run = start_egc; start_run = start_egc;
attrs = attrs_egc; attrs = attrs_egc;
@ -366,24 +381,14 @@ impl ShapeWord {
} }
if start_run < word_range.end { if start_run < word_range.end {
//TODO: more efficient //TODO: more efficient
if skip_shaping { glyphs.append(&mut shaping.run(
glyphs.append(&mut shape_skip( font_system,
font_system, line,
line, attrs_list,
attrs_list, start_run,
start_run, word_range.end,
word_range.end, span_rtl,
)); ));
} else {
glyphs.append(&mut shape_run(
font_system,
line,
attrs_list,
start_run,
word_range.end,
span_rtl,
));
}
} }
let mut x_advance = 0.0; let mut x_advance = 0.0;
@ -416,7 +421,7 @@ impl ShapeSpan {
span_range: Range<usize>, span_range: Range<usize>,
line_rtl: bool, line_rtl: bool,
level: unicode_bidi::Level, level: unicode_bidi::Level,
skip_shaping: bool, shaping: Shaping,
) -> Self { ) -> Self {
let span = &line[span_range.start..span_range.end]; let span = &line[span_range.start..span_range.end];
@ -447,7 +452,7 @@ impl ShapeSpan {
(span_range.start + start_word)..(span_range.start + start_lb), (span_range.start + start_word)..(span_range.start + start_lb),
level, level,
false, false,
skip_shaping, shaping,
)); ));
} }
if start_lb < end_lb { if start_lb < end_lb {
@ -461,7 +466,7 @@ impl ShapeSpan {
..(span_range.start + start_lb + i + c.len_utf8()), ..(span_range.start + start_lb + i + c.len_utf8()),
level, level,
true, true,
skip_shaping, shaping,
)); ));
} }
} }
@ -508,7 +513,7 @@ impl ShapeLine {
font_system: &mut FontSystem, font_system: &mut FontSystem,
line: &str, line: &str,
attrs_list: &AttrsList, attrs_list: &AttrsList,
skip_shaping: bool, shaping: Shaping,
) -> Self { ) -> Self {
let mut spans = Vec::new(); let mut spans = Vec::new();
@ -545,7 +550,7 @@ impl ShapeLine {
start..i, start..i,
line_rtl, line_rtl,
run_level, run_level,
skip_shaping, shaping,
)); ));
start = i; start = i;
run_level = new_level; run_level = new_level;
@ -558,7 +563,7 @@ impl ShapeLine {
start..line_range.end, start..line_range.end,
line_rtl, line_rtl,
run_level, run_level,
skip_shaping, shaping,
)); ));
line_rtl line_rtl
}; };