From a2f1f4b2a0ea18c2ec19f28b8663292659a650d5 Mon Sep 17 00:00:00 2001 From: romanstingler Date: Mon, 11 Aug 2025 21:58:59 +0200 Subject: [PATCH] refactor: address clippy warnings and improve code quality (#409) - Fix string formatting with modern interpolation syntax - Improve Debug implementation with finish_non_exhaustive() - Fix function placement in shape.rs to avoid items_after_statements warning - Use more idiomatic Rust patterns (map_or_else, next_back) - Clean up conditional imports in vi.rs - Convert multiple methods to `const` functions for optimization and consistency - Introduce `core_maths` for enhanced no-std compatibility - Update `Cargo.toml` for the new optional dependency and feature adjustments --- Cargo.toml | 3 +- src/attrs.rs | 62 +++++++++-------- src/bidi_para.rs | 15 ++-- src/buffer.rs | 111 ++++++++++++++---------------- src/buffer_line.rs | 14 ++-- src/cached.rs | 6 +- src/cursor.rs | 4 +- src/edit/editor.rs | 81 ++++++++++------------ src/edit/mod.rs | 6 +- src/edit/vi.rs | 5 +- src/font/fallback/mod.rs | 42 ++++++------ src/font/fallback/other.rs | 6 +- src/font/fallback/unix.rs | 4 +- src/font/mod.rs | 14 ++-- src/font/system.rs | 31 ++++----- src/glyph_cache.rs | 2 +- src/layout.rs | 8 ++- src/line_ending.rs | 8 +-- src/shape.rs | 137 ++++++++++++++++++------------------- src/swash.rs | 22 +++--- 20 files changed, 282 insertions(+), 299 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 091c306..a43caac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ rust-version = "1.75" [dependencies] bitflags = "2.4.1" +core_maths = { version = "0.1.1", optional = true } cosmic_undo_2 = { version = "0.2.0", optional = true } fontdb = { version = "0.23", default-features = false } hashbrown = { version = "0.14.1", optional = true, default-features = false } @@ -48,7 +49,7 @@ optional = true default = ["std", "swash", "fontconfig"] fontconfig = ["fontdb/fontconfig", "std"] monospace_fallback = [] -no_std = ["rustybuzz/libm", "hashbrown", "dep:libm"] +no_std = ["rustybuzz/libm", "hashbrown", "dep:libm", "core_maths"] peniko = ["dep:peniko"] shape-run-cache = [] std = [ diff --git a/src/attrs.rs b/src/attrs.rs index 43f1789..dd105b1 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -30,37 +30,37 @@ impl Color { /// Get a tuple over all of the attributes, in `(r, g, b, a)` order. #[inline] - pub fn as_rgba_tuple(self) -> (u8, u8, u8, u8) { + pub const fn as_rgba_tuple(self) -> (u8, u8, u8, u8) { (self.r(), self.g(), self.b(), self.a()) } /// Get an array over all of the components, in `[r, g, b, a]` order. #[inline] - pub fn as_rgba(self) -> [u8; 4] { + pub const fn as_rgba(self) -> [u8; 4] { [self.r(), self.g(), self.b(), self.a()] } /// Get the red component #[inline] - pub fn r(&self) -> u8 { + pub const fn r(&self) -> u8 { ((self.0 & 0x00_FF_00_00) >> 16) as u8 } /// Get the green component #[inline] - pub fn g(&self) -> u8 { + pub const fn g(&self) -> u8 { ((self.0 & 0x00_00_FF_00) >> 8) as u8 } /// Get the blue component #[inline] - pub fn b(&self) -> u8 { + pub const fn b(&self) -> u8 { (self.0 & 0x00_00_00_FF) as u8 } /// Get the alpha component #[inline] - pub fn a(&self) -> u8 { + pub const fn a(&self) -> u8 { ((self.0 & 0xFF_00_00_00) >> 24) as u8 } } @@ -79,23 +79,23 @@ pub enum FamilyOwned { impl FamilyOwned { pub fn new(family: Family) -> Self { match family { - Family::Name(name) => FamilyOwned::Name(SmolStr::from(name)), - Family::Serif => FamilyOwned::Serif, - Family::SansSerif => FamilyOwned::SansSerif, - Family::Cursive => FamilyOwned::Cursive, - Family::Fantasy => FamilyOwned::Fantasy, - Family::Monospace => FamilyOwned::Monospace, + Family::Name(name) => Self::Name(SmolStr::from(name)), + Family::Serif => Self::Serif, + Family::SansSerif => Self::SansSerif, + Family::Cursive => Self::Cursive, + Family::Fantasy => Self::Fantasy, + Family::Monospace => Self::Monospace, } } pub fn as_family(&self) -> Family { match self { - FamilyOwned::Name(name) => Family::Name(name), - FamilyOwned::Serif => Family::Serif, - FamilyOwned::SansSerif => Family::SansSerif, - FamilyOwned::Cursive => Family::Cursive, - FamilyOwned::Fantasy => Family::Fantasy, - FamilyOwned::Monospace => Family::Monospace, + Self::Name(name) => Family::Name(name), + Self::Serif => Family::Serif, + Self::SansSerif => Family::SansSerif, + Self::Cursive => Family::Cursive, + Self::Fantasy => Family::Fantasy, + Self::Monospace => Family::Monospace, } } } @@ -153,7 +153,7 @@ impl FeatureTag { /// Stylistic Set 2 (font-specific alternate glyphs) pub const STYLISTIC_SET_2: Self = Self::new(b"ss02"); - pub fn as_bytes(&self) -> &[u8; 4] { + pub const fn as_bytes(&self) -> &[u8; 4] { &self.0 } } @@ -170,7 +170,7 @@ pub struct FontFeatures { } impl FontFeatures { - pub fn new() -> Self { + pub const fn new() -> Self { Self { features: Vec::new(), } @@ -244,7 +244,7 @@ impl<'a> Attrs<'a> { /// Create a new set of attributes with sane defaults /// /// This defaults to a regular Sans-Serif font. - pub fn new() -> Self { + pub const fn new() -> Self { Self { color_opt: None, family: Family::SansSerif, @@ -260,43 +260,43 @@ impl<'a> Attrs<'a> { } /// Set [Color] - pub fn color(mut self, color: Color) -> Self { + pub const fn color(mut self, color: Color) -> Self { self.color_opt = Some(color); self } /// Set [Family] - pub fn family(mut self, family: Family<'a>) -> Self { + pub const fn family(mut self, family: Family<'a>) -> Self { self.family = family; self } /// Set [Stretch] - pub fn stretch(mut self, stretch: Stretch) -> Self { + pub const fn stretch(mut self, stretch: Stretch) -> Self { self.stretch = stretch; self } /// Set [Style] - pub fn style(mut self, style: Style) -> Self { + pub const fn style(mut self, style: Style) -> Self { self.style = style; self } /// Set [Weight] - pub fn weight(mut self, weight: Weight) -> Self { + pub const fn weight(mut self, weight: Weight) -> Self { self.weight = weight; self } /// Set metadata - pub fn metadata(mut self, metadata: usize) -> Self { + pub const fn metadata(mut self, metadata: usize) -> Self { self.metadata = metadata; self } /// Set [`CacheKeyFlags`] - pub fn cache_key_flags(mut self, cache_key_flags: CacheKeyFlags) -> Self { + pub const fn cache_key_flags(mut self, cache_key_flags: CacheKeyFlags) -> Self { self.cache_key_flags = cache_key_flags; self } @@ -308,7 +308,7 @@ impl<'a> Attrs<'a> { } /// Set letter spacing (tracking) in EM - pub fn letter_spacing(mut self, letter_spacing: f32) -> Self { + pub const fn letter_spacing(mut self, letter_spacing: f32) -> Self { self.letter_spacing_opt = Some(LetterSpacing(letter_spacing)); self } @@ -471,7 +471,9 @@ impl AttrsList { for span in self.spans.iter() { if span.0.end <= index { continue; - } else if span.0.start >= index { + } + + if span.0.start >= index { removes.push((span.0.clone(), false)); } else { removes.push((span.0.clone(), true)); diff --git a/src/bidi_para.rs b/src/bidi_para.rs index fefdc1c..ed0741f 100644 --- a/src/bidi_para.rs +++ b/src/bidi_para.rs @@ -63,13 +63,12 @@ impl<'text> Iterator for BidiParagraphs<'text> { let paragraph = &self.text[para.range]; // `para.range` includes the newline that splits the line, so remove it if present let mut char_indices = paragraph.char_indices(); - if let Some(i) = char_indices.next_back().and_then(|(i, c)| { - // `BidiClass::B` is a Paragraph_Separator (various newline characters) - (bidi_class(c) == BidiClass::B).then_some(i) - }) { - Some(¶graph[0..i]) - } else { - Some(paragraph) - } + char_indices + .next_back() + .and_then(|(i, c)| { + // `BidiClass::B` is a Paragraph_Separator (various newline characters) + (bidi_class(c) == BidiClass::B).then_some(i) + }) + .map_or(Some(paragraph), |i| Some(¶graph[0..i])) } } diff --git a/src/buffer.rs b/src/buffer.rs index b13e96d..0905c86 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -2,11 +2,16 @@ #[cfg(not(feature = "std"))] use alloc::{string::String, vec::Vec}; + use core::{cmp, fmt}; + +#[cfg(not(feature = "std"))] +use core_maths::CoreFloat; use unicode_segmentation::UnicodeSegmentation; #[cfg(feature = "swash")] use crate::Color; + use crate::{ Affinity, Align, Attrs, AttrsList, BidiParagraphs, BorrowedWithFontSystem, BufferLine, Cursor, FontSystem, LayoutCursor, LayoutGlyph, LayoutLine, LineEnding, LineIter, Motion, Scroll, @@ -45,36 +50,34 @@ impl LayoutRun<'_> { let mut x_end = None; let rtl_factor = if self.rtl { 1. } else { 0. }; let ltr_factor = 1. - rtl_factor; - for glyph in self.glyphs.iter() { + for glyph in self.glyphs { let cursor = self.cursor_from_glyph_left(glyph); if cursor >= cursor_start && cursor <= cursor_end { if x_start.is_none() { - x_start = Some(glyph.x + glyph.w * rtl_factor); + x_start = Some(glyph.x + glyph.w.mul_add(rtl_factor, 0.0)); } - x_end = Some(glyph.x + glyph.w * rtl_factor); + x_end = Some(glyph.x + glyph.w.mul_add(rtl_factor, 0.0)); } let cursor = self.cursor_from_glyph_right(glyph); if cursor >= cursor_start && cursor <= cursor_end { if x_start.is_none() { - x_start = Some(glyph.x + glyph.w * ltr_factor); + x_start = Some(glyph.x + glyph.w.mul_add(ltr_factor, 0.0)); } - x_end = Some(glyph.x + glyph.w * ltr_factor); + x_end = Some(glyph.x + glyph.w.mul_add(ltr_factor, 0.0)); } } - if let Some(x_start) = x_start { + x_start.map(|x_start| { let x_end = x_end.expect("end of cursor not found"); let (x_start, x_end) = if x_start < x_end { (x_start, x_end) } else { (x_end, x_start) }; - Some((x_start, x_end - x_start)) - } else { - None - } + (x_start, x_end - x_start) + }) } - fn cursor_from_glyph_left(&self, glyph: &LayoutGlyph) -> Cursor { + const fn cursor_from_glyph_left(&self, glyph: &LayoutGlyph) -> Cursor { if self.rtl { Cursor::new_with_affinity(self.line_i, glyph.end, Affinity::Before) } else { @@ -82,7 +85,7 @@ impl LayoutRun<'_> { } } - fn cursor_from_glyph_right(&self, glyph: &LayoutGlyph) -> Cursor { + const fn cursor_from_glyph_right(&self, glyph: &LayoutGlyph) -> Cursor { if self.rtl { Cursor::new_with_affinity(self.line_i, glyph.start, Affinity::After) } else { @@ -102,7 +105,7 @@ pub struct LayoutRunIter<'b> { } impl<'b> LayoutRunIter<'b> { - pub fn new(buffer: &'b Buffer) -> Self { + pub const fn new(buffer: &'b Buffer) -> Self { Self { buffer, line_i: buffer.scroll.line, @@ -276,7 +279,7 @@ impl Buffer { pub fn borrow_with<'a>( &'a mut self, font_system: &'a mut FontSystem, - ) -> BorrowedWithFontSystem<'a, Buffer> { + ) -> BorrowedWithFontSystem<'a, Self> { BorrowedWithFontSystem { inner: self, font_system, @@ -358,7 +361,7 @@ impl Buffer { let layout = self .line_layout(font_system, line_i) .expect("shape_until_cursor failed to scroll forwards"); - for layout_line in layout.iter() { + for layout_line in layout { total_height += layout_line.line_height_opt.unwrap_or(metrics.line_height); } if total_height > height + self.scroll.vertical { @@ -379,18 +382,16 @@ impl Buffer { if let Some(layout_cursor) = self.layout_cursor(font_system, cursor) { if let Some(layout_lines) = self.line_layout(font_system, layout_cursor.line) { if let Some(layout_line) = layout_lines.get(layout_cursor.layout) { - let (x_min, x_max) = if let Some(glyph) = layout_line + let (x_min, x_max) = layout_line .glyphs .get(layout_cursor.glyph) .or_else(|| layout_line.glyphs.last()) - { - //TODO: use code from cursor_glyph_opt? - let x_a = glyph.x; - let x_b = glyph.x + glyph.w; - (x_a.min(x_b), x_a.max(x_b)) - } else { - (0.0, 0.0) - }; + .map_or((0.0, 0.0), |glyph| { + //TODO: use code from cursor_glyph_opt? + let x_a = glyph.x; + let x_b = glyph.x + glyph.w; + (x_a.min(x_b), x_a.max(x_b)) + }); if x_min < self.scroll.horizontal { self.scroll.horizontal = x_min; self.redraw = true; @@ -419,7 +420,7 @@ impl Buffer { let line_i = self.scroll.line - 1; if let Some(layout) = self.line_layout(font_system, line_i) { let mut layout_height = 0.0; - for layout_line in layout.iter() { + for layout_line in layout { layout_height += layout_line.line_height_opt.unwrap_or(metrics.line_height); } @@ -451,16 +452,15 @@ impl Buffer { if prune { self.lines[line_i].reset_shaping(); continue; - } else { - break; } + break; } let mut layout_height = 0.0; let layout = self .line_layout(font_system, line_i) .expect("shape_until_scroll invalid line"); - for layout_line in layout.iter() { + for layout_line in layout { let line_height = layout_line.line_height_opt.unwrap_or(metrics.line_height); layout_height += line_height; total_height += line_height; @@ -547,7 +547,7 @@ impl Buffer { } /// Get the current [`Metrics`] - pub fn metrics(&self) -> Metrics { + pub const fn metrics(&self) -> Metrics { self.metrics } @@ -561,7 +561,7 @@ impl Buffer { } /// Get the current [`Wrap`] - pub fn wrap(&self) -> Wrap { + pub const fn wrap(&self) -> Wrap { self.wrap } @@ -575,7 +575,7 @@ impl Buffer { } /// Get the current `monospace_width` - pub fn monospace_width(&self) -> Option { + pub const fn monospace_width(&self) -> Option { self.monospace_width } @@ -593,7 +593,7 @@ impl Buffer { } /// Get the current `tab_width` - pub fn tab_width(&self) -> u16 { + pub const fn tab_width(&self) -> u16 { self.tab_width } @@ -606,7 +606,7 @@ impl Buffer { if tab_width != self.tab_width { self.tab_width = tab_width; // Shaping must be reset when tab width is changed - for line in self.lines.iter_mut() { + for line in &mut self.lines { if line.shape_opt().is_some() && line.text().contains('\t') { line.reset_shaping(); } @@ -617,7 +617,7 @@ impl Buffer { } /// Get the current buffer dimensions (width, height) - pub fn size(&self) -> (Option, Option) { + pub const fn size(&self) -> (Option, Option) { (self.width_opt, self.height_opt) } @@ -660,7 +660,7 @@ impl Buffer { } /// Get the current scroll location - pub fn scroll(&self) -> Scroll { + pub const fn scroll(&self) -> Scroll { self.scroll } @@ -758,8 +758,7 @@ impl Buffer { let mut attrs_list = self .lines .get_mut(line_count) - .map(BufferLine::reclaim_attrs) - .unwrap_or_else(|| AttrsList::new(&Attrs::new())) + .map_or_else(|| AttrsList::new(&Attrs::new()), BufferLine::reclaim_attrs) .reset(default_attrs); let mut line_string = self .lines @@ -811,8 +810,7 @@ impl Buffer { let next_attrs_list = self .lines .get_mut(line_count + 1) - .map(BufferLine::reclaim_attrs) - .unwrap_or_else(|| AttrsList::new(&Attrs::new())) + .map_or_else(|| AttrsList::new(&Attrs::new()), BufferLine::reclaim_attrs) .reset(default_attrs); let next_line_string = self .lines @@ -856,7 +854,7 @@ impl Buffer { } /// True if a redraw is needed - pub fn redraw(&self) -> bool { + pub const fn redraw(&self) -> bool { self.redraw } @@ -866,7 +864,7 @@ impl Buffer { } /// Get the visible layout runs for rendering and other tasks - pub fn layout_runs(&self) -> LayoutRunIter { + pub const fn layout_runs(&self) -> LayoutRunIter { LayoutRunIter::new(self) } @@ -991,14 +989,16 @@ impl Buffer { }, }; - let (new_index, new_affinity) = match layout_line.glyphs.get(layout_cursor.glyph) { - Some(glyph) => (glyph.start, Affinity::After), - None => match layout_line.glyphs.last() { - Some(glyph) => (glyph.end, Affinity::Before), - //TODO: is this correct? - None => (0, Affinity::After), - }, - }; + let (new_index, new_affinity) = + layout_line.glyphs.get(layout_cursor.glyph).map_or_else( + || { + layout_line + .glyphs + .last() + .map_or((0, Affinity::After), |glyph| (glyph.end, Affinity::Before)) + }, + |glyph| (glyph.start, Affinity::After), + ); if cursor.line != layout_cursor.line || cursor.index != new_index @@ -1159,8 +1159,7 @@ impl Buffer { cursor.index = line .text() .char_indices() - .filter_map(|(i, c)| if c.is_whitespace() { None } else { Some(i) }) - .next() + .find_map(|(i, c)| if c.is_whitespace() { None } else { Some(i) }) .unwrap_or(0); cursor_x_opt = None; } @@ -1253,7 +1252,7 @@ impl Buffer { .unicode_word_indices() .map(|(i, word)| i + word.len()) .find(|&i| i > cursor.index) - .unwrap_or(line.text().len()); + .unwrap_or_else(|| line.text().len()); } else if cursor.line + 1 < self.lines.len() { cursor.line += 1; cursor.index = 0; @@ -1340,13 +1339,9 @@ impl Buffer { F: FnMut(i32, i32, u32, u32, Color), { for run in self.layout_runs() { - for glyph in run.glyphs.iter() { + for glyph in run.glyphs { let physical_glyph = glyph.physical((0., 0.), 1.0); - - let glyph_color = match glyph.color_opt { - Some(some) => some, - None => color, - }; + let glyph_color = glyph.color_opt.map_or(color, |some| some); cache.with_pixels( font_system, diff --git a/src/buffer_line.rs b/src/buffer_line.rs index 6929e03..cec5077 100644 --- a/src/buffer_line.rs +++ b/src/buffer_line.rs @@ -95,7 +95,7 @@ impl BufferLine { } /// Get line ending - pub fn ending(&self) -> LineEnding { + pub const fn ending(&self) -> LineEnding { self.ending } @@ -114,7 +114,7 @@ impl BufferLine { } /// Get attributes list - pub fn attrs_list(&self) -> &AttrsList { + pub const fn attrs_list(&self) -> &AttrsList { &self.attrs_list } @@ -133,7 +133,7 @@ impl BufferLine { } /// Get the Text alignment - pub fn align(&self) -> Option { + pub const fn align(&self) -> Option { self.align } @@ -155,7 +155,7 @@ impl BufferLine { /// Append line at end of this line /// /// The wrap setting of the appended line will be lost - pub fn append(&mut self, other: Self) { + pub fn append(&mut self, other: &Self) { let len = self.text.len(); self.text.push_str(other.text()); @@ -224,7 +224,7 @@ impl BufferLine { } /// Get line shaping cache - pub fn shape_opt(&self) -> Option<&ShapeLine> { + pub const fn shape_opt(&self) -> Option<&ShapeLine> { self.shape_opt.get() } @@ -261,13 +261,13 @@ impl BufferLine { } /// Get line layout cache - pub fn layout_opt(&self) -> Option<&Vec> { + pub const fn layout_opt(&self) -> Option<&Vec> { self.layout_opt.get() } /// Get line metadata. This will be None if [`BufferLine::set_metadata`] has not been called /// after the last reset of shaping and layout caches - pub fn metadata(&self) -> Option { + pub const fn metadata(&self) -> Option { self.metadata } diff --git a/src/cached.rs b/src/cached.rs index cf7e1ac..51079e8 100644 --- a/src/cached.rs +++ b/src/cached.rs @@ -11,7 +11,7 @@ pub enum Cached { impl Cached { /// Gets the value if in state `Self::Used`. - pub fn get(&self) -> Option<&T> { + pub const fn get(&self) -> Option<&T> { match self { Self::Empty | Self::Unused(_) => None, Self::Used(t) => Some(t), @@ -27,7 +27,7 @@ impl Cached { } /// Checks if the value is empty or unused. - pub fn is_unused(&self) -> bool { + pub const fn is_unused(&self) -> bool { match self { Self::Empty | Self::Unused(_) => true, Self::Used(_) => false, @@ -35,7 +35,7 @@ impl Cached { } /// Checks if the value is used (i.e. cached for access). - pub fn is_used(&self) -> bool { + pub const fn is_used(&self) -> bool { match self { Self::Empty | Self::Unused(_) => false, Self::Used(_) => true, diff --git a/src/cursor.rs b/src/cursor.rs index e6358c6..13bfbda 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -43,7 +43,7 @@ impl Affinity { *self == Self::After } - pub fn from_before(before: bool) -> Self { + pub const fn from_before(before: bool) -> Self { if before { Self::Before } else { @@ -51,7 +51,7 @@ impl Affinity { } } - pub fn from_after(after: bool) -> Self { + pub const fn from_after(after: bool) -> Self { if after { Self::After } else { diff --git a/src/edit/editor.rs b/src/edit/editor.rs index 8060b6d..a738428 100644 --- a/src/edit/editor.rs +++ b/src/edit/editor.rs @@ -1,21 +1,24 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 +#[cfg(not(feature = "std"))] +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; + +#[cfg(feature = "swash")] +use std::cmp; + +use core::iter::once; +use unicode_segmentation::UnicodeSegmentation; + #[cfg(feature = "swash")] use crate::Color; use crate::{ Action, Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, BufferRef, Change, ChangeItem, Cursor, Edit, FontSystem, LayoutRun, Selection, Shaping, }; -#[cfg(feature = "no_std")] -use alloc::{ - string::{String, ToString}, - vec::Vec, -}; -#[cfg(feature = "swash")] -use std::cmp; -use core::iter::once; -use unicode_segmentation::UnicodeSegmentation; /// A wrapper of [`Buffer`] for easy editing #[derive(Debug, Clone)] pub struct Editor<'buffer> { @@ -66,30 +69,24 @@ fn cursor_glyph_opt(cursor: &Cursor, run: &LayoutRun) -> Option<(usize, f32)> { fn cursor_position(cursor: &Cursor, run: &LayoutRun) -> Option<(i32, i32)> { let (cursor_glyph, cursor_glyph_offset) = cursor_glyph_opt(cursor, run)?; - let x = match run.glyphs.get(cursor_glyph) { - Some(glyph) => { - // Start of detected glyph - if glyph.level.is_rtl() { - (glyph.x + glyph.w - cursor_glyph_offset) as i32 - } else { - (glyph.x + cursor_glyph_offset) as i32 - } - } - None => match run.glyphs.last() { - Some(glyph) => { - // End of last glyph + let x = run.glyphs.get(cursor_glyph).map_or_else( + || { + run.glyphs.last().map_or(0, |glyph| { if glyph.level.is_rtl() { glyph.x as i32 } else { (glyph.x + glyph.w) as i32 } - } - None => { - // Start of empty line - 0 + }) + }, + |glyph| { + if glyph.level.is_rtl() { + (glyph.x + glyph.w - cursor_glyph_offset) as i32 + } else { + (glyph.x + cursor_glyph_offset) as i32 } }, - }; + ); Some((x, run.line_top as i32)) } @@ -135,7 +132,7 @@ impl<'buffer> Editor<'buffer> { if let Some((start, end)) = selection_bounds { if line_i >= start.line && line_i <= end.line { let mut range_opt = None; - for glyph in run.glyphs.iter() { + for glyph in run.glyphs { // Guess x offset based on characters let cluster = &run.text[glyph.start..glyph.end]; let total = cluster.grapheme_indices(true).count(); @@ -197,13 +194,10 @@ impl<'buffer> Editor<'buffer> { f(x, y, 1, line_height as u32, cursor_color); } - for glyph in run.glyphs.iter() { + for glyph in run.glyphs { let physical_glyph = glyph.physical((0., 0.), 1.0); - let mut glyph_color = match glyph.color_opt { - Some(some) => some, - None => text_color, - }; + let mut glyph_color = glyph.color_opt.map_or(text_color, |some| some); if text_color != selected_text_color { if let Some((start, end)) = selection_bounds { if line_i >= start.line @@ -277,7 +271,7 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { } fn tab_width(&self) -> u16 { - self.with_buffer(|buffer| buffer.tab_width()) + self.with_buffer(super::super::buffer::Buffer::tab_width) } fn set_tab_width(&mut self, font_system: &mut FontSystem, tab_width: u16) { @@ -334,12 +328,12 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { // Re-add part of line after selection if let Some(after) = after_opt { - buffer.lines[start.line].append(after); + buffer.lines[start.line].append(&after); } // Re-add valid parts of end line if let Some(end_line) = end_line_opt { - buffer.lines[start.line].append(end_line); + buffer.lines[start.line].append(&end_line); } } @@ -376,7 +370,7 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { let ending = buffer .lines .last() - .map(|line| line.ending()) + .map(super::super::buffer_line::BufferLine::ending) .unwrap_or_default(); let line = BufferLine::new( String::new(), @@ -386,7 +380,7 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { buffer .lines .last() - .map_or(Attrs::new(), |line| line.attrs_list().defaults()) + .map_or_else(Attrs::new, |line| line.attrs_list().defaults()) }, |x| x.defaults(), )), @@ -417,7 +411,7 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { let mut these_attrs = final_attrs.split_off(data_line.len()); remaining_split_len -= data_line.len(); core::mem::swap(&mut these_attrs, &mut final_attrs); - line.append(BufferLine::new( + line.append(&BufferLine::new( data_line .strip_suffix(char::is_control) .unwrap_or(data_line), @@ -438,11 +432,11 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { final_attrs.split_off(remaining_split_len), Shaping::Advanced, ); - tmp.append(after); + tmp.append(&after); buffer.lines.insert(insert_line, tmp); cursor.line += 1; } else { - line.append(after); + line.append(&after); } for data_line in lines_iter.rev() { remaining_split_len -= data_line.len(); @@ -510,9 +504,8 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { } fn delete_selection(&mut self) -> bool { - let (start, end) = match self.selection_bounds() { - Some(some) => some, - None => return false, + let Some((start, end)) = self.selection_bounds() else { + return false; }; // Reset cursor to start of selection @@ -538,7 +531,7 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> { } } - for item in change.items.iter() { + for item in &change.items { //TODO: edit cursor if needed? if item.insert { self.cursor = self.insert_at(item.start, &item.text, None); diff --git a/src/edit/mod.rs b/src/edit/mod.rs index a27fa41..24784be 100644 --- a/src/edit/mod.rs +++ b/src/edit/mod.rs @@ -130,7 +130,7 @@ impl Change { // Reverse change (in place) pub fn reverse(&mut self) { self.items.reverse(); - for item in self.items.iter_mut() { + for item in &mut self.items { item.reverse(); } } @@ -192,7 +192,7 @@ pub trait Edit<'buffer> { /// Get the [`Buffer`] redraw flag fn redraw(&self) -> bool { - self.with_buffer(|buffer| buffer.redraw()) + self.with_buffer(super::buffer::Buffer::redraw) } /// Set the [`Buffer`] redraw flag @@ -273,7 +273,7 @@ pub trait Edit<'buffer> { .unicode_word_indices() .map(|(i, word)| i + word.len()) .find(|&i| i > end.index) - .unwrap_or(line.text().len()); + .unwrap_or_else(|| line.text().len()); } Some((start, end)) diff --git a/src/edit/vi.rs b/src/edit/vi.rs index 9540234..165523e 100644 --- a/src/edit/vi.rs +++ b/src/edit/vi.rs @@ -1,7 +1,6 @@ -#[cfg(feature = "no_std")] -use core::cmp; - use alloc::{collections::BTreeMap, string::String}; +#[cfg(feature = "swash")] +use core::cmp; use modit::{Event, Key, Parser, TextObject, WordIter}; use crate::{ diff --git a/src/font/fallback/mod.rs b/src/font/fallback/mod.rs index 05c392b..00b7218 100644 --- a/src/font/fallback/mod.rs +++ b/src/font/fallback/mod.rs @@ -77,7 +77,7 @@ pub trait Fallback: Send + Sync { } #[derive(Debug, Default)] -pub(crate) struct Fallbacks { +pub struct Fallbacks { lists: Vec<&'static str>, common_fallback_range: Range, forbidden_fallback_range: Range, @@ -174,13 +174,14 @@ use log::warn as missing_warn; // Default font gets None for both `weight_offset` and `script_non_matches`, and thus, it is // always the first to be popped from the set. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub(crate) struct MonospaceFallbackInfo { +pub struct MonospaceFallbackInfo { font_weight_diff: Option, codepoint_non_matches: Option, font_weight: u16, id: fontdb::ID, } +#[derive(Debug)] pub struct FontFallbackIter<'a> { font_system: &'a mut FontSystem, font_match_keys: &'a [FontMatchKey], @@ -223,7 +224,7 @@ impl<'a> FontFallbackIter<'a> { } } - pub fn check_missing(&mut self, word: &str) { + pub fn check_missing(&self, word: &str) { if self.end { missing_warn!( "Failed to find any fallback for {:?} locale '{}': '{}'", @@ -252,15 +253,16 @@ impl<'a> FontFallbackIter<'a> { } pub fn face_name(&self, id: fontdb::ID) -> &str { - if let Some(face) = self.font_system.db().face(id) { - if let Some((name, _)) = face.families.first() { - name - } else { - &face.post_script_name - } - } else { - "invalid font id" - } + self.font_system + .db() + .face(id) + .map_or("invalid font id", |face| { + if let Some((name, _)) = face.families.first() { + name + } else { + &face.post_script_name + } + }) } pub fn shape_caches(&mut self) -> &mut ShapeBuffer { @@ -268,11 +270,10 @@ impl<'a> FontFallbackIter<'a> { } fn face_contains_family(&self, id: fontdb::ID, family_name: &str) -> bool { - if let Some(face) = self.font_system.db().face(id) { - face.families.iter().any(|(name, _)| name == family_name) - } else { - false - } + self.font_system + .db() + .face(id) + .is_some_and(|face| face.families.iter().any(|(name, _)| name == family_name)) } fn default_font_match_key(&self) -> Option<&FontMatchKey> { @@ -304,7 +305,7 @@ impl<'a> FontFallbackIter<'a> { 'DEF_FAM: while self.default_i < self.default_families.len() { self.default_i += 1; let is_mono = self.default_families[self.default_i - 1] == &Family::Monospace; - let default_font_match_key = self.default_font_match_key().cloned(); + let default_font_match_key = self.default_font_match_key().copied(); let word_chars_count = self.word.chars().count(); macro_rules! mk_mono_fallback_info { @@ -334,9 +335,8 @@ impl<'a> FontFallbackIter<'a> { (false, Some(m_key)) => { if let Some(font) = self.font_system.get_font(m_key.id, self.ideal_weight) { return Some(font); - } else { - break 'DEF_FAM; } + break 'DEF_FAM; } (true, None) => (), (true, Some(m_key)) => { @@ -360,7 +360,7 @@ impl<'a> FontFallbackIter<'a> { } } } - }; + } let mono_ids_for_scripts = if is_mono && !self.scripts.is_empty() { let scripts = self.scripts.iter().filter_map(|script| { diff --git a/src/font/fallback/other.rs b/src/font/fallback/other.rs index 7659d80..77d821a 100644 --- a/src/font/fallback/other.rs +++ b/src/font/fallback/other.rs @@ -27,16 +27,16 @@ impl Fallback for PlatformFallback { } // Fallbacks to use after any script specific fallbacks -fn common_fallback() -> &'static [&'static str] { +const fn common_fallback() -> &'static [&'static str] { &[] } // Fallbacks to never use -fn forbidden_fallback() -> &'static [&'static str] { +const fn forbidden_fallback() -> &'static [&'static str] { &[] } // Fallbacks to use per script -fn script_fallback(_script: Script, _locale: &str) -> &'static [&'static str] { +const fn script_fallback(_script: Script, _locale: &str) -> &'static [&'static str] { &[] } diff --git a/src/font/fallback/unix.rs b/src/font/fallback/unix.rs index 12c4a7e..ecd99aa 100644 --- a/src/font/fallback/unix.rs +++ b/src/font/fallback/unix.rs @@ -27,7 +27,7 @@ impl Fallback for PlatformFallback { } // Fallbacks to use after any script specific fallbacks -fn common_fallback() -> &'static [&'static str] { +const fn common_fallback() -> &'static [&'static str] { //TODO: abstract style (sans/serif/monospaced) &[ /* Sans-serif fallbacks */ @@ -49,7 +49,7 @@ fn common_fallback() -> &'static [&'static str] { } // Fallbacks to never use -fn forbidden_fallback() -> &'static [&'static str] { +const fn forbidden_fallback() -> &'static [&'static str] { &[] } diff --git a/src/font/mod.rs b/src/font/mod.rs index a8d6663..2f97704 100644 --- a/src/font/mod.rs +++ b/src/font/mod.rs @@ -15,7 +15,7 @@ use alloc::vec::Vec; use rustybuzz::Face as RustybuzzFace; use self_cell::self_cell; -pub(crate) mod fallback; +pub mod fallback; pub use fallback::{Fallback, PlatformFallback}; pub use self::system::*; @@ -58,7 +58,7 @@ impl fmt::Debug for Font { } impl Font { - pub fn id(&self) -> fontdb::ID { + pub const fn id(&self) -> fontdb::ID { self.id } @@ -119,9 +119,9 @@ impl Font { let monospace_em_width = info .monospaced .then(|| { - let hor_advance = face.glyph_hor_advance(face.glyph_index(' ')?)? as f32; - let upem = face.units_per_em() as f32; - Some(hor_advance / upem) + let hor_advance = face.glyph_hor_advance(face.glyph_index(' ')?)?; + let upem = face.units_per_em(); + Some(f32::from(hor_advance) / f32::from(upem)) }) .flatten(); @@ -144,7 +144,7 @@ impl Font { .cmap? .subtables .into_iter() - .filter(|subtable| subtable.is_unicode()) + .filter(ttf_parser::cmap::Subtable::is_unicode) .for_each(|subtable| { unicode_codepoints.reserve(1024); subtable.codepoints(|code_point| { @@ -194,7 +194,7 @@ impl Font { .into_iter() .find(|axis| axis.tag == ttf_parser::Tag::from_bytes(b"wght")) { - let wght = (weight.0 as f32).clamp(axis.min_value, axis.max_value); + let wght = f32::from(weight.0).clamp(axis.min_value, axis.max_value); let _ = face.set_variation(ttf_parser::Tag::from_bytes(b"wght"), wght); } face diff --git a/src/font/system.rs b/src/font/system.rs index 8a47e4a..6ddc24d 100644 --- a/src/font/system.rs +++ b/src/font/system.rs @@ -127,7 +127,7 @@ impl fmt::Debug for FontSystem { f.debug_struct("FontSystem") .field("locale", &self.locale) .field("db", &self.db) - .finish() + .finish_non_exhaustive() } } @@ -180,7 +180,7 @@ impl FontSystem { HashMap::default(); if cfg!(feature = "monospace_fallback") { - monospace_font_ids.iter().for_each(|&id| { + for &id in &monospace_font_ids { db.with_face_data(id, |font_data, face_index| { let _ = ttf_parser::Face::parse(font_data, face_index).map(|face| { face.tables() @@ -196,7 +196,7 @@ impl FontSystem { }) }); }); - }); + } } let per_script_monospace_font_ids = per_script_monospace_font_ids @@ -211,9 +211,9 @@ impl FontSystem { db, monospace_font_ids, per_script_monospace_font_ids, - font_cache: Default::default(), - font_matches_cache: Default::default(), - font_codepoint_support_info_cache: Default::default(), + font_cache: HashMap::default(), + font_matches_cache: HashMap::default(), + font_codepoint_support_info_cache: HashMap::default(), monospace_fallbacks_buffer: BTreeSet::default(), #[cfg(feature = "shape-run-cache")] shape_run_cache: crate::ShapeRunCache::default(), @@ -234,7 +234,7 @@ impl FontSystem { } /// Get the database. - pub fn db(&self) -> &fontdb::Database { + pub const fn db(&self) -> &fontdb::Database { &self.db } @@ -258,15 +258,14 @@ impl FontSystem { unsafe { self.db.make_shared_face_data(id); } - match Font::new(&self.db, id, weight) { - Some(font) => Some(Arc::new(font)), - None => { - log::warn!( - "failed to load font '{}'", - self.db.face(id)?.post_script_name - ); - None - } + if let Some(font) = Font::new(&self.db, id, weight) { + Some(Arc::new(font)) + } else { + log::warn!( + "failed to load font '{}'", + self.db.face(id)?.post_script_name + ); + None } }) .clone() diff --git a/src/glyph_cache.rs b/src/glyph_cache.rs index ffec6d4..ef21c8a 100644 --- a/src/glyph_cache.rs +++ b/src/glyph_cache.rs @@ -102,7 +102,7 @@ impl SubpixelBin { } } - pub fn as_float(&self) -> f32 { + pub const fn as_float(&self) -> f32 { match self { Self::Zero => 0.0, Self::One => 0.25, diff --git a/src/layout.rs b/src/layout.rs index a3926fd..0d45703 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -2,10 +2,12 @@ use core::fmt::Display; +use crate::{math, CacheKey, CacheKeyFlags, Color}; #[cfg(not(feature = "std"))] use alloc::vec::Vec; -use crate::{math, CacheKey, CacheKeyFlags, Color}; +#[cfg(not(feature = "std"))] +use core_maths::CoreFloat; /// A laid out glyph #[derive(Clone, Debug)] @@ -78,8 +80,8 @@ impl LayoutGlyph { self.glyph_id, self.font_size * scale, ( - (self.x + x_offset) * scale + offset.0, - math::truncf((self.y - y_offset) * scale + offset.1), // Hinting in Y axis + (self.x + x_offset).mul_add(scale, offset.0), + math::truncf((self.y - y_offset).mul_add(scale, offset.1)), // Hinting in Y axis ), self.font_weight, self.cache_key_flags, diff --git a/src/line_ending.rs b/src/line_ending.rs index 13c1488..cca9aa4 100644 --- a/src/line_ending.rs +++ b/src/line_ending.rs @@ -18,7 +18,7 @@ pub enum LineEnding { impl LineEnding { /// Get the line ending as a str - pub fn as_str(&self) -> &'static str { + pub const fn as_str(&self) -> &'static str { match self { Self::Lf => "\n", Self::CrLf => "\r\n", @@ -39,7 +39,7 @@ pub struct LineIter<'a> { impl<'a> LineIter<'a> { /// Create an iterator of lines in a string slice - pub fn new(string: &'a str) -> Self { + pub const fn new(string: &'a str) -> Self { Self { string, start: 0, @@ -61,9 +61,9 @@ impl Iterator for LineIter<'_> { LineEnding::CrLf } else if after.starts_with("\n\r") { LineEnding::LfCr - } else if after.starts_with("\n") { + } else if after.starts_with('\n') { LineEnding::Lf - } else if after.starts_with("\r") { + } else if after.starts_with('\r') { LineEnding::Cr } else { //TODO: this should not be possible diff --git a/src/shape.rs b/src/shape.rs index 624da32..91365a5 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -2,20 +2,23 @@ #![allow(clippy::too_many_arguments)] -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; -use core::cmp::{max, min}; -use core::fmt; -use core::mem; -use core::ops::Range; -use unicode_script::{Script, UnicodeScript}; -use unicode_segmentation::UnicodeSegmentation; - use crate::fallback::FontFallbackIter; use crate::{ math, Align, AttrsList, CacheKeyFlags, Color, Font, FontSystem, LayoutGlyph, LayoutLine, Metrics, Wrap, }; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +use core::cmp::{max, min}; +use core::fmt; +use core::mem; +use core::ops::Range; + +#[cfg(not(feature = "std"))] +use core_maths::CoreFloat; +use unicode_script::{Script, UnicodeScript}; +use unicode_segmentation::UnicodeSegmentation; /// The shaping strategy of some text. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -117,8 +120,8 @@ fn shape_fallback( let run = &line[start_run..end_run]; let font_scale = font.rustybuzz().units_per_em() as f32; - let ascent = font.rustybuzz().ascender() as f32 / font_scale; - let descent = -font.rustybuzz().descender() as f32 / font_scale; + let ascent = f32::from(font.rustybuzz().ascender()) / font_scale; + let descent = -f32::from(font.rustybuzz().descender()) / font_scale; let mut buffer = scratch.rustybuzz_buffer.take().unwrap_or_default(); buffer.set_direction(if span_rtl { @@ -197,7 +200,7 @@ fn shape_fallback( color_opt: attrs.color_opt, metadata: attrs.metadata, cache_key_flags: attrs.cache_key_flags, - metrics_opt: attrs.metrics_opt.map(|x| x.into()), + metrics_opt: attrs.metrics_opt.map(Into::into), }); } @@ -286,9 +289,8 @@ fn shape_run( //TODO: improve performance! while !missing.is_empty() { - let font = match font_iter.next() { - Some(some) => some, - None => break, + let Some(font) = font_iter.next() else { + break; }; log::trace!( @@ -335,9 +337,8 @@ fn shape_run( while i < glyphs.len() { if glyphs[i].start >= start && glyphs[i].end <= end { break; - } else { - i += 1; } + i += 1; } // Remove prior glyphs @@ -495,7 +496,7 @@ fn shape_skip( color_opt: attrs.color_opt, metadata: attrs.metadata, cache_key_flags: attrs.cache_key_flags, - metrics_opt: attrs.metrics_opt.map(|x| x.into()), + metrics_opt: attrs.metrics_opt.map(Into::into), } }), ); @@ -523,7 +524,7 @@ pub struct ShapeGlyph { } impl ShapeGlyph { - fn layout( + const fn layout( &self, font_size: f32, line_height_opt: Option, @@ -633,7 +634,7 @@ impl ShapeWord { word.is_ascii() && !word.chars().any(|c| c.is_ascii_control() && c != '\t'); if is_simple_ascii && !word.is_empty() { - let attrs = attrs_list.defaults(); + let _attrs = attrs_list.defaults(); shaping.run( &mut glyphs, font_system, @@ -685,7 +686,7 @@ impl ShapeWord { /// Get the width of the [`ShapeWord`] in pixels, using the [`ShapeGlyph::width`] function. pub fn width(&self, font_size: f32) -> f32 { let mut width = 0.0; - for glyph in self.glyphs.iter() { + for glyph in &self.glyphs { width += glyph.width(font_size); } width @@ -920,7 +921,7 @@ impl ShapeLine { log::trace!("Line {}: '{}'", if rtl { "RTL" } else { "LTR" }, line); - for para_info in bidi.paragraphs.iter() { + for para_info in &bidi.paragraphs { let line_rtl = para_info.level.is_rtl(); assert_eq!(line_rtl, rtl); @@ -971,12 +972,12 @@ impl ShapeLine { // Adjust for tabs let mut x = 0.0; - for span in spans.iter_mut() { - for word in span.words.iter_mut() { - for glyph in word.glyphs.iter_mut() { + for span in &mut spans { + for word in &mut span.words { + for glyph in &mut word.glyphs { if line.get(glyph.start..glyph.end) == Some("\t") { // Tabs are shaped as spaces, so they will always have the x_advance of a space. - let tab_x_advance = (tab_width as f32) * glyph.x_advance; + let tab_x_advance = f32::from(tab_width) * glyph.x_advance; let tab_stop = (math::floorf(x / tab_x_advance) + 1.0) * tab_x_advance; glyph.x_advance = tab_stop - x; } @@ -987,7 +988,7 @@ impl ShapeLine { self.rtl = rtl; self.spans = spans; - self.metrics_opt = attrs_list.defaults().metrics_opt.map(|x| x.into()); + self.metrics_opt = attrs_list.defaults().metrics_opt.map(Into::into); // Return the buffer for later reuse. font_system.shape_buffer.spans = cached_spans; @@ -995,7 +996,7 @@ impl ShapeLine { // A modified version of first part of unicode_bidi::bidi_info::visual_run fn adjust_levels(para: &unicode_bidi::Paragraph) -> Vec { - use unicode_bidi::BidiClass::*; + use unicode_bidi::BidiClass::{B, BN, FSI, LRE, LRI, LRO, PDF, PDI, RLE, RLI, RLO, S, WS}; let text = para.info.text; let levels = ¶.info.levels; let original_classes = ¶.info.original_classes; @@ -1141,6 +1142,23 @@ impl ShapeLine { layout_lines: &mut Vec, match_mono_width: Option, ) { + fn add_to_visual_line( + vl: &mut VisualLine, + span_index: usize, + start: (usize, usize), + end: (usize, usize), + width: f32, + number_of_blanks: u32, + ) { + if end == start { + return; + } + + vl.ranges.push((span_index, start, end)); + vl.w += width; + vl.spaces += number_of_blanks; + } + // For each visual line a list of (span index, and range of words in that span) // Note that a BiDi visual line could have multiple spans or parts of them // let mut vl_range_of_spans = Vec::with_capacity(1); @@ -1160,23 +1178,6 @@ impl ShapeLine { v.glyphs })); - fn add_to_visual_line( - vl: &mut VisualLine, - span_index: usize, - start: (usize, usize), - end: (usize, usize), - width: f32, - number_of_blanks: u32, - ) { - if end == start { - return; - } - - vl.ranges.push((span_index, start, end)); - vl.w += width; - vl.spaces += number_of_blanks; - } - // This would keep the maximum number of spans that would fit on a visual line // If one span is too large, this variable will hold the range of words inside that span // that fits on a line. @@ -1187,7 +1188,7 @@ impl ShapeLine { for (span_index, span) in self.spans.iter().enumerate() { let mut word_range_width = 0.; let mut number_of_blanks: u32 = 0; - for word in span.words.iter() { + for word in &span.words { let word_width = word.width(font_size); word_range_width += word_width; if word.blank { @@ -1232,7 +1233,6 @@ impl ShapeLine { width_before_last_blank = word_range_width; } word_range_width += word_width; - continue; } else if wrap == Wrap::Glyph // Make sure that the word is able to fit on it's own line, if not, fall back to Glyph wrapping. || (wrap == Wrap::WordOrGlyph && word_width > width_opt.unwrap_or(f32::INFINITY)) @@ -1266,7 +1266,6 @@ impl ShapeLine { <= width_opt.unwrap_or(f32::INFINITY) { word_range_width += glyph_width; - continue; } else { add_to_visual_line( &mut current_visual_line, @@ -1358,7 +1357,6 @@ impl ShapeLine { width_before_last_blank = word_range_width; } word_range_width += word_width; - continue; } else if wrap == Wrap::Glyph // Make sure that the word is able to fit on it's own line, if not, fall back to Glyph wrapping. || (wrap == Wrap::WordOrGlyph && word_width > width_opt.unwrap_or(f32::INFINITY)) @@ -1392,7 +1390,6 @@ impl ShapeLine { <= width_opt.unwrap_or(f32::INFINITY) { word_range_width += glyph_width; - continue; } else { add_to_visual_line( &mut current_visual_line, @@ -1467,26 +1464,26 @@ impl ShapeLine { } } - if !current_visual_line.ranges.is_empty() { - visual_lines.push(current_visual_line); - } else { + if current_visual_line.ranges.is_empty() { current_visual_line.clear(); cached_visual_lines.push(current_visual_line); + } else { + visual_lines.push(current_visual_line); } // Create the LayoutLines using the ranges inside visual lines let align = align.unwrap_or(if self.rtl { Align::Right } else { Align::Left }); - let line_width = match width_opt { - Some(width) => width, - None => { + let line_width = width_opt.map_or_else( + || { let mut width: f32 = 0.0; - for visual_line in visual_lines.iter() { + for visual_line in &visual_lines { width = width.max(visual_line.w); } width - } - }; + }, + |width| width, + ); let start_x = if self.rtl { line_width } else { 0.0 }; @@ -1546,7 +1543,7 @@ impl ShapeLine { let mut process_range = |range: Range| { for &(span_index, (starting_word, starting_glyph), (ending_word, ending_glyph)) in - visual_line.ranges[range.clone()].iter() + &visual_line.ranges[range] { let span = &self.spans[span_index]; // If ending_glyph is not 0 we need to include glyphs from the ending_word @@ -1585,12 +1582,14 @@ impl ShapeLine { _ => font_size, }; - let x_advance = glyph_font_size * glyph.x_advance - + if word.blank { + let x_advance = glyph_font_size.mul_add( + glyph.x_advance, + if word.blank { justification_expansion } else { 0.0 - }; + }, + ); if self.rtl { x -= x_advance; } @@ -1626,12 +1625,12 @@ impl ShapeLine { } let mut line_height_opt: Option = None; - for glyph in glyphs.iter() { + for glyph in &glyphs { if let Some(glyph_line_height) = glyph.line_height_opt { - line_height_opt = match line_height_opt { - Some(line_height) => Some(line_height.max(glyph_line_height)), - None => Some(glyph_line_height), - }; + line_height_opt = line_height_opt + .map_or(Some(glyph_line_height), |line_height| { + Some(line_height.max(glyph_line_height)) + }); } } @@ -1657,7 +1656,7 @@ impl ShapeLine { max_ascent: 0.0, max_descent: 0.0, line_height_opt: self.metrics_opt.map(|x| x.line_height), - glyphs: Default::default(), + glyphs: Vec::default(), }); } diff --git a/src/swash.rs b/src/swash.rs index 657e109..62a5898 100644 --- a/src/swash.rs +++ b/src/swash.rs @@ -17,12 +17,9 @@ fn swash_image( context: &mut ScaleContext, cache_key: CacheKey, ) -> Option { - let font = match font_system.get_font(cache_key.font_id, cache_key.font_weight) { - Some(some) => some, - None => { - log::warn!("did not find font {:?}", cache_key.font_id); - return None; - } + let Some(font) = font_system.get_font(cache_key.font_id, cache_key.font_weight) else { + log::warn!("did not find font {:?}", cache_key.font_id); + return None; }; let variable_width = font @@ -38,7 +35,7 @@ fn swash_image( if let Some(variation) = variable_width { scaler = scaler.variations(std::iter::once(swash::Setting { tag: swash::Tag::from_be_bytes(*b"wght"), - value: (cache_key.font_weight.0 as f32) + value: f32::from(cache_key.font_weight.0) .clamp(variation.min_value(), variation.max_value()), })); } @@ -87,12 +84,9 @@ fn swash_outline_commands( ) -> Option> { use swash::zeno::PathData as _; - let font = match font_system.get_font(cache_key.font_id, cache_key.font_weight) { - Some(some) => some, - None => { - log::warn!("did not find font {:?}", cache_key.font_id); - return None; - } + let Some(font) = font_system.get_font(cache_key.font_id, cache_key.font_weight) else { + log::warn!("did not find font {:?}", cache_key.font_id); + return None; }; // Build the scaler @@ -206,7 +200,7 @@ impl SwashCache { f( x + off_x, y + off_y, - Color(((image.data[i] as u32) << 24) | base.0 & 0xFF_FF_FF), + Color((u32::from(image.data[i]) << 24) | base.0 & 0xFF_FF_FF), ); i += 1; }