Skip to content

Commit

Permalink
Make StyleProperty::FontStack more ergonomic. (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
xorgy authored Oct 10, 2024
1 parent d4dcf36 commit 17f4e9f
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 44 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This release has an [MSRV] of 1.75.
- An example with Vello on Winit which shows a basic text editor ([#106] by [@dfrg])
- `PlainEditor`, a basic action-based text editor based on Parley `Selection` and `Cursor` ([#126] by [@xorgy])
- Tree style builder ([#76] by [@nicoburns])
- Conversions for `FontFamily`, `FontStack`, and `StyleProperty` to make styling more ergonomic ([#129] by [@xorgy])

### Changed

Expand All @@ -35,6 +36,7 @@ This release has an [MSRV] of 1.75.
#### Parley

- Emoji clusters now get an Emoji family added by default ([#56] by [@dfrg])
- Style builders now accept `Into<StyleProperty<'a, B: Brush>>` so you can push a `GenericFamily` or `FontStack` directly. ([#129] by [@xorgy])

#### Fontique

Expand Down Expand Up @@ -78,6 +80,7 @@ This release has an [MSRV] of 1.70.
[#85]: https://github.com/linebender/parley/pull/85
[#106]: https://github.com/linebender/parley/pull/106
[#126]: https://github.com/linebender/parley/pull/126
[#129]: https://github.com/linebender/parley/pull/129

[Unreleased]: https://github.com/linebender/parley/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/linebender/parley/releases/tag/v0.1.0
17 changes: 7 additions & 10 deletions examples/swash_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ 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 @@ -47,10 +46,8 @@ fn main() {

// Setup some Parley text styles
let brush_style = StyleProperty::Brush(text_color);
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);
let font_stack = FontStack::from("system-ui");
let bold_style = StyleProperty::FontWeight(FontWeight::new(600.0));

let mut layout = if std::env::args().any(|arg| arg == "--tree") {
// TREE BUILDER
Expand Down Expand Up @@ -104,15 +101,15 @@ fn main() {
let mut builder = layout_cx.ranged_builder(&mut font_cx, &text, display_scale);

// Set default text colour styles (set foreground text color)
builder.push_default(&brush_style);
builder.push_default(brush_style);

// Set default font family
builder.push_default(&font_stack_style);
builder.push_default(&StyleProperty::LineHeight(1.3));
builder.push_default(&StyleProperty::FontSize(16.0));
builder.push_default(font_stack);
builder.push_default(StyleProperty::LineHeight(1.3));
builder.push_default(StyleProperty::FontSize(16.0));

// Set the first 4 characters to bold
builder.push(&bold_style, 0..4);
builder.push(bold_style, 0..4);

builder.push_inline_box(InlineBox {
id: 0,
Expand Down
32 changes: 15 additions & 17 deletions examples/tiny_skia_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@
//! 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};
use parley::{
Alignment, FontContext, FontWeight, GenericFamily, GlyphRun, InlineBox, Layout, LayoutContext,
PositionedLayoutItem, StyleProperty,
};
use peniko::Color as PenikoColor;
use skrifa::instance::{LocationRef, NormalizedCoord, Size};
use skrifa::outline::{DrawSettings, OutlinePen};
use skrifa::raw::FontRef as ReadFontsRef;
use skrifa::{GlyphId, MetadataProvider, OutlineGlyph};
use skrifa::{
instance::{LocationRef, NormalizedCoord, Size},
outline::{DrawSettings, OutlinePen},
raw::FontRef as ReadFontsRef,
GlyphId, MetadataProvider, OutlineGlyph,
};
use tiny_skia::{
Color as TinySkiaColor, FillRule, Paint, PathBuilder, Pixmap, PixmapMut, Rect, Transform,
};
Expand Down Expand Up @@ -52,19 +53,16 @@ fn main() {

// Set default text colour styles (set foreground text color)
let brush_style = StyleProperty::Brush(foreground_color);
builder.push_default(&brush_style);
builder.push_default(brush_style);

// Set default font family
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));
builder.push_default(&StyleProperty::FontSize(16.0));
builder.push_default(GenericFamily::SystemUi);
builder.push_default(StyleProperty::LineHeight(1.3));
builder.push_default(StyleProperty::FontSize(16.0));

// Set the first 4 characters to bold
let bold = FontWeight::new(600.0);
let bold_style = StyleProperty::FontWeight(bold);
builder.push(&bold_style, 0..4);
builder.push(StyleProperty::FontWeight(bold), 0..4);

builder.push_inline_box(InlineBox {
id: 0,
Expand Down
11 changes: 4 additions & 7 deletions examples/vello_editor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// 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 All @@ -17,7 +16,7 @@ use winit::window::Window;

// #[path = "text2.rs"]
mod text;
use parley::layout::editor::PlainEditorOp;
use parley::{GenericFamily, PlainEditorOp, StyleProperty};

// Simple struct to hold the state of the renderer
pub struct ActiveRenderState<'s> {
Expand Down Expand Up @@ -133,11 +132,9 @@ impl ApplicationHandler for SimpleVelloApp<'_> {
PlainEditorOp::SetScale(1.0),
PlainEditorOp::SetWidth(size.width as f32 - 2f32 * text::INSET),
PlainEditorOp::SetDefaultStyle(Arc::new([
parley::style::StyleProperty::FontSize(32.0),
parley::style::StyleProperty::LineHeight(1.2),
parley::style::StyleProperty::FontStack(parley::style::FontStack::Source(
Cow::Borrowed("system-ui"),
)),
StyleProperty::FontSize(32.0),
StyleProperty::LineHeight(1.2),
GenericFamily::SystemUi.into(),
])),
]);
}
Expand Down
12 changes: 8 additions & 4 deletions parley/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,23 @@ pub struct RangedBuilder<'a, B: Brush> {
}

impl<B: Brush> RangedBuilder<'_, B> {
pub fn push_default(&mut self, property: &StyleProperty<B>) {
pub fn push_default<'a>(&mut self, property: impl Into<StyleProperty<'a, B>>) {
let resolved = self
.lcx
.rcx
.resolve_property(self.fcx, property, self.scale);
.resolve_property(self.fcx, &property.into(), self.scale);
self.lcx.ranged_style_builder.push_default(resolved);
}

pub fn push(&mut self, property: &StyleProperty<B>, range: impl RangeBounds<usize>) {
pub fn push<'a>(
&mut self,
property: impl Into<StyleProperty<'a, B>>,
range: impl RangeBounds<usize>,
) {
let resolved = self
.lcx
.rcx
.resolve_property(self.fcx, property, self.scale);
.resolve_property(self.fcx, &property.into(), self.scale);
self.lcx.ranged_style_builder.push(resolved, range);
}

Expand Down
2 changes: 1 addition & 1 deletion parley/src/layout/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ where
fn update_layout(&mut self, font_cx: &mut FontContext, layout_cx: &mut LayoutContext<T>) {
let mut builder = layout_cx.ranged_builder(font_cx, &self.buffer, self.scale);
for prop in self.default_style.iter() {
builder.push_default(prop);
builder.push_default(prop.to_owned());
}
builder.build_into(&mut self.layout, &self.buffer);
self.layout.break_all_lines(Some(self.width));
Expand Down
10 changes: 5 additions & 5 deletions parley/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
//! - [`RangedBuilder`] and [`TreeBuilder`] which are builders for creating a [`Layout`].
//! - [`RangedBuilder`] allows styles to be specified as a flat `Vec` of spans
//! - [`TreeBuilder`] allows styles to be specified as a tree of spans
//!
//!
//! They are constructed using the [`ranged_builder`](LayoutContext::ranged_builder) and [`tree_builder`](LayoutContext::ranged_builder) methods on [`LayoutContext`].
//! - [`Layout`] which represents styled paragraph(s) of text and can perform shaping, line-breaking, bidi-reordering, and alignment of that text.
//!
//!
//! `Layout` supports re-linebreaking and re-aligning many times (in case the width at which wrapping should occur changes). But if the text content or
//! the styles applied to that content change then a new `Layout` must be created using a new `RangedBuilder` or `TreeBuilder`.
//!
Expand All @@ -38,11 +38,11 @@
//! let mut builder = layout_cx.ranged_builder(&mut font_cx, &TEXT, DISPLAY_SCALE);
//!
//! // Set default styles that apply to the entire layout
//! builder.push_default(&StyleProperty::LineHeight(1.3));
//! builder.push_default(&StyleProperty::FontSize(16.0));
//! builder.push_default(StyleProperty::LineHeight(1.3));
//! builder.push_default(StyleProperty::FontSize(16.0));
//!
//! // Set a style that applies to the first 4 characters
//! builder.push(&StyleProperty::FontWeight(FontWeight::new(600.0)), 0..4);
//! builder.push(StyleProperty::FontWeight(FontWeight::new(600.0)), 0..4);
//!
//! // Add a box to be laid out inline with the text
//! builder.push_inline_box(InlineBox { id: 0, index: 5, width: 50.0, height: 50.0 });
Expand Down
30 changes: 30 additions & 0 deletions parley/src/style/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,36 @@ impl<'a> FontFamily<'a> {
}
}

impl<'a> From<GenericFamily> for FontFamily<'a> {
fn from(f: GenericFamily) -> Self {
FontFamily::Generic(f)
}
}

impl<'a> From<GenericFamily> for FontStack<'a> {
fn from(f: GenericFamily) -> Self {
FontStack::Single(f.into())
}
}

impl<'a> From<FontFamily<'a>> for FontStack<'a> {
fn from(f: FontFamily<'a>) -> Self {
FontStack::Single(f)
}
}

impl<'a> From<&'a str> for FontStack<'a> {
fn from(s: &'a str) -> Self {
FontStack::Source(Cow::Borrowed(s))
}
}

impl<'a> From<&'a [FontFamily<'a>]> for FontStack<'a> {
fn from(fs: &'a [FontFamily<'a>]) -> Self {
FontStack::List(Cow::Borrowed(fs))
}
}

impl fmt::Display for FontFamily<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expand Down
24 changes: 24 additions & 0 deletions parley/src/style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,27 @@ impl<B: Brush> Default for TextStyle<'_, B> {
}
}
}

impl<'a, B: Brush> From<FontStack<'a>> for StyleProperty<'a, B> {
fn from(fs: FontStack<'a>) -> Self {
StyleProperty::FontStack(fs)
}
}

impl<'a, B: Brush> From<&'a [FontFamily<'a>]> for StyleProperty<'a, B> {
fn from(fs: &'a [FontFamily<'a>]) -> Self {
StyleProperty::FontStack(fs.into())
}
}

impl<'a, B: Brush> From<FontFamily<'a>> for StyleProperty<'a, B> {
fn from(f: FontFamily<'a>) -> Self {
StyleProperty::FontStack(FontStack::from(f))
}
}

impl<'a, B: Brush> From<GenericFamily> for StyleProperty<'a, B> {
fn from(f: GenericFamily) -> Self {
StyleProperty::FontStack(f.into())
}
}

0 comments on commit 17f4e9f

Please sign in to comment.