Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CoWify style types #128

Merged
merged 2 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions examples/swash_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<Color> = StyleProperty::FontStack(font_stack);
let font_stack = FontStack::Source(Cow::Borrowed("system-ui"));
let font_stack_style: StyleProperty<Color> = StyleProperty::FontStack(font_stack.clone());
let bold = FontWeight::new(600.0);
let bold_style = StyleProperty::FontWeight(bold);

Expand Down
4 changes: 3 additions & 1 deletion examples/tiny_skia_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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));
Expand Down
5 changes: 3 additions & 2 deletions examples/vello_editor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -48,7 +49,7 @@ struct SimpleVelloApp<'s> {
scene: Scene,

// Our text state object
editor: text::Editor<'s>,
editor: text::Editor,
}

impl ApplicationHandler for SimpleVelloApp<'_> {
Expand Down Expand Up @@ -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"),
)),
xorgy marked this conversation as resolved.
Show resolved Hide resolved
])),
]);
Expand Down
8 changes: 4 additions & 4 deletions examples/vello_editor/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ use parley::{FontContext, LayoutContext, PlainEditor, PlainEditorOp};
pub const INSET: f32 = 32.0;

#[derive(Default)]
pub struct Editor<'a> {
pub struct Editor {
font_cx: FontContext,
layout_cx: LayoutContext<Color>,
editor: PlainEditor<'a, Color>,
editor: PlainEditor<Color>,
last_click_time: Option<Instant>,
click_count: u32,
pointer_down: bool,
cursor_pos: (f32, f32),
modifiers: Option<Modifiers>,
}

impl<'a> Editor<'a> {
pub fn transact(&mut self, t: impl IntoIterator<Item = PlainEditorOp<'a, Color>>) {
impl Editor {
pub fn transact(&mut self, t: impl IntoIterator<Item = PlainEditorOp<Color>>) {
self.editor
.transact(&mut self.font_cx, &mut self.layout_cx, t);
}
Expand Down
14 changes: 7 additions & 7 deletions parley/src/layout/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ pub enum ActiveText<'a> {
}

/// Basic plain text editor with a single default style.
pub struct PlainEditor<'a, T>
pub struct PlainEditor<T>
where
T: Brush + Clone + Debug + PartialEq + Default,
{
default_style: Arc<[StyleProperty<'a, T>]>,
default_style: Arc<[StyleProperty<'static, T>]>,
buffer: String,
layout: Layout<T>,
selection: Selection,
Expand All @@ -36,7 +36,7 @@ where
}

// TODO: When MSRV >= 1.80 we can remove this. Default was not implemented for Arc<[T]> where T: !Default until 1.80
impl<'a, T> Default for PlainEditor<'a, T>
impl<T> Default for PlainEditor<T>
where
T: Brush + Clone + Debug + PartialEq + Default,
{
Expand All @@ -55,7 +55,7 @@ where

/// Operations on a `PlainEditor` for `PlainEditor::transact`
#[non_exhaustive]
pub enum PlainEditorOp<'a, T>
pub enum PlainEditorOp<T>
where
T: Brush + Clone + Debug + PartialEq + Default,
{
Expand All @@ -66,7 +66,7 @@ where
/// Set the scale for the layout
SetScale(f32),
/// Set the default style for the layout
SetDefaultStyle(Arc<[StyleProperty<'a, T>]>),
SetDefaultStyle(Arc<[StyleProperty<'static, T>]>),
/// Insert at cursor, or replace selection
InsertOrReplaceSelection(Arc<str>),
/// Delete the selection
Expand Down Expand Up @@ -133,7 +133,7 @@ where
ExtendSelectionToPoint(f32, f32),
}

impl<'a, T> PlainEditor<'a, T>
impl<T> PlainEditor<T>
where
T: Brush + Clone + Debug + PartialEq + Default,
{
Expand All @@ -142,7 +142,7 @@ where
&mut self,
font_cx: &mut FontContext,
layout_cx: &mut LayoutContext<T>,
t: impl IntoIterator<Item = PlainEditorOp<'a, T>>,
t: impl IntoIterator<Item = PlainEditorOp<T>>,
) {
let mut layout_after = false;

Expand Down
28 changes: 17 additions & 11 deletions parley/src/resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -134,13 +135,13 @@ impl ResolveContext {
) -> ResolvedProperty<B> {
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),
Expand All @@ -166,13 +167,13 @@ impl ResolveContext {
scale: f32,
) -> ResolvedStyle<B> {
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 {
Expand All @@ -194,14 +195,18 @@ impl ResolveContext {
}

/// Resolves a font stack.
pub fn resolve_stack(&mut self, fcx: &mut FontContext, stack: FontStack) -> Resolved<FamilyId> {
pub fn resolve_stack(
&mut self,
fcx: &mut FontContext,
stack: &FontStack,
) -> Resolved<FamilyId> {
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());
}
}
Expand All @@ -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) => {
Expand All @@ -247,7 +253,7 @@ impl ResolveContext {
/// Resolves font variation settings.
pub fn resolve_variations(
&mut self,
variations: FontSettings<FontVariation>,
variations: &FontSettings<FontVariation>,
) -> Resolved<Setting<f32>> {
match variations {
FontSettings::Source(source) => {
Expand All @@ -272,7 +278,7 @@ impl ResolveContext {
/// Resolves font feature settings.
pub fn resolve_features(
&mut self,
features: FontSettings<FontFeature>,
features: &FontSettings<FontFeature>,
) -> Resolved<Setting<u16>> {
match features {
FontSettings::Source(source) => {
Expand Down
58 changes: 37 additions & 21 deletions parley/src/style/font.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand All @@ -16,23 +18,23 @@ pub type FontFeature = swash::Setting<u16>;
/// Prioritized sequence of font families.
///
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/font-family>
#[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.
///
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/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),
}
Expand All @@ -44,13 +46,14 @@ impl<'a> FontFamily<'a> {
/// ```
/// use parley::style::FontFamily::{self, *};
/// use parley::style::GenericFamily::*;
/// use std::borrow::Cow;
///
/// assert_eq!(FontFamily::parse("Palatino Linotype"), Some(Named("Palatino Linotype")));
/// assert_eq!(FontFamily::parse("Palatino Linotype"), Some(Named(Cow::Borrowed("Palatino Linotype"))));
/// assert_eq!(FontFamily::parse("monospace"), Some(Generic(Monospace)));
///
/// // Note that you can quote a generic family to capture it as a named family:
///
/// assert_eq!(FontFamily::parse("'monospace'"), Some(Named("monospace")));
/// assert_eq!(FontFamily::parse("'monospace'"), Some(Named(Cow::Borrowed("monospace"))));
/// ```
pub fn parse(s: &'a str) -> Option<Self> {
Self::parse_list(s).next()
Expand All @@ -62,11 +65,12 @@ impl<'a> FontFamily<'a> {
/// ```
/// use parley::style::FontFamily::{self, *};
/// use parley::style::GenericFamily::*;
/// use std::borrow::Cow;
///
/// let source = "Arial, 'Times New Roman', serif";
///
/// let parsed_families = FontFamily::parse_list(source).collect::<Vec<_>>();
/// let families = vec![Named("Arial"), Named("Times New Roman"), Generic(Serif)];
/// let families = vec![Named(Cow::Borrowed("Arial")), Named(Cow::Borrowed("Times New Roman")), Generic(Serif)];
///
/// assert_eq!(parsed_families, families);
/// ```
Expand Down Expand Up @@ -125,20 +129,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 {
Expand All @@ -155,29 +159,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))
}
}
Loading