Skip to content
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
10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ This release has an [MSRV] of 1.82.

### Fixed

#### Fontique

- Font family name aliases (secondary names for font families, often in another language) not being registered. ([#380][] by [@valadaptive][])

#### Parley

- Selection extension moves the focus to the side being extended. ([#385][] by [@kekelp][])
- Ranged builder default style not respecting `scale`. ([#368][] by [@xStrom][])

#### Fontique

- Font family name aliases (secondary names for font families, often in another language) not being registered. ([#380][] by [@valadaptive][])

## [0.5.0] - 2025-06-01

Expand Down Expand Up @@ -308,6 +309,7 @@ This release has an [MSRV][] of 1.70.
[#348]: https://github.com/linebender/parley/pull/348
[#353]: https://github.com/linebender/parley/pull/353
[#362]: https://github.com/linebender/parley/pull/362
[#368]: https://github.com/linebender/parley/pull/368
[#369]: https://github.com/linebender/parley/pull/369
[#378]: https://github.com/linebender/parley/pull/378
[#380]: https://github.com/linebender/parley/pull/380
Expand Down
2 changes: 1 addition & 1 deletion examples/swash_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ fn main() {
let (layout, _text): (Layout<ColorBrush>, String) = builder.build();
layout
} else {
// RANGE BUILDER
// RANGED BUILDER
// ============

// Creates a RangedBuilder
Expand Down
9 changes: 6 additions & 3 deletions parley/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ impl<B: Brush> LayoutContext<B> {
quantize: bool,
) -> RangedBuilder<'a, B> {
self.begin();
self.ranged_style_builder.begin(text.len());

let resolved_root_style = self.resolve_style_set(fcx, scale, &TextStyle::default());
self.ranged_style_builder
.begin(resolved_root_style, text.len());

fcx.source_cache.prune(128, false);

Expand Down Expand Up @@ -123,11 +126,11 @@ impl<B: Brush> LayoutContext<B> {
fcx: &'a mut FontContext,
scale: f32,
quantize: bool,
raw_style: &TextStyle<'_, B>,
root_style: &TextStyle<'_, B>,
) -> TreeBuilder<'a, B> {
self.begin();

let resolved_root_style = self.resolve_style_set(fcx, scale, raw_style);
let resolved_root_style = self.resolve_style_set(fcx, scale, root_style);
self.tree_style_builder.begin(resolved_root_style);

fcx.source_cache.prune(128, false);
Expand Down
5 changes: 3 additions & 2 deletions parley/src/layout/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{
Affinity, Alignment, AlignmentOptions, Layout,
cursor::{Cursor, Selection},
},
resolve::ResolvedStyle,
style::Brush,
};
use alloc::{borrow::ToOwned, string::String, vec::Vec};
Expand Down Expand Up @@ -114,6 +113,7 @@ where
/// Whether the cursor should be shown. The IME can request to hide the cursor.
show_cursor: bool,
width: Option<f32>,
font_size: f32,
scale: f32,
quantize: bool,
// Simple tracking of when the layout needs to be updated
Expand Down Expand Up @@ -146,6 +146,7 @@ where
compose: None,
show_cursor: true,
width: None,
font_size,
scale: 1.0,
quantize: true,
layout_dirty: true,
Expand Down Expand Up @@ -925,7 +926,7 @@ where
let font_size = downstream
.or(upstream)
.map(|cluster| cluster.run().font_size())
.unwrap_or(ResolvedStyle::<T>::default().font_size);
.unwrap_or(self.font_size * self.scale);
// Using 0.6 as an estimate of the average advance
let inflate = 3. * 0.6 * font_size as f64;
let editor_width = self.width.map(f64::from).unwrap_or(f64::INFINITY);
Expand Down
25 changes: 1 addition & 24 deletions parley/src/resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ pub(crate) enum ResolvedProperty<B: Brush> {
}

/// Flattened group of style properties.
#[derive(Clone, PartialEq, Debug)]
#[derive(Clone, PartialEq, Debug, Default)]
pub(crate) struct ResolvedStyle<B: Brush> {
/// Font stack.
pub(crate) font_stack: Resolved<FamilyId>,
Expand Down Expand Up @@ -413,29 +413,6 @@ pub(crate) struct ResolvedStyle<B: Brush> {
pub(crate) overflow_wrap: OverflowWrap,
}

impl<B: Brush> Default for ResolvedStyle<B> {
fn default() -> Self {
Self {
font_stack: Resolved::default(),
font_size: 16.,
font_width: Default::default(),
font_style: Default::default(),
font_weight: Default::default(),
font_variations: Default::default(),
font_features: Default::default(),
locale: None,
brush: Default::default(),
underline: Default::default(),
strikethrough: Default::default(),
line_height: Default::default(),
word_spacing: 0.,
letter_spacing: 0.,
word_break: Default::default(),
overflow_wrap: Default::default(),
}
}
}

impl<B: Brush> ResolvedStyle<B> {
/// Applies the specified property to this style.
pub(crate) fn apply(&mut self, property: ResolvedProperty<B>) {
Expand Down
27 changes: 14 additions & 13 deletions parley/src/resolve/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,51 +13,52 @@ use core::ops::{Bound, Range, RangeBounds};
#[derive(Clone)]
pub(crate) struct RangedStyleBuilder<B: Brush> {
properties: Vec<RangedProperty<B>>,
default_style: ResolvedStyle<B>,
root_style: ResolvedStyle<B>,
len: usize,
}

impl<B: Brush> Default for RangedStyleBuilder<B> {
fn default() -> Self {
Self {
properties: vec![],
default_style: Default::default(),
root_style: ResolvedStyle::default(),
len: !0,
}
}
}

impl<B: Brush> RangedStyleBuilder<B> {
/// Prepares the builder for accepting ranged properties for text of the
/// specified length.
pub(crate) fn begin(&mut self, len: usize) {
/// Prepares the builder for accepting ranged properties for text of the specified length.
///
/// The provided `root_style` is the default style applied to all text unless overridden.
pub(crate) fn begin(&mut self, root_style: ResolvedStyle<B>, len: usize) {
self.properties.clear();
self.default_style = ResolvedStyle::default();
self.root_style = root_style;
self.len = len;
}

/// Pushes a property that covers the full range of text.
/// Change a property of the root style, which covers the full range of text.
pub(crate) fn push_default(&mut self, property: ResolvedProperty<B>) {
assert!(self.len != !0);
self.default_style.apply(property);
self.root_style.apply(property);
}

/// Pushes a property that covers the specified range of text.
/// Override a property for the specified range of text.
pub(crate) fn push(&mut self, property: ResolvedProperty<B>, range: impl RangeBounds<usize>) {
let range = resolve_range(range, self.len);
assert!(self.len != !0);
let range = resolve_range(range, self.len);
self.properties.push(RangedProperty { property, range });
}

/// Computes the sequence of ranged styles.
pub(crate) fn finish(&mut self, styles: &mut Vec<RangedStyle<B>>) {
if self.len == !0 {
self.properties.clear();
self.default_style = ResolvedStyle::default();
self.root_style = ResolvedStyle::default();
return;
}
styles.push(RangedStyle {
style: self.default_style.clone(),
style: self.root_style.clone(),
range: 0..self.len,
});
for prop in &self.properties {
Expand Down Expand Up @@ -125,7 +126,7 @@ impl<B: Brush> RangedStyleBuilder<B> {
styles.truncate(styles.len() - merged_count);

self.properties.clear();
self.default_style = ResolvedStyle::default();
self.root_style = ResolvedStyle::default();
self.len = !0;
}
}
Expand Down
4 changes: 3 additions & 1 deletion parley/src/resolve/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ impl<B: Brush> Default for TreeStyleBuilder<B> {
}

impl<B: Brush> TreeStyleBuilder<B> {
/// Prepares the builder for accepting a style tree for text of the specified length.
/// Prepares the builder for accepting a tree of styles and text.
///
/// The provided `root_style` is the default style applied to all text unless overridden.
pub(crate) fn begin(&mut self, root_style: ResolvedStyle<B>) {
self.tree.clear();
self.flatted_styles.clear();
Expand Down
30 changes: 30 additions & 0 deletions parley/src/tests/test_builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,36 @@ fn set_root_style(rb: &mut RangedBuilder<'_, ColorBrush>) {
rb.push_default(StyleProperty::OverflowWrap(OverflowWrap::Anywhere));
}

/// Test that all the builders have the same default behavior.
#[test]
fn builders_default() {
let text = "Builders often wear hard hats for safety while working on construction sites.";
let scale = 2.;
let quantize = false;
let max_advance = Some(50.);
let root_style = TextStyle {
font_stack: FontStack::from(FONT_STACK),
..TextStyle::default()
};

let with_ranged_builder = |rb: &mut RangedBuilder<'_, ColorBrush>| {
rb.push_default(FontStack::from(FONT_STACK));
};
let with_tree_builder = |tb: &mut TreeBuilder<'_, ColorBrush>| {
tb.push_text(text);
};

assert_builders_produce_same_result(
text,
scale,
quantize,
max_advance,
&root_style,
with_ranged_builder,
with_tree_builder,
);
}

/// Test that all the builders behave the same when given the same root style.
#[test]
fn builders_root_only() {
Expand Down
Loading