diff --git a/Cargo.toml b/Cargo.toml index dbb829f5e..f50fcecb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -175,7 +175,7 @@ resolver = "2" [patch.crates-io.kas-text] git = "https://github.com/kas-gui/kas-text.git" -rev = "9797e78ad4664ae5055e8dab6067e40b215f6b3e" +rev = "efe15a6040edde83b64cb668c64da63b164abfd7" [patch.crates-io.impl-tools-lib] git = "https://github.com/kas-gui/impl-tools.git" diff --git a/crates/kas-core/src/draw/draw.rs b/crates/kas-core/src/draw/draw.rs index 0518b8c9b..b93933806 100644 --- a/crates/kas-core/src/draw/draw.rs +++ b/crates/kas-core/src/draw/draw.rs @@ -9,7 +9,7 @@ use super::{AnimationState, color::Rgba}; #[allow(unused)] use super::{DrawRounded, DrawRoundedImpl}; use super::{DrawShared, DrawSharedImpl, ImageId, PassId, PassType, SharedState, WindowCommon}; use crate::geom::{Offset, Quad, Rect, Vec2}; -use crate::text::{TextDisplay, format}; +use crate::text::{Forme, format}; use crate::theme::ColorsLinear; use std::any::Any; use std::time::Instant; @@ -132,7 +132,7 @@ impl<'a, DS: DrawSharedImpl> DrawIface<'a, DS> { &mut self, pos: Vec2, bounding_box: Quad, - text: &TextDisplay, + text: &Forme, theme: &ColorsLinear, col: Rgba, ) { @@ -268,7 +268,7 @@ pub trait Draw { &mut self, pos: Vec2, bounding_box: Quad, - text: &TextDisplay, + text: &Forme, theme: &ColorsLinear, tokens: &[(u32, format::Colors)], ) { @@ -285,7 +285,7 @@ pub trait Draw { &mut self, pos: Vec2, bounding_box: Quad, - text: &TextDisplay, + text: &Forme, theme: &ColorsLinear, decorations: &[(u32, format::Decoration)], ) { diff --git a/crates/kas-core/src/draw/draw_shared.rs b/crates/kas-core/src/draw/draw_shared.rs index 9434b7f63..8aac71e02 100644 --- a/crates/kas-core/src/draw/draw_shared.rs +++ b/crates/kas-core/src/draw/draw_shared.rs @@ -9,7 +9,7 @@ use super::{DrawImpl, PassId}; use crate::ActionRedraw; use crate::config::RasterConfig; use crate::geom::{Quad, Size, Vec2}; -use crate::text::{TextDisplay, format}; +use crate::text::{Forme, format}; use crate::theme::ColorsLinear; use std::any::Any; use std::num::NonZeroU32; @@ -200,7 +200,7 @@ pub trait DrawSharedImpl: Any { pass: PassId, pos: Vec2, bounding_box: Quad, - text: &TextDisplay, + text: &Forme, theme: &ColorsLinear, tokens: &[(u32, format::Colors)], ); @@ -215,7 +215,7 @@ pub trait DrawSharedImpl: Any { pass: PassId, pos: Vec2, bounding_box: Quad, - text: &TextDisplay, + text: &Forme, theme: &ColorsLinear, decorations: &[(u32, format::Decoration)], ); diff --git a/crates/kas-core/src/text/format.rs b/crates/kas-core/src/text/format.rs index 52ac2fb8f..1d13705a3 100644 --- a/crates/kas-core/src/text/format.rs +++ b/crates/kas-core/src/text/format.rs @@ -10,7 +10,7 @@ use std::num::NonZeroU32; use super::fonts::FontSelector; use crate::draw::color::{Rgba, Rgba8Srgb}; use crate::theme::ColorsLinear; -pub use kas_text::format::FontToken; +pub use kas_text::FontToken; #[cfg(feature = "markdown")] mod markdown; #[cfg(feature = "markdown")] pub use markdown::Markdown; @@ -171,7 +171,7 @@ pub trait FormattableText: std::cmp::PartialEq { /// /// These tokens are used to select the font and font size. /// Each text object has a configured - /// [font size][super::ConfiguredDisplay::set_font_size] and [`FontSelector`]; these + /// [font size][super::ConfiguredForme::set_font_size] and [`FontSelector`]; these /// values are passed as a reference (`dpem` and `font`). /// /// The iterator is expected to yield a stream of tokens such that diff --git a/crates/kas-core/src/text/display.rs b/crates/kas-core/src/text/forme.rs similarity index 78% rename from crates/kas-core/src/text/display.rs rename to crates/kas-core/src/text/forme.rs index 2ba497861..cb2502aa2 100644 --- a/crates/kas-core/src/text/display.rs +++ b/crates/kas-core/src/text/forme.rs @@ -15,10 +15,10 @@ use crate::text::*; use crate::theme::{DrawCx, SizeCx, TextClass}; use std::num::NonZeroUsize; -/// A [`TextDisplay`] plus configuration and state tracking +/// A [`Forme`] plus configuration and state tracking /// /// This struct contains: -/// - A [`TextDisplay`] +/// - A [`Forme`] /// - A [`FontSelector`] /// - Type-setting configuration. Values have reasonable defaults: /// - The font is derived from the [`TextClass`] by [`Self::configure`], @@ -28,10 +28,10 @@ use std::num::NonZeroUsize; /// - Default text direction and alignment is inferred from the text. /// /// This struct tracks the -/// [state of preparation][TextDisplay#status-of-preparation], but is unable to +/// [state of preparation][Forme#status-of-preparation], but is unable to /// perform the first step of preparation (run-breaking) by itself. #[derive(Clone, Debug)] -pub struct ConfiguredDisplay { +pub struct ConfiguredForme { font: FontSelector, dpem: f32, class: TextClass, @@ -46,10 +46,10 @@ pub struct ConfiguredDisplay { status: Status, rect: Rect, - display: TextDisplay, + forme: Forme, } -impl Layout for ConfiguredDisplay { +impl Layout for ConfiguredForme { fn rect(&self) -> Rect { self.rect } @@ -93,39 +93,39 @@ impl Layout for ConfiguredDisplay { self.set_align(hints.complete_default().into()); if rect.size != self.rect.size { if rect.size.0 != self.rect.size.0 { - self.set_max_status(Status::LevelRuns); + self.set_max_status(Status::Shaped); } else { self.set_max_status(Status::Wrapped); } } self.rect = rect; - self.prepare_wrap(); + let _ = self.prepare_wrap(); } /// Text color and decorations are not present here; derivative types will /// likely need their own implementation of this method. fn draw(&self, mut draw: DrawCx) { - if let Ok(display) = self.display() { + if let Ok(forme) = self.forme() { let rect = self.rect(); - draw.text(rect.pos, rect, display, &[]); + draw.text(rect.pos, rect, forme, &[]); } } } -impl ConfiguredDisplay { +impl ConfiguredForme { /// Construct a new instance #[inline] pub fn new(class: TextClass, wrap: bool) -> Self { - ConfiguredDisplay { + ConfiguredForme { font: FontSelector::default(), dpem: 16.0, class, wrap, align: Default::default(), direction: Direction::default(), - status: Status::New, + status: Status::Empty, rect: Rect::default(), - display: Default::default(), + forme: Default::default(), } } @@ -153,13 +153,10 @@ impl ConfiguredDisplay { pub fn configure(&mut self, cx: &mut SizeCx) { let font = cx.font(self.class); let dpem = cx.dpem(self.class); - if font != self.font { + if font != self.font || dpem != self.dpem { self.font = font; self.dpem = dpem; - self.set_max_status(Status::New); - } else if dpem != self.dpem { - self.dpem = dpem; - self.set_max_status(Status::ResizeLevelRuns); + self.set_max_status(Status::Empty); } } @@ -168,7 +165,7 @@ impl ConfiguredDisplay { /// This may be required after calling [`Text::text_mut`](super::Text::text_mut). #[inline] pub fn require_reprepare(&mut self) { - self.set_max_status(Status::New); + self.set_max_status(Status::Empty); } /// Get text class @@ -221,7 +218,7 @@ impl ConfiguredDisplay { pub fn set_font(&mut self, font: FontSelector) { if font != self.font { self.font = font; - self.set_max_status(Status::New); + self.set_max_status(Status::Empty); } } @@ -250,7 +247,7 @@ impl ConfiguredDisplay { pub fn set_font_size(&mut self, dpem: f32) { if dpem != self.dpem { self.dpem = dpem; - self.set_max_status(Status::ResizeLevelRuns); + self.set_max_status(Status::Empty); } } @@ -279,7 +276,7 @@ impl ConfiguredDisplay { pub fn set_direction(&mut self, direction: Direction) { if direction != self.direction { self.direction = direction; - self.set_max_status(Status::New); + self.set_max_status(Status::Empty); } } @@ -303,7 +300,7 @@ impl ConfiguredDisplay { if align.0 == self.align.0 { self.set_max_status(Status::Wrapped); } else { - self.set_max_status(Status::LevelRuns); + self.set_max_status(Status::Shaped); } self.align = align; } @@ -315,8 +312,8 @@ impl ConfiguredDisplay { /// falling back to [`Direction::text_is_rtl`]. #[inline] pub fn text_is_rtl(&self, text: &str) -> bool { - if self.status >= Status::ResizeLevelRuns { - self.display.text_is_rtl() + if self.status >= Status::Shaped { + self.forme.text_is_rtl() } else { self.direction.text_is_rtl(text) } @@ -359,7 +356,7 @@ impl ConfiguredDisplay { /// Prepare text: perform run-breaking and shaping /// /// This method advances the [status of preparation](Self::status) from - /// [`Status::New`] or [`Status::ResizeLevelRuns`] to [`Status::LevelRuns`]. + /// [`Status::Empty`] to [`Status::Shaped`]. /// This is the slowest step of text preparation and requires access to the /// `text` and `font_tokens`. /// @@ -370,86 +367,83 @@ impl ConfiguredDisplay { /// # Example /// /// ```rust - /// # use kas_core::text::{ConfiguredDisplay, format::FontToken}; + /// # use kas_core::text::{ConfiguredForme, format::FontToken}; /// # use kas_core::theme::TextClass; - /// let mut display = ConfiguredDisplay::new(TextClass::Standard, true); - /// display.prepare_runs("Hello world", std::iter::once(FontToken { + /// let mut forme = ConfiguredForme::new(TextClass::Standard, true); + /// forme.prepare_runs("Hello world", std::iter::once(FontToken { /// start: 0, /// dpem: 16.0, /// font: Default::default(), /// })); - /// display.prepare_wrap(); - /// // display is now ready + /// forme.prepare_wrap(); + /// // forme is now ready /// ``` pub fn prepare_runs(&mut self, text: &str, font_tokens: impl Iterator) { let direction = self.direction(); match self.status() { - Status::New => self - .unchecked_display_mut() - .prepare_runs(text, direction, font_tokens) + Status::Empty => self + .unchecked_forme_mut() + .set_text(text, direction) + .with_tokens(font_tokens, false) .expect("no suitable font found"), - Status::ResizeLevelRuns => self.unchecked_display_mut().resize_runs(text, font_tokens), _ => return, } - self.set_status(Status::LevelRuns); + self.set_status(Status::Shaped); } /// Prepare text: perform line wrapping and alignment /// - /// Actions depend on the [status of preparation](Self::status), - /// - /// - If less than [`Status::LevelRuns`], this method will do nothing. - /// [`Self::prepare_runs`] should be called first. - /// - If at exactly [`Status::LevelRuns`], this method will perform line - /// wrapping (see also next item). - /// - If at [`Status::LevelRuns`] or [`Status::Wrapped`], this method will - /// align the text vertically and advance to [`Status::Ready`]. - pub fn prepare_wrap(&mut self) { - if self.status() < Status::LevelRuns { - return; + /// If the initial [status](Self::status) is less than [`Status::Shaped`], + /// this method returns `Err(NotReady)`. Otherwise, this method performs + /// line-wrapping and alignment (if required), advancing the status to + /// [`Status::Ready`]. + pub fn prepare_wrap(&mut self) -> Result<(), NotReady> { + if self.status() < Status::Shaped { + return Err(NotReady); } let align = self.align(); - if self.status() == Status::LevelRuns { + if self.status() == Status::Shaped { let align_width = self.rect.size.0.cast(); let wrap_width = if !self.wrap() { f32::INFINITY } else { align_width }; - self.unchecked_display_mut() + self.unchecked_forme_mut() .prepare_lines(wrap_width, align_width, align.0); } if self.status() <= Status::Wrapped { let h = self.rect.size.1.cast(); - self.unchecked_display_mut().vertically_align(h, align.1); + self.unchecked_forme_mut().vertically_align(h, align.1); } self.set_status(Status::Ready); + Ok(()) } - /// Read the [`TextDisplay`], without checking status + /// Read the [`Forme`], without checking status #[inline] - pub fn unchecked_display(&self) -> &TextDisplay { - &self.display + pub fn unchecked_forme(&self) -> &Forme { + &self.forme } - /// Write to the [`TextDisplay`], without checking status + /// Write to the [`Forme`], without checking status #[inline] - pub fn unchecked_display_mut(&mut self) -> &mut TextDisplay { - &mut self.display + pub fn unchecked_forme_mut(&mut self) -> &mut Forme { + &mut self.forme } - /// Read the [`TextDisplay`], if fully prepared + /// Read the [`Forme`], if fully prepared #[inline] - pub fn display(&self) -> Result<&TextDisplay, NotReady> { + pub fn forme(&self) -> Result<&Forme, NotReady> { self.check_status(Status::Ready)?; - Ok(self.unchecked_display()) + Ok(self.unchecked_forme()) } - /// Read the [`TextDisplay`], if at least wrapped + /// Read the [`Forme`], if at least wrapped #[inline] - pub fn wrapped_display(&self) -> Result<&TextDisplay, NotReady> { + pub fn wrapped_forme(&self) -> Result<&Forme, NotReady> { self.check_status(Status::Wrapped)?; - Ok(self.unchecked_display()) + Ok(self.unchecked_forme()) } /// Offset prepared content to avoid left-overhangs @@ -464,7 +458,7 @@ impl ConfiguredDisplay { /// above the top (the first y-component is never negative). #[inline] pub fn ensure_no_left_overhang(&mut self) { - self.display.ensure_non_negative_alignment(); + self.forme.ensure_non_negative_alignment(); } /// Get the size of the required bounding box @@ -474,22 +468,22 @@ impl ConfiguredDisplay { /// Alignment and size do affect the result. #[inline] pub fn bounding_box(&self) -> Result<(Vec2, Vec2), NotReady> { - let (tl, br) = self.wrapped_display()?.bounding_box(); + let (tl, br) = self.wrapped_forme()?.bounding_box(); Ok((tl.into(), br.into())) } /// Get the number of lines (after wrapping) /// - /// See [`TextDisplay::num_lines`]. + /// See [`Forme::num_lines`]. #[inline] pub fn num_lines(&self) -> Result { - Ok(self.wrapped_display()?.num_lines()) + Ok(self.wrapped_forme()?.num_lines()) } /// Get line properties #[inline] pub fn get_line(&self, index: usize) -> Result, NotReady> { - Ok(self.wrapped_display()?.get_line(index)) + Ok(self.wrapped_forme()?.get_line(index)) } /// Iterate over line properties @@ -497,43 +491,43 @@ impl ConfiguredDisplay { /// [Requires status][Self#status-of-preparation]: lines have been wrapped. #[inline] pub fn lines(&self) -> Result, NotReady> { - Ok(self.wrapped_display()?.lines()) + Ok(self.wrapped_forme()?.lines()) } /// Find the line containing text `index` /// /// Returns the line number and the text-range of the line. - /// See [`TextDisplay::find_line`]. + /// See [`Forme::find_line`]. #[inline] pub fn find_line( &self, index: usize, ) -> Result)>, NotReady> { - Ok(self.wrapped_display()?.find_line(index)) + Ok(self.wrapped_forme()?.find_line(index)) } /// Get the directionality of the current line /// - /// See [`TextDisplay::line_is_rtl`]. + /// See [`Forme::line_is_rtl`]. #[inline] pub fn line_is_rtl(&self, line: usize) -> Result, NotReady> { - Ok(self.wrapped_display()?.line_is_rtl(line)) + Ok(self.wrapped_forme()?.line_is_rtl(line)) } /// Find the text index for the glyph nearest the given `pos` /// - /// See [`TextDisplay::text_index_nearest`]. + /// See [`Forme::text_index_nearest`]. #[inline] pub fn text_index_nearest(&self, pos: Vec2) -> Result { - Ok(self.display()?.text_index_nearest(pos.into())) + Ok(self.forme()?.text_index_nearest(pos.into())) } /// Find the text index nearest horizontal-coordinate `x` on `line` /// - /// See [`TextDisplay::line_index_nearest`]. + /// See [`Forme::line_index_nearest`]. #[inline] pub fn line_index_nearest(&self, line: usize, x: f32) -> Result, NotReady> { - Ok(self.wrapped_display()?.line_index_nearest(line, x)) + Ok(self.wrapped_forme()?.line_index_nearest(line, x)) } /// Measure required width, up to some `max_width` @@ -544,8 +538,8 @@ impl ConfiguredDisplay { /// /// The return value is unaffected by alignment and wrap configuration. pub fn measure_width(&self, max_width: f32) -> Result { - if self.status >= Status::LevelRuns { - Ok(self.display.measure_width(max_width)) + if self.status >= Status::Shaped { + Ok(self.forme.measure_width(max_width)) } else { Err(NotReady) } @@ -559,8 +553,8 @@ impl ConfiguredDisplay { wrap_width: f32, max_lines: Option, ) -> Result { - if self.status >= Status::LevelRuns { - Ok(self.display.measure_height(wrap_width, max_lines)) + if self.status >= Status::Shaped { + Ok(self.forme.measure_height(wrap_width, max_lines)) } else { Err(NotReady) } @@ -568,8 +562,8 @@ impl ConfiguredDisplay { /// Find the starting position (top-left) of the glyph at the given index /// - /// See [`TextDisplay::text_glyph_pos`]. + /// See [`Forme::text_glyph_pos`]. pub fn text_glyph_pos(&self, index: usize) -> Result { - Ok(self.display()?.text_glyph_pos(index)) + Ok(self.forme()?.text_glyph_pos(index)) } } diff --git a/crates/kas-core/src/text/mod.rs b/crates/kas-core/src/text/mod.rs index bc530201d..c74c319cf 100644 --- a/crates/kas-core/src/text/mod.rs +++ b/crates/kas-core/src/text/mod.rs @@ -11,12 +11,12 @@ //! [KAS Text]: https://github.com/kas-gui/kas-text/ pub use kas_text::{ - Align, DPU, Direction, Line, LineIterator, MarkerPos, MarkerPosIter, NotReady, Status, - TextDisplay, Vec2, fonts, + Align, DPU, Direction, Forme, Line, LineIterator, MarkerPos, MarkerPosIter, NotReady, Status, + Vec2, fonts, }; -mod display; pub mod format; +mod forme; /// Glyph rastering #[cfg_attr(not(feature = "internal_doc"), doc(hidden))] #[cfg_attr(docsrs, doc(cfg(internal_doc)))] @@ -25,7 +25,7 @@ mod selection; mod string; mod text; -pub use display::ConfiguredDisplay; +pub use forme::ConfiguredForme; pub use selection::CursorRange; pub use string::AccessString; pub use text::Text; diff --git a/crates/kas-core/src/text/raster.rs b/crates/kas-core/src/text/raster.rs index fdc324a6c..a09313c12 100644 --- a/crates/kas-core/src/text/raster.rs +++ b/crates/kas-core/src/text/raster.rs @@ -18,7 +18,7 @@ use kas::config::RasterConfig; use kas::draw::{AllocError, Allocation, PassId, color::Rgba}; use kas::geom::{Quad, Vec2}; use kas_text::fonts::{self, FaceId}; -use kas_text::{Glyph, GlyphId, TextDisplay}; +use kas_text::{Forme, Glyph, GlyphId}; use rustc_hash::FxHashMap as HashMap; use swash::zeno::Format; @@ -510,7 +510,7 @@ impl State { pass: PassId, pos: Vec2, bb: Quad, - text: &TextDisplay, + text: &Forme, col: Rgba, ) { for run in text.runs::<()>(pos.into(), &[]) { @@ -542,12 +542,12 @@ impl State { pass: PassId, pos: Vec2, bb: Quad, - text: &TextDisplay, + text: &Forme, theme: &ColorsLinear, tokens: &[(u32, Colors)], mut draw_quad: impl FnMut(Quad, Rgba), ) { - // Optimisation: use cheaper TextDisplay::runs method + // Optimisation: use cheaper Forme::runs method if tokens.len() <= 1 && tokens .first() @@ -602,7 +602,7 @@ impl State { &mut self, pos: Vec2, bb: Quad, - text: &TextDisplay, + text: &Forme, theme: &ColorsLinear, tokens: &[(u32, Decoration)], mut draw_quad: impl FnMut(Quad, Rgba), diff --git a/crates/kas-core/src/text/text.rs b/crates/kas-core/src/text/text.rs index 274a4558d..d0c41c77e 100644 --- a/crates/kas-core/src/text/text.rs +++ b/crates/kas-core/src/text/text.rs @@ -20,18 +20,18 @@ use std::num::NonZeroUsize; /// /// This struct contains: /// - A [`FormattableText`] -/// - A [`ConfiguredDisplay`] (accessible using `*self`) +/// - A [`ConfiguredForme`] (accessible using `*self`) /// /// This struct tracks the -/// [state of preparation][TextDisplay#status-of-preparation] and will perform +/// [state of preparation][Forme#status-of-preparation] and will perform /// steps as required. Typical usage of this struct is as follows: /// - Construct with some text and [`TextClass`] -/// - Configure by calling [`ConfiguredDisplay::configure`] +/// - Configure by calling [`ConfiguredForme::configure`] /// - Size and draw using [`Layout`] methods #[derive(Clone, Debug)] #[autoimpl(Deref, DerefMut using self.inner)] pub struct Text { - inner: ConfiguredDisplay, + inner: ConfiguredForme, text: T, } @@ -55,11 +55,11 @@ impl Layout for Text { #[inline] fn draw(&self, mut draw: DrawCx) { - if let Ok(display) = self.display() { + if let Ok(forme) = self.forme() { let rect = self.rect(); let tokens = self.color_tokens(); - draw.text(rect.pos, rect, display, tokens); - draw.decorate_text(rect.pos, rect, display, self.decorations()); + draw.text(rect.pos, rect, forme, tokens); + draw.decorate_text(rect.pos, rect, forme, self.decorations()); } } } @@ -71,7 +71,7 @@ impl Text { #[inline] pub fn new(text: T, class: TextClass, wrap: bool) -> Self { Text { - inner: ConfiguredDisplay::new(class, wrap), + inner: ConfiguredForme::new(class, wrap), text, } } @@ -95,7 +95,7 @@ impl Text { /// Access the formattable text object mutably /// /// If the text is changed, one **must** call - /// self.[require_reprepare][ConfiguredDisplay::require_reprepare]() + /// self.[require_reprepare][ConfiguredForme::require_reprepare]() /// after this method then [`Text::prepare`]. #[inline] pub fn text_mut(&mut self) -> &mut T { @@ -119,7 +119,7 @@ impl Text { } self.text = text; - self.set_max_status(Status::New); + self.set_max_status(Status::Empty); true } @@ -169,7 +169,7 @@ impl Text { #[inline] fn prepare_runs(&mut self) { - if self.status() < Status::LevelRuns { + if self.status() < Status::Shaped { let (dpem, font) = (self.font_size(), self.font()); self.inner .prepare_runs(self.text.as_str(), self.text.font_tokens(dpem, font)); @@ -178,7 +178,7 @@ impl Text { /// Measure required width, up to some `max_width` /// - /// This method partially prepares the [`TextDisplay`] as required. + /// This method partially prepares the [`Forme`] as required. /// /// This method allows calculation of the width requirement of a text object /// without full wrapping and glyph placement. Whenever the requirement @@ -187,7 +187,7 @@ impl Text { /// The return value is unaffected by alignment and wrap configuration. pub fn measure_width(&mut self, max_width: f32) -> f32 { self.prepare_runs(); - self.unchecked_display().measure_width(max_width) + self.unchecked_forme().measure_width(max_width) } /// Measure required vertical height, wrapping as configured @@ -198,8 +198,7 @@ impl Text { /// modify `self`. pub fn measure_height(&mut self, wrap_width: f32, max_lines: Option) -> f32 { self.prepare_runs(); - self.unchecked_display() - .measure_height(wrap_width, max_lines) + self.unchecked_forme().measure_height(wrap_width, max_lines) } /// Prepare text for display, as necessary @@ -219,8 +218,8 @@ impl Text { fn inner(this: &mut Text) { this.prepare_runs(); - debug_assert!(this.status() >= Status::LevelRuns); - this.inner.prepare_wrap(); + let result = this.inner.prepare_wrap(); + debug_assert_eq!(result, Ok(())); } inner(self); true @@ -234,7 +233,7 @@ impl Text { /// This is typically called after updating a `Text` object in a widget. pub fn reprepare_action(&mut self, cx: &mut ConfigCx) { if self.prepare() { - let (tl, br) = self.unchecked_display().bounding_box(); + let (tl, br) = self.unchecked_forme().bounding_box(); let bounds: Vec2 = self.rect().size.cast(); if tl.0 < 0.0 || tl.1 < 0.0 || br.0 > bounds.0 || br.1 > bounds.1 { cx.resize(); @@ -248,14 +247,14 @@ impl Text { /// The given `color` is used, ignoring [`Self::color_tokens`] /// Decorations are inferred from [`Text::decorations`]. pub fn draw_with_color(&self, mut draw: DrawCx, color: Rgba) { - if let Ok(display) = self.display() { + if let Ok(forme) = self.forme() { let rect = self.rect(); let tokens = [(0, format::Colors { foreground: format::Color::from_rgba(color), ..Default::default() })]; - draw.text(rect.pos, rect, display, &tokens); - draw.decorate_text(rect.pos, rect, display, self.decorations()); + draw.text(rect.pos, rect, forme, &tokens); + draw.decorate_text(rect.pos, rect, forme, self.decorations()); } } } @@ -272,7 +271,7 @@ impl Text { #[inline] pub fn insert_str(&mut self, index: usize, text: &str) { self.text.insert_str(index, text); - self.set_max_status(Status::New); + self.set_max_status(Status::Empty); } /// Replace a section of text @@ -287,7 +286,7 @@ impl Text { #[inline] pub fn replace_range(&mut self, range: std::ops::Range, replace_with: &str) { self.text.replace_range(range, replace_with); - self.set_max_status(Status::New); + self.set_max_status(Status::Empty); } /// Replace the whole text @@ -297,6 +296,6 @@ impl Text { #[inline] pub fn set_string(&mut self, text: String) { self.text = text; - self.set_max_status(Status::New); + self.set_max_status(Status::Empty); } } diff --git a/crates/kas-core/src/theme/draw.rs b/crates/kas-core/src/theme/draw.rs index c3ee7e4ea..38c7e95c8 100644 --- a/crates/kas-core/src/theme/draw.rs +++ b/crates/kas-core/src/theme/draw.rs @@ -15,7 +15,7 @@ use crate::event::EventState; #[allow(unused)] use crate::event::{Command, ConfigCx}; use crate::geom::{Coord, Offset, Rect}; #[allow(unused)] use crate::text::format::FormattableText; -use crate::text::{TextDisplay, format}; +use crate::text::{Forme, format}; use crate::theme::ColorsLinear; use crate::{Id, Tile, autoimpl}; #[allow(unused)] use crate::{Layout, theme::TextClass}; @@ -288,13 +288,7 @@ impl<'a> DrawCx<'a> { /// Text is clipped to `rect`, drawing from `pos`; use `pos = rect.pos` if /// the text is not scrolled. #[inline] - pub fn text( - &mut self, - pos: Coord, - rect: Rect, - display: &TextDisplay, - tokens: &[(u32, format::Colors)], - ) { + pub fn text(&mut self, pos: Coord, rect: Rect, text: &Forme, tokens: &[(u32, format::Colors)]) { if cfg!(debug_assertions) { let mut i = 0; for (start, _) in tokens { @@ -303,7 +297,7 @@ impl<'a> DrawCx<'a> { } } - self.h.text(&self.id, pos, rect, display, tokens); + self.h.text(&self.id, pos, rect, text, tokens); } /// Draw text decorations (e.g. underlines) @@ -315,7 +309,7 @@ impl<'a> DrawCx<'a> { &mut self, pos: Coord, rect: Rect, - display: &TextDisplay, + text: &Forme, decorations: &[(u32, format::Decoration)], ) { if cfg!(debug_assertions) { @@ -327,8 +321,7 @@ impl<'a> DrawCx<'a> { } if !decorations.is_empty() { - self.h - .decorate_text(&self.id, pos, rect, display, decorations); + self.h.decorate_text(&self.id, pos, rect, text, decorations); } } @@ -339,12 +332,11 @@ impl<'a> DrawCx<'a> { &mut self, pos: Coord, rect: Rect, - display: &TextDisplay, + text: &Forme, byte: usize, color: Option, ) { - self.h - .text_cursor(&self.id, pos, rect, display, byte, color); + self.h.text_cursor(&self.id, pos, rect, text, byte, color); } /// Draw UI element: check box (without label) @@ -508,7 +500,7 @@ pub trait ThemeDraw { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, tokens: &[(u32, format::Colors)], ); @@ -522,7 +514,7 @@ pub trait ThemeDraw { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, decorations: &[(u32, format::Decoration)], ); @@ -534,7 +526,7 @@ pub trait ThemeDraw { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, byte: usize, color: Option, ); diff --git a/crates/kas-core/src/theme/flat_theme.rs b/crates/kas-core/src/theme/flat_theme.rs index b9c934ce5..62ab408ab 100644 --- a/crates/kas-core/src/theme/flat_theme.rs +++ b/crates/kas-core/src/theme/flat_theme.rs @@ -17,7 +17,7 @@ use crate::dir::{Direction, Directional}; use crate::draw::{color::Rgba, *}; use crate::event::EventState; use crate::geom::*; -use crate::text::TextDisplay; +use crate::text::Forme; use crate::theme::dimensions as dim; use crate::theme::{Background, FrameStyle, MarkStyle}; use crate::theme::{ColorsLinear, InputState, Theme}; diff --git a/crates/kas-core/src/theme/simple_theme.rs b/crates/kas-core/src/theme/simple_theme.rs index efe6c42ba..c0fc0288c 100644 --- a/crates/kas-core/src/theme/simple_theme.rs +++ b/crates/kas-core/src/theme/simple_theme.rs @@ -17,7 +17,7 @@ use crate::dir::{Direction, Directional}; use crate::draw::{color::Rgba, *}; use crate::event::EventState; use crate::geom::*; -use crate::text::{TextDisplay, format}; +use crate::text::{Forme, format}; use crate::theme::dimensions as dim; use crate::theme::{Background, FrameStyle, MarkStyle}; use crate::theme::{ColorsLinear, InputState, Theme}; @@ -351,7 +351,7 @@ impl<'a, DS: DrawSharedImpl> ThemeDraw for DrawHandle<'a, DS> { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, tokens: &[(u32, format::Colors)], ) { // NOTE: id is passed to allow usage of self.cols.text_disabled if self.ev.is_disabled(id). @@ -367,7 +367,7 @@ impl<'a, DS: DrawSharedImpl> ThemeDraw for DrawHandle<'a, DS> { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, decorations: &[(u32, format::Decoration)], ) { // NOTE: see above note on usage of self.cols.text_disabled. @@ -383,7 +383,7 @@ impl<'a, DS: DrawSharedImpl> ThemeDraw for DrawHandle<'a, DS> { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, byte: usize, color: Option, ) { diff --git a/crates/kas-macros/src/extends.rs b/crates/kas-macros/src/extends.rs index f845b2840..aaad868d7 100644 --- a/crates/kas-macros/src/extends.rs +++ b/crates/kas-macros/src/extends.rs @@ -85,7 +85,7 @@ impl Methods { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, tokens: &[(u32, ::kas::text::format::Colors)], ) { (#base).text(id, pos, rect, text, tokens); @@ -96,7 +96,7 @@ impl Methods { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, decorations: &[(u32, ::kas::text::format::Decoration)], ) { (#base).decorate_text(id, pos, rect, text, decorations); @@ -107,7 +107,7 @@ impl Methods { id: &Id, pos: Coord, rect: Rect, - text: &TextDisplay, + text: &Forme, byte: usize, color: Option<::kas::text::format::Color>, ) { diff --git a/crates/kas-soft/src/draw.rs b/crates/kas-soft/src/draw.rs index 0c0a0b408..625719bb5 100644 --- a/crates/kas-soft/src/draw.rs +++ b/crates/kas-soft/src/draw.rs @@ -185,7 +185,7 @@ impl DrawSharedImpl for Shared { pass: PassId, pos: Vec2, bb: Quad, - text: &text::TextDisplay, + text: &text::Forme, theme: &ColorsLinear, tokens: &[(u32, text::format::Colors)], ) { @@ -212,7 +212,7 @@ impl DrawSharedImpl for Shared { pass: PassId, pos: Vec2, bb: Quad, - text: &text::TextDisplay, + text: &text::Forme, theme: &ColorsLinear, decorations: &[(u32, text::format::Decoration)], ) { diff --git a/crates/kas-wgpu/src/draw/draw_pipe.rs b/crates/kas-wgpu/src/draw/draw_pipe.rs index f9fb2b0e0..edea2f828 100644 --- a/crates/kas-wgpu/src/draw/draw_pipe.rs +++ b/crates/kas-wgpu/src/draw/draw_pipe.rs @@ -367,7 +367,7 @@ impl DrawSharedImpl for DrawPipe { pass: PassId, pos: Vec2, bb: Quad, - text: &text::TextDisplay, + text: &text::Forme, theme: &ColorsLinear, tokens: &[(u32, text::format::Colors)], ) { @@ -394,7 +394,7 @@ impl DrawSharedImpl for DrawPipe { pass: PassId, pos: Vec2, bb: Quad, - text: &text::TextDisplay, + text: &text::Forme, theme: &ColorsLinear, decorations: &[(u32, text::format::Decoration)], ) { diff --git a/crates/kas-wgpu/src/shaded_theme.rs b/crates/kas-wgpu/src/shaded_theme.rs index 6a6e6fb08..aee767acf 100644 --- a/crates/kas-wgpu/src/shaded_theme.rs +++ b/crates/kas-wgpu/src/shaded_theme.rs @@ -17,7 +17,7 @@ use kas::dir::{Direction, Directional}; use kas::draw::{color::Rgba, *}; use kas::event::EventState; use kas::geom::*; -use kas::text::TextDisplay; +use kas::text::Forme; use kas::theme::dimensions as dim; use kas::theme::{Background, ThemeDraw, ThemeSize}; use kas::theme::{ColorsLinear, FlatTheme, InputState, SimpleTheme, Theme}; diff --git a/crates/kas-widgets/src/access_label.rs b/crates/kas-widgets/src/access_label.rs index ffe8a3774..2179425f4 100644 --- a/crates/kas-widgets/src/access_label.rs +++ b/crates/kas-widgets/src/access_label.rs @@ -135,9 +135,9 @@ mod AccessLabel { && draw.access_key(&self.target, key) { // Stop on first successful binding and draw - if let Ok(display) = self.text.display() { + if let Ok(forme) = self.text.forme() { let rect = self.text.rect(); - draw.decorate_text(rect.pos, rect, display, decoration); + draw.decorate_text(rect.pos, rect, forme, decoration); } } } diff --git a/crates/kas-widgets/src/edit/editor.rs b/crates/kas-widgets/src/edit/editor.rs index c52da5921..67bc04f21 100644 --- a/crates/kas-widgets/src/edit/editor.rs +++ b/crates/kas-widgets/src/edit/editor.rs @@ -25,7 +25,7 @@ use kas::geom::{Rect, Vec2}; use kas::layout::{AlignHints, AxisInfo, SizeRules}; use kas::prelude::*; use kas::text::fonts::FontSelector; -use kas::text::{CursorRange, Direction, NotReady, Status, TextDisplay, format}; +use kas::text::{CursorRange, Direction, Forme, NotReady, Status, format}; use kas::theme::{Background, DrawCx, SizeCx, TextClass}; use kas::util::UndoStack; use kas::{Layout, autoimpl}; @@ -34,7 +34,7 @@ use std::num::NonZeroUsize; use std::rc::Rc; use unicode_segmentation::{GraphemeCursor, UnicodeSegmentation}; -/// Action: text parts should have their status reset to [`Status::New`] and be re-prepared +/// Action: text parts should have their status reset to [`Status::Empty`] and be re-prepared #[must_use] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub struct ActionResetStatus; @@ -170,7 +170,7 @@ impl Common { /// current text direction of the `part` pub fn update_direction(&mut self, part: &Part) { if self.direction.is_auto() { - self.direction = if part.display.text_is_rtl() { + self.direction = if part.forme.text_is_rtl() { Direction::AutoRtl } else { Direction::Auto @@ -214,7 +214,7 @@ pub struct Part { part: u32, // part index rect: Rect, status: Status, - display: TextDisplay, + forme: Forme, highlight: highlight::Cache, text: Rc, } @@ -351,7 +351,7 @@ impl Component { #[inline] pub fn set_wrap(&mut self, wrap: bool) { self.0.common.wrap = wrap; - self.0.part.status = self.0.part.status.min(Status::LevelRuns); + self.0.part.status = self.0.part.status.min(Status::Shaped); } /// Set the base text direction @@ -362,7 +362,7 @@ impl Component { #[inline] pub fn set_direction(&mut self, direction: Direction) { self.0.common.direction = direction; - self.0.part.status = Status::New; + self.0.part.status = Status::Empty; } /// Replace the highlighter @@ -424,7 +424,7 @@ impl Component { } fn prepare_runs(&mut self) { - if self.0.part.status < Status::LevelRuns { + if self.0.part.status < Status::Shaped { self.0.part.prepare_runs(&self.0.common, &mut self.1); self.0.common.update_direction(&self.0.part); } @@ -439,7 +439,7 @@ impl Component { /// edits to the text to trigger any required resizing and scrolling. #[inline] pub fn prepare(&mut self) { - if self.0.part.is_prepared() { + if self.0.part.is_ready() { return; } @@ -468,7 +468,7 @@ impl Component { #[inline] pub fn measure_height(&mut self, wrap_width: f32, max_lines: Option) -> f32 { self.prepare_runs(); - self.0.part.display.measure_height(wrap_width, max_lines) + self.0.part.forme.measure_height(wrap_width, max_lines) } /// Implementation of [`Viewport::draw_with_offset`] @@ -504,8 +504,8 @@ impl Default for Part { Part { part: 0, rect: Rect::ZERO, - status: Status::New, - display: TextDisplay::default(), + status: Status::Empty, + forme: Forme::default(), highlight: Default::default(), text: Default::default(), } @@ -547,13 +547,13 @@ impl Part { /// [`Self::prepare_runs`] should be called before this method. #[inline] pub fn text_is_rtl(&self) -> bool { - debug_assert!(self.status >= Status::ResizeLevelRuns); - self.display.text_is_rtl() + debug_assert!(self.status >= Status::Shaped); + self.forme.text_is_rtl() } /// Check whether the text is fully prepared and ready for usage #[inline] - pub fn is_prepared(&self) -> bool { + pub fn is_ready(&self) -> bool { self.status == Status::Ready } @@ -566,16 +566,16 @@ impl Part { /// Force full repreparation of text #[inline] pub fn require_reprepare(&mut self) { - self.status = Status::New; + self.status = Status::Empty; } /// Perform run-breaking and shaping /// /// This represents a high-level step of preparation required before /// displaying text: it advances the [`Self::status`] to - /// [`Status::LevelRuns`]. This method is safe to call from any status, + /// [`Status::Shaped`]. This method is safe to call from any status, /// though it is suggested to only call when the status is less than - /// [`Status::LevelRuns`]. + /// [`Status::Shaped`]. #[inline] pub fn prepare_runs(&mut self, common: &Common, highlighter: &mut H) { self.highlight.highlight(&self.text, highlighter); @@ -583,15 +583,15 @@ impl Part { let text = self.text.as_str(); let font_tokens = self.highlight.font_tokens(common.dpem, common.font); match self.status { - Status::New => self - .display - .prepare_runs(text, common.direction, font_tokens) + Status::Empty => self + .forme + .set_text(text, common.direction) + .with_tokens(font_tokens, true) .expect("no suitable font found"), - Status::ResizeLevelRuns => self.display.resize_runs(text, font_tokens), _ => return, } - self.status = Status::LevelRuns; + self.status = Status::Shaped; } /// Get the assigned [`Rect`] @@ -606,13 +606,13 @@ impl Part { let mut bound = 0i32; if common.wrap { let (min, ideal) = cx.wrapped_line_len(TextClass::Editor, common.dpem); - if self.status >= Status::LevelRuns { - bound = self.display.measure_width(ideal.cast()).cast_ceil(); + if self.status >= Status::Shaped { + bound = self.forme.measure_width(ideal.cast()).cast_ceil(); } SizeRules::new(bound.min(min), bound.min(ideal), Stretch::Filler) } else { - if self.status >= Status::LevelRuns { - bound = self.display.measure_width(f32::INFINITY).cast_ceil(); + if self.status >= Status::Shaped { + bound = self.forme.measure_width(f32::INFINITY).cast_ceil(); } SizeRules::new(bound, bound, Stretch::Filler) } @@ -623,8 +623,8 @@ impl Part { .flatten() .unwrap_or(f32::INFINITY); let mut bound = 0i32; - if self.status >= Status::LevelRuns { - bound = self.display.measure_height(wrap_width, None).cast_ceil(); + if self.status >= Status::Shaped { + bound = self.forme.measure_height(wrap_width, None).cast_ceil(); } SizeRules::new(bound, bound, Stretch::Filler) }; @@ -642,7 +642,7 @@ impl Part { /// Note that editors always use default alignment of content. pub fn set_rect(&mut self, common: &Common, cx: &mut SizeCx, rect: Rect) { if rect.size.0 != self.rect.size.0 { - self.status = self.status.min(Status::LevelRuns); + self.status = self.status.min(Status::Shaped); } self.rect = rect; @@ -663,31 +663,31 @@ impl Part { /// Perform line wrapping and alignment /// /// This represents a high-level step of preparation required before - /// displaying text: it advances [`Self::status`] from [`Status::LevelRuns`] + /// displaying text: it advances [`Self::status`] from [`Status::Shaped`] /// to [`Status::Ready`]. /// - /// If [`Self::status`] is less than [`Status::LevelRuns`], this method + /// If [`Self::status`] is less than [`Status::Shaped`], this method /// returns early, otherwise it performs line-wrapping (if required) and /// sets the status to [`Status::Ready`]. /// /// Returns `true` when the size of the bounding-box changes. pub fn prepare_wrap(&mut self, common: &Common) -> bool { - if self.status < Status::LevelRuns || self.rect.size.0 == 0 { + if self.status < Status::Shaped || self.rect.size.0 == 0 { return false; }; - let bb = self.display.bounding_box(); + let bb = self.forme.bounding_box(); - if self.status == Status::LevelRuns { + if self.status == Status::Shaped { let align_width = self.rect.size.0.cast(); let wrap_width = if !common.wrap { f32::INFINITY } else { align_width }; - self.display + self.forme .prepare_lines(wrap_width, align_width, Align::Default); - self.display.ensure_non_negative_alignment(); + self.forme.ensure_non_negative_alignment(); } self.status = Status::Ready; - bb != self.display.bounding_box() + bb != self.forme.bounding_box() } /// Measure required vertical height, wrapping as configured @@ -700,8 +700,8 @@ impl Part { wrap_width: f32, max_lines: Option, ) -> Result { - if self.status >= Status::LevelRuns { - Ok(self.display.measure_height(wrap_width, max_lines)) + if self.status >= Status::Shaped { + Ok(self.forme.measure_height(wrap_width, max_lines)) } else { Err(NotReady) } @@ -709,17 +709,17 @@ impl Part { /// Implementation of [`Viewport::content_size`] pub fn content_size(&self) -> Size { - if self.status < Status::Wrapped { + if !self.is_ready() { return Size::ZERO; } - let (tl, br) = self.display.bounding_box(); + let (tl, br) = self.forme.bounding_box(); (Vec2::from(br) - Vec2::from(tl)).cast_ceil() } /// Implementation of [`Viewport::draw_with_offset`] pub fn draw_with_offset(&self, mut draw: DrawCx, common: &Common, rect: Rect, offset: Offset) { - if !self.is_prepared() { + if !self.is_ready() { return; } @@ -825,11 +825,11 @@ impl Part { } &vec }; - draw.text(pos, rect, &self.display, tokens); + draw.text(pos, rect, &self.forme, tokens); let decorations = self.highlight.decorations(); if !decorations.is_empty() { - draw.decorate_text(pos, rect, &self.display, decorations); + draw.decorate_text(pos, rect, &self.forme, decorations); } if let CurrentAction::ImePreedit { edit_range, .. } = common.current.clone() { @@ -842,7 +842,7 @@ impl Part { (edit_range.end, Default::default()), ]; let r0 = if edit_range.start > 0 { 0 } else { 1 }; - draw.decorate_text(pos, rect, &self.display, &tokens[r0..]); + draw.decorate_text(pos, rect, &self.forme, &tokens[r0..]); } if !common.read_only @@ -852,7 +852,7 @@ impl Part { draw.text_cursor( pos, rect, - &self.display, + &self.forme, common.selection.cursor.byte(), Some(common.colors.cursor), ); @@ -910,11 +910,11 @@ impl Part { let initial_range = range.clone(); let edit_len = edit_range.clone().map(|r| r.len()).unwrap_or(0); - if self.status >= Status::Wrapped { - if let Some((_, line_range)) = self.display.find_line(range.start) { + if self.is_ready() { + if let Some((_, line_range)) = self.forme.find_line(range.start) { range.start = line_range.start; } - if let Some((_, line_range)) = self.display.find_line(range.end) { + if let Some((_, line_range)) = self.forme.find_line(range.end) { range.end = line_range.end; } } @@ -954,7 +954,7 @@ impl Part { /// Call to set IME position only while IME is active fn set_ime_cursor_area(&self, common: &Common, cx: &mut EventState) { - if !self.is_prepared() { + if !self.is_ready() { return; } @@ -966,12 +966,12 @@ impl Part { let (m1, m2); if range.is_empty() { - let mut iter = self.display.text_glyph_pos(range.start); + let mut iter = self.forme.text_glyph_pos(range.start); m1 = iter.next(); m2 = iter.next(); } else { - m1 = self.display.text_glyph_pos(range.start).next_back(); - m2 = self.display.text_glyph_pos(range.end).next(); + m1 = self.forme.text_glyph_pos(range.start).next_back(); + m2 = self.forme.text_glyph_pos(range.end).next(); } let rect = if let Some((c1, c2)) = m1.zip(m2) { @@ -1171,8 +1171,8 @@ impl Common { let mut any_resized = false; for (i, part) in parts.iter_mut().enumerate() { - if !part.is_prepared() { - if part.status < Status::LevelRuns { + if !part.is_ready() { + if part.status < Status::Shaped { part.prepare_runs(self, highlighter); if i == 0 { self.update_direction(part); @@ -1224,7 +1224,7 @@ impl Common { let mut best_p = p; loop { let part = parts.get(p); - debug_assert!(part.is_prepared()); + debug_assert!(part.is_ready()); let (y0, y1) = (part.rect.pos.1, part.rect.pos2().1 - 1); let dist = y0.saturating_sub(coord.1).max(coord.1.saturating_sub(y1)); @@ -1248,7 +1248,7 @@ impl Common { let part = parts.get(best_p); let rel_pos = (coord - part.rect().pos).cast(); - let byte = part.display.text_index_nearest(rel_pos); + let byte = part.forme.text_index_nearest(rel_pos); TextIndex::new(p, byte) } @@ -1451,7 +1451,7 @@ impl Common { part.text.as_str(), CursorRange::from(anchor.byte()..cursor.byte()), (repeats >= 3) - .then_some(&|index| part.display.find_line(index).map(|r| r.1)), + .then_some(&|index| part.forme.find_line(index).map(|r| r.1)), ); anchor.byte = r.anchor.cast(); cursor.byte = r.cursor.cast(); @@ -1476,7 +1476,7 @@ impl Common { CursorRange::from(anchor.byte()..cursor.byte()), index.byte(), repeats, - Some(&|index| part.display.find_line(index).map(|r| r.1)), + Some(&|index| part.forme.find_line(index).map(|r| r.1)), ); anchor.byte = r.anchor.cast(); cursor.byte = r.cursor.cast(); @@ -1578,7 +1578,7 @@ impl Common { let c_p = cursor.part(); let cursor = cursor.byte(); let c_part = parts.get(c_p); - debug_assert!(c_part.is_prepared()); + debug_assert!(c_part.is_ready()); let c_part_len = c_part.as_str().len(); let multi_line = self.wrap; let selection = self.selection.to_range(); @@ -1704,13 +1704,13 @@ impl Common { let x = match self.edit_x_coord { Some(x) => x, None => c_part - .display + .forme .text_glyph_pos(cursor) .next_back() .map(|r| r.pos.0) .unwrap_or(0.0), }; - let mut line = c_part.display.find_line(cursor).map(|r| r.0).unwrap_or(0); + let mut line = c_part.forme.find_line(cursor).map(|r| r.0).unwrap_or(0); // We can tolerate invalid line numbers here! line = match cmd { Command::Up => line.wrapping_sub(1), @@ -1724,7 +1724,7 @@ impl Common { }; // TODO: prev/next c_part - .display + .forme .line_index_nearest(line, x) .map(|index| Action::Move(TextIndex::new(c_p, index), Some(x))) .unwrap_or(Action::Move(TextIndex::new(c_p, nearest_end), None)) @@ -1732,7 +1732,7 @@ impl Common { Command::Home if cursor > 0 => { // TODO: we don't need to use find_line if each part represents a line let index = c_part - .display + .forme .find_line(cursor) .map(|r| r.1.start) .unwrap_or(0); @@ -1740,7 +1740,7 @@ impl Common { } Command::End if cursor < c_part_len => { let index = c_part - .display + .forme .find_line(cursor) .map(|r| r.1.end) .unwrap_or(c_part_len); @@ -1758,7 +1758,7 @@ impl Common { } Command::PageUp | Command::PageDown if multi_line => { let mut v = c_part - .display + .forme .text_glyph_pos(cursor) .next_back() .map(|r| r.pos.into()) @@ -1768,7 +1768,7 @@ impl Common { } // TODO: page height should be an input? let mut line_height = self.dpem; - if let Some(line) = c_part.display.lines().next() { + if let Some(line) = c_part.forme.lines().next() { line_height = line.bottom() - line.top(); } let mut h_dist = line_height * 10.0; @@ -1940,7 +1940,7 @@ impl Common { let part = parts.get_mut(p); if !Rc::ptr_eq(&part.text, text) { part.text = Rc::clone(text); - part.status = Status::New; + part.status = Status::Empty; } p += 1; } @@ -1972,8 +1972,8 @@ impl Common { fn set_view_offset_from_cursor(&self, parts: &impl PartList, cx: &mut EventCx) { let cursor = self.selection.cursor; let part = parts.get(cursor.part()); - if part.is_prepared() - && let Some(marker) = part.display.text_glyph_pos(cursor.byte()).next_back() + if part.is_ready() + && let Some(marker) = part.forme.text_glyph_pos(cursor.byte()).next_back() { let y0 = (marker.pos.1 - marker.ascent).cast_floor(); let pos = part.rect.pos + Offset(marker.pos.0.cast_nearest(), y0); diff --git a/crates/kas-widgets/src/scroll_label.rs b/crates/kas-widgets/src/scroll_label.rs index ecbfe50c7..1ae6c3899 100644 --- a/crates/kas-widgets/src/scroll_label.rs +++ b/crates/kas-widgets/src/scroll_label.rs @@ -66,7 +66,7 @@ mod ScrollTextCore { } fn draw_with_offset(&self, mut draw: DrawCx, rect: Rect, offset: Offset) { - let Ok(display) = self.text.display() else { + let Ok(forme) = self.text.forme() else { return; }; @@ -84,9 +84,9 @@ mod ScrollTextCore { let r0 = if range.start > 0 { 0 } else { 1 }; &tokens[r0..] }; - draw.text(pos, rect, display, tokens); + draw.text(pos, rect, forme, tokens); - draw.decorate_text(pos, rect, display, self.text.decorations()); + draw.decorate_text(pos, rect, forme, self.text.decorations()); } } @@ -292,7 +292,7 @@ mod ScrollTextCore { } let rel_pos = (coord - self.rect().pos).cast(); - let cursor = self.text.unchecked_display().text_index_nearest(rel_pos); + let cursor = self.text.unchecked_forme().text_index_nearest(rel_pos); let anchor = if clear { cursor } else { self.selection.anchor }; let range = CursorRange::from(anchor..cursor); @@ -308,7 +308,7 @@ mod ScrollTextCore { } TextInputAction::PressMove { coord, repeats } => { let rel_pos = (coord - self.rect().pos).cast(); - let index = self.text.unchecked_display().text_index_nearest(rel_pos); + let index = self.text.unchecked_forme().text_index_nearest(rel_pos); TextInput::adjust_range( self.text.as_str(),