diff --git a/examples/swash_render/src/main.rs b/examples/swash_render/src/main.rs index c5a11045..c95e6bf6 100644 --- a/examples/swash_render/src/main.rs +++ b/examples/swash_render/src/main.rs @@ -10,6 +10,7 @@ use parley::layout::{Alignment, Glyph, GlyphRun, Layout, PositionedLayoutItem}; use parley::style::{FontStack, FontWeight, StyleProperty, TextStyle}; use parley::{FontContext, InlineBox, LayoutContext}; use peniko::Color; +use std::borrow::Cow; use std::fs::File; use swash::scale::image::Content; use swash::scale::{Render, ScaleContext, Scaler, Source, StrikeWith}; @@ -46,8 +47,8 @@ fn main() { // Setup some Parley text styles let brush_style = StyleProperty::Brush(text_color); - let font_stack = FontStack::Source("system-ui"); - let font_stack_style: StyleProperty = StyleProperty::FontStack(font_stack); + let font_stack = FontStack::Source(Cow::Borrowed("system-ui")); + let font_stack_style: StyleProperty = StyleProperty::FontStack(font_stack.clone()); let bold = FontWeight::new(600.0); let bold_style = StyleProperty::FontWeight(bold); diff --git a/examples/tiny_skia_render/src/main.rs b/examples/tiny_skia_render/src/main.rs index 7f322055..a1690ec4 100644 --- a/examples/tiny_skia_render/src/main.rs +++ b/examples/tiny_skia_render/src/main.rs @@ -7,6 +7,8 @@ //! Note: Emoji rendering is not currently implemented in this example. See the swash example //! if you need emoji rendering. +use std::borrow::Cow; + use parley::layout::{Alignment, GlyphRun, Layout, PositionedLayoutItem}; use parley::style::{FontStack, FontWeight, StyleProperty}; use parley::{FontContext, InlineBox, LayoutContext}; @@ -53,7 +55,7 @@ fn main() { builder.push_default(&brush_style); // Set default font family - let font_stack = FontStack::Source("system-ui"); + let font_stack = FontStack::Source(Cow::Borrowed("system-ui")); let font_stack_style = StyleProperty::FontStack(font_stack); builder.push_default(&font_stack_style); builder.push_default(&StyleProperty::LineHeight(1.3)); diff --git a/examples/vello_editor/src/main.rs b/examples/vello_editor/src/main.rs index 66e0451a..eb17b3c6 100644 --- a/examples/vello_editor/src/main.rs +++ b/examples/vello_editor/src/main.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use anyhow::Result; +use std::borrow::Cow; use std::num::NonZeroUsize; use std::sync::Arc; use vello::peniko::Color; @@ -135,7 +136,7 @@ impl ApplicationHandler for SimpleVelloApp<'_> { parley::style::StyleProperty::FontSize(32.0), parley::style::StyleProperty::LineHeight(1.2), parley::style::StyleProperty::FontStack(parley::style::FontStack::Source( - "system-ui", + Cow::Borrowed("system-ui"), )), ])), ]); diff --git a/parley/src/resolve/mod.rs b/parley/src/resolve/mod.rs index 16af7fb9..055b21c5 100644 --- a/parley/src/resolve/mod.rs +++ b/parley/src/resolve/mod.rs @@ -19,6 +19,7 @@ use crate::font::FontContext; use crate::layout; use crate::style::TextStyle; use crate::util::nearly_eq; +use core::borrow::Borrow; use core::ops::Range; use fontique::FamilyId; use swash::text::Language; @@ -134,13 +135,13 @@ impl ResolveContext { ) -> ResolvedProperty { use ResolvedProperty::*; match property { - StyleProperty::FontStack(value) => FontStack(self.resolve_stack(fcx, *value)), + StyleProperty::FontStack(value) => FontStack(self.resolve_stack(fcx, value)), StyleProperty::FontSize(value) => FontSize(*value * scale), StyleProperty::FontStretch(value) => FontStretch(*value), StyleProperty::FontStyle(value) => FontStyle(*value), StyleProperty::FontWeight(value) => FontWeight(*value), - StyleProperty::FontVariations(value) => FontVariations(self.resolve_variations(*value)), - StyleProperty::FontFeatures(value) => FontFeatures(self.resolve_features(*value)), + StyleProperty::FontVariations(value) => FontVariations(self.resolve_variations(value)), + StyleProperty::FontFeatures(value) => FontFeatures(self.resolve_features(value)), StyleProperty::Locale(value) => Locale(value.map(Language::parse).flatten()), StyleProperty::Brush(value) => Brush(value.clone()), StyleProperty::Underline(value) => Underline(*value), @@ -166,13 +167,13 @@ impl ResolveContext { scale: f32, ) -> ResolvedStyle { ResolvedStyle { - font_stack: self.resolve_stack(fcx, raw_style.font_stack), + font_stack: self.resolve_stack(fcx, &raw_style.font_stack), font_size: raw_style.font_size * scale, font_stretch: raw_style.font_stretch, font_style: raw_style.font_style, font_weight: raw_style.font_weight, - font_variations: self.resolve_variations(raw_style.font_variations), - font_features: self.resolve_features(raw_style.font_features), + font_variations: self.resolve_variations(&raw_style.font_variations), + font_features: self.resolve_features(&raw_style.font_features), locale: raw_style.locale.and_then(Language::parse), brush: raw_style.brush.clone(), underline: ResolvedDecoration { @@ -194,14 +195,18 @@ impl ResolveContext { } /// Resolves a font stack. - pub fn resolve_stack(&mut self, fcx: &mut FontContext, stack: FontStack) -> Resolved { + pub fn resolve_stack( + &mut self, + fcx: &mut FontContext, + stack: &FontStack, + ) -> Resolved { self.tmp_families.clear(); match stack { FontStack::Source(source) => { for family in FontFamily::parse_list(source) { match family { FontFamily::Named(name) => { - if let Some(family) = fcx.collection.family_by_name(name) { + if let Some(family) = fcx.collection.family_by_name(&name) { self.tmp_families.push(family.id()); } } @@ -220,10 +225,11 @@ impl ResolveContext { } FontFamily::Generic(family) => { self.tmp_families - .extend(fcx.collection.generic_families(family)); + .extend(fcx.collection.generic_families(*family)); } }, FontStack::List(families) => { + let families: &[FontFamily<'_>] = families.borrow(); for family in families { match family { FontFamily::Named(name) => { @@ -247,7 +253,7 @@ impl ResolveContext { /// Resolves font variation settings. pub fn resolve_variations( &mut self, - variations: FontSettings, + variations: &FontSettings, ) -> Resolved> { match variations { FontSettings::Source(source) => { @@ -272,7 +278,7 @@ impl ResolveContext { /// Resolves font feature settings. pub fn resolve_features( &mut self, - features: FontSettings, + features: &FontSettings, ) -> Resolved> { match features { FontSettings::Source(source) => { diff --git a/parley/src/style/font.rs b/parley/src/style/font.rs index c84cced9..990b9e38 100644 --- a/parley/src/style/font.rs +++ b/parley/src/style/font.rs @@ -1,6 +1,8 @@ // Copyright 2021 the Parley Authors // SPDX-License-Identifier: Apache-2.0 OR MIT +use alloc::borrow::Cow; +use alloc::borrow::ToOwned; use core::fmt; pub use fontique::{ @@ -16,23 +18,23 @@ pub type FontFeature = swash::Setting; /// Prioritized sequence of font families. /// /// -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] pub enum FontStack<'a> { /// Font family list in CSS format. - Source(&'a str), + Source(Cow<'a, str>), /// Single font family. Single(FontFamily<'a>), /// Ordered list of font families. - List(&'a [FontFamily<'a>]), + List(Cow<'a, [FontFamily<'a>]>), } /// Named or generic font family. /// /// -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] pub enum FontFamily<'a> { /// Named font family. - Named(&'a str), + Named(Cow<'a, str>), /// Generic font family. Generic(GenericFamily), } @@ -125,20 +127,20 @@ impl<'a> Iterator for ParseList<'a> { while pos < self.len { if self.source[pos] == quote { self.pos = pos + 1; - return Some(FontFamily::Named( + return Some(FontFamily::Named(Cow::Borrowed( core::str::from_utf8(self.source.get(start..pos)?) .ok()? .trim(), - )); + ))); } pos += 1; } self.pos = pos; - return Some(FontFamily::Named( + return Some(FontFamily::Named(Cow::Borrowed( core::str::from_utf8(self.source.get(start..pos)?) .ok()? .trim(), - )); + ))); } let mut end = start; while pos < self.len { @@ -155,29 +157,41 @@ impl<'a> Iterator for ParseList<'a> { .trim(); Some(match GenericFamily::parse(name) { Some(family) => FontFamily::Generic(family), - _ => FontFamily::Named(name), + _ => FontFamily::Named(Cow::Borrowed(name)), }) } } /// Font settings that can be supplied as a raw source string or /// a parsed slice. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum FontSettings<'a, T> { +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum FontSettings<'a, T> +where + [T]: ToOwned, + <[T] as ToOwned>::Owned: fmt::Debug + Eq + Clone, +{ /// Setting source in CSS format. - Source(&'a str), + Source(Cow<'a, str>), /// List of settings. - List(&'a [T]), + List(Cow<'a, [T]>), } -impl<'a, T> From<&'a str> for FontSettings<'a, T> { +impl<'a, T> From<&'a str> for FontSettings<'a, T> +where + [T]: ToOwned, + <[T] as ToOwned>::Owned: fmt::Debug + Eq + Clone, +{ fn from(value: &'a str) -> Self { - Self::Source(value) + Self::Source(Cow::Borrowed(value)) } } -impl<'a, T> From<&'a [T]> for FontSettings<'a, T> { +impl<'a, T> From<&'a [T]> for FontSettings<'a, T> +where + [T]: ToOwned, + <[T] as ToOwned>::Owned: fmt::Debug + Eq + Clone, +{ fn from(value: &'a [T]) -> Self { - Self::List(value) + Self::List(Cow::Borrowed(value)) } } diff --git a/parley/src/style/mod.rs b/parley/src/style/mod.rs index f4289020..6efc1cb0 100644 --- a/parley/src/style/mod.rs +++ b/parley/src/style/mod.rs @@ -6,6 +6,8 @@ mod brush; mod font; +use alloc::borrow::Cow; + pub use brush::*; pub use font::{ FontFamily, FontFeature, FontSettings, FontStack, FontStretch, FontStyle, FontVariation, @@ -111,13 +113,13 @@ pub struct TextStyle<'a, B: Brush> { impl Default for TextStyle<'_, B> { fn default() -> Self { TextStyle { - font_stack: FontStack::Source("sans-serif"), + font_stack: FontStack::Source(Cow::Borrowed("sans-serif")), font_size: 16.0, font_stretch: Default::default(), font_style: Default::default(), font_weight: Default::default(), - font_variations: FontSettings::List(&[]), - font_features: FontSettings::List(&[]), + font_variations: FontSettings::List(Cow::Borrowed(&[])), + font_features: FontSettings::List(Cow::Borrowed(&[])), locale: Default::default(), brush: Default::default(), has_underline: Default::default(),