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
This commit is contained in:
romanstingler 2025-08-11 21:58:59 +02:00 committed by GitHub
parent e80dbc3607
commit a2f1f4b2a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 282 additions and 299 deletions

View file

@ -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 = [

View file

@ -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));

View file

@ -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(&paragraph[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(&paragraph[0..i]))
}
}

View file

@ -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<f32> {
pub const fn monospace_width(&self) -> Option<f32> {
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<f32>, Option<f32>) {
pub const fn size(&self) -> (Option<f32>, Option<f32>) {
(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,

View file

@ -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<Align> {
pub const fn align(&self) -> Option<Align> {
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<LayoutLine>> {
pub const fn layout_opt(&self) -> Option<&Vec<LayoutLine>> {
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<usize> {
pub const fn metadata(&self) -> Option<usize> {
self.metadata
}

View file

@ -11,7 +11,7 @@ pub enum Cached<T: Clone + Debug> {
impl<T: Clone + Debug> Cached<T> {
/// 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<T: Clone + Debug> Cached<T> {
}
/// 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<T: Clone + Debug> Cached<T> {
}
/// 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,

View file

@ -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 {

View file

@ -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);

View file

@ -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))

View file

@ -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::{

View file

@ -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<usize>,
forbidden_fallback_range: Range<usize>,
@ -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<u16>,
codepoint_non_matches: Option<usize>,
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| {

View file

@ -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] {
&[]
}

View file

@ -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] {
&[]
}

View file

@ -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

View file

@ -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()

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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<f32>,
@ -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<unicode_bidi::Level> {
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 = &para.info.levels;
let original_classes = &para.info.original_classes;
@ -1141,6 +1142,23 @@ impl ShapeLine {
layout_lines: &mut Vec<LayoutLine>,
match_mono_width: Option<f32>,
) {
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<usize>| {
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<f32> = 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(),
});
}

View file

@ -17,12 +17,9 @@ fn swash_image(
context: &mut ScaleContext,
cache_key: CacheKey,
) -> Option<SwashImage> {
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<Box<[swash::zeno::Command]>> {
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;
}