Skip to content

Commit 579086c

Browse files
committed
Fixed several issues found in examples
The containers example has slowed down at some point. Some very basic benchmarking pointed to the font family list being applied being expensive. I attempted to reduce the overhead of this by making single element lists be allocation free. Unfortunately that wasn't enough, and this slowdown is almost certainly unrelated to this branch, so while I'm keeping the optimization, the example is still too slow. In the process of trying to get baseline working for the Grid widget, at one point I changed the "other" constraint to SizeToFit to prevent labels from growing. Ultimately, the label code itself was updated to account for this. By changing this back, many examples were working correctly again. Lastly, the selection rectangle for a single line of text wasn't including the descender... which then became more complex since that measurement isn't present if the text doesn't have any descenders. There's an approximation in place now, but I suspect we should measure a character with a descender to get the line metrics.
1 parent cfad657 commit 579086c

File tree

8 files changed

+73
-33
lines changed

8 files changed

+73
-33
lines changed

examples/7guis-counter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn main() -> cushy::Result {
99

1010
count
1111
.to_label()
12+
.centered()
1213
.expand()
1314
.and(
1415
"Count"

examples/buttons.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ fn main() -> cushy::Result {
1616

1717
clicked_label
1818
.clone()
19+
.centered()
1920
.and(
2021
"Normal Button"
2122
.into_button()

examples/fonts-dynamic.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ fn main() -> cushy::Result<()> {
2727
let font = loaded_font.get_tracking_invalidate(context)?;
2828

2929
let face = context.loaded_font_faces(&font).first()?;
30-
Some(Component::custom(FontFamilyList::from(vec![
31-
FamilyOwned::Name(face.families[0].0.clone()),
32-
])))
30+
Some(Component::custom(FontFamilyList::from(FamilyOwned::Name(
31+
face.families[0].0.clone(),
32+
))))
3333
}
3434
});
3535
let family_weight = DynamicComponent::new(move |context| {

examples/scroll-nested.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
use cushy::figures::units::Lp;
22
use cushy::kludgine::cosmic_text::FamilyOwned;
33
use cushy::styles::components::FontFamily;
4-
use cushy::styles::{Edges, FontFamilyList};
4+
use cushy::styles::Edges;
55
use cushy::widget::MakeWidget;
66
use cushy::Run;
77

88
fn main() -> cushy::Result {
99
include_str!("scroll-nested.rs")
1010
.vertical_scroll()
11-
.with(&FontFamily, FontFamilyList::from(FamilyOwned::Monospace))
11+
.with(&FontFamily, FamilyOwned::Monospace)
1212
.height(Lp::inches(3))
1313
.and(
1414
include_str!("./canvas.rs")
1515
.vertical_scroll()
16-
.with(&FontFamily, FontFamilyList::from(FamilyOwned::Monospace))
16+
.with(&FontFamily, FamilyOwned::Monospace)
1717
.height(Lp::inches(3)),
1818
)
1919
.into_rows()

src/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ impl<'clip, 'gfx, 'pass> GraphicsContext<'_, 'clip, 'gfx, 'pass> {
625625
self.font_state
626626
.current_font_family
627627
.clone()
628-
.unwrap_or_else(|| FontFamilyList::from(vec![FamilyOwned::new(self.gfx.font_family())]))
628+
.unwrap_or_else(|| FontFamilyList::from(FamilyOwned::new(self.gfx.font_family())))
629629
}
630630

631631
/// Returns the first font family in `list` that is currently in the font

src/styles.rs

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::ops::{
99
RangeToInclusive, Sub,
1010
};
1111
use std::sync::Arc;
12+
use std::{mem, slice};
1213

1314
use ahash::AHashMap;
1415
use figures::units::{Lp, Px, UPx};
@@ -2698,47 +2699,82 @@ impl From<ColorSource> for ColorScheme {
26982699
}
26992700
}
27002701

2701-
/// A list of font families.
27022702
#[derive(Clone, Debug, Eq, PartialEq)]
2703-
pub struct FontFamilyList(Arc<Vec<FamilyOwned>>);
2704-
2705-
impl Default for FontFamilyList {
2706-
fn default() -> Self {
2707-
static DEFAULT: Lazy<FontFamilyList> = Lazy::new(|| FontFamilyList::from(vec![]));
2708-
DEFAULT.clone()
2709-
}
2703+
enum FontFamilyListData {
2704+
Single(FamilyOwned),
2705+
Multiple(Arc<Vec<FamilyOwned>>),
27102706
}
27112707

2708+
/// A list of font families.
2709+
#[derive(Clone, Debug, Eq, PartialEq, Default)]
2710+
pub struct FontFamilyList(Option<FontFamilyListData>);
2711+
27122712
impl FontFamilyList {
27132713
/// Pushes `family` on the end of this list.
27142714
pub fn push(&mut self, family: FamilyOwned) {
2715-
Arc::make_mut(&mut self.0).push(family);
2715+
match &mut self.0 {
2716+
None => {
2717+
self.0 = Some(FontFamilyListData::Single(family));
2718+
}
2719+
Some(FontFamilyListData::Single(first_family)) => {
2720+
let first_family = mem::replace(first_family, FamilyOwned::Serif);
2721+
self.0 = Some(FontFamilyListData::Multiple(Arc::new(vec![
2722+
first_family,
2723+
family,
2724+
])));
2725+
}
2726+
Some(FontFamilyListData::Multiple(vec)) => {
2727+
Arc::make_mut(vec).push(family);
2728+
}
2729+
}
27162730
}
27172731
}
27182732

27192733
impl Deref for FontFamilyList {
27202734
type Target = [FamilyOwned];
27212735

27222736
fn deref(&self) -> &Self::Target {
2723-
&self.0
2737+
match &self.0 {
2738+
Some(FontFamilyListData::Single(family)) => slice::from_ref(family),
2739+
Some(FontFamilyListData::Multiple(vec)) => vec,
2740+
None => &[],
2741+
}
27242742
}
27252743
}
27262744

27272745
impl FromIterator<FamilyOwned> for FontFamilyList {
27282746
fn from_iter<T: IntoIterator<Item = FamilyOwned>>(iter: T) -> Self {
2729-
Self(Arc::new(iter.into_iter().collect()))
2747+
let mut iter = iter.into_iter();
2748+
match iter.size_hint().0 {
2749+
0 | 1 => match iter.next() {
2750+
Some(first) => match iter.next() {
2751+
Some(second) => {
2752+
let mut contents = vec![first, second];
2753+
contents.extend(iter);
2754+
Self(Some(FontFamilyListData::Multiple(Arc::new(contents))))
2755+
}
2756+
None => Self(Some(FontFamilyListData::Single(first))),
2757+
},
2758+
None => Self(None),
2759+
},
2760+
_ => Self(Some(FontFamilyListData::Multiple(Arc::new(iter.collect())))),
2761+
}
27302762
}
27312763
}
27322764

27332765
impl From<FamilyOwned> for FontFamilyList {
27342766
fn from(value: FamilyOwned) -> Self {
2735-
Self::from(vec![value])
2767+
Self(Some(FontFamilyListData::Single(value)))
27362768
}
27372769
}
27382770

27392771
impl From<Vec<FamilyOwned>> for FontFamilyList {
27402772
fn from(value: Vec<FamilyOwned>) -> Self {
2741-
Self(Arc::new(value))
2773+
match value.len() {
2774+
1 => Self(value.into_iter().next().map(FontFamilyListData::Single)),
2775+
0 => Self(None),
2776+
_ => Self(Some(FontFamilyListData::Multiple(Arc::new(value)))),
2777+
}
27422778
}
27432779
}
27442780

src/widgets/grid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ impl GridLayout {
634634
element,
635635
self.orientation.make_size(
636636
ConstraintLimit::Fill(self.layouts[index].size.into_upx(scale)),
637-
ConstraintLimit::SizeToFit(self.others[element]),
637+
ConstraintLimit::Fill(self.others[element]),
638638
),
639639
true,
640640
);

src/widgets/input.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,14 @@ where
10721072
});
10731073
}
10741074

1075+
// TODO: Approximating the descent is not great. We probably should
1076+
// measure a letter with a descender and use that size as a minimum.
1077+
let full_line_height = info.cache.measured.line_height
1078+
- info
1079+
.cache
1080+
.measured
1081+
.descent
1082+
.min((-info.cache.measured.line_height / 3).ceil());
10751083
if let Some(selection) = info.selection {
10761084
let (start, end) = if selection < info.cursor {
10771085
(selection, info.cursor)
@@ -1088,10 +1096,7 @@ where
10881096
let width = end_position.x - start_position.x;
10891097
context.gfx.draw_shape(
10901098
Shape::filled_rect(
1091-
Rect::new(
1092-
start_position,
1093-
Size::new(width, info.cache.measured.line_height),
1094-
),
1099+
Rect::new(start_position, Size::new(width, full_line_height)),
10951100
highlight,
10961101
)
10971102
.translate_by(padding),
@@ -1101,16 +1106,13 @@ where
11011106
let width = size.width.into_signed() - start_position.x;
11021107
context.gfx.draw_shape(
11031108
Shape::filled_rect(
1104-
Rect::new(
1105-
start_position,
1106-
Size::new(width, info.cache.measured.line_height),
1107-
),
1109+
Rect::new(start_position, Size::new(width, full_line_height)),
11081110
highlight,
11091111
)
11101112
.translate_by(padding),
11111113
);
11121114
// Fill region between
1113-
let bottom_of_first_line = start_position.y + info.cache.measured.line_height;
1115+
let bottom_of_first_line = start_position.y + full_line_height;
11141116
let distance_between = end_position.y - bottom_of_first_line;
11151117
if distance_between > 0 {
11161118
context.gfx.draw_shape(
@@ -1129,7 +1131,7 @@ where
11291131
Shape::filled_rect(
11301132
Rect::new(
11311133
Point::new(Px::ZERO, end_position.y),
1132-
Size::new(end_position.x + end_width, info.cache.measured.line_height),
1134+
Size::new(end_position.x + end_width, full_line_height),
11331135
),
11341136
highlight,
11351137
)
@@ -1144,7 +1146,7 @@ where
11441146
Shape::filled_rect(
11451147
Rect::new(
11461148
Point::new(location.x - cursor_width / 2, location.y),
1147-
Size::new(cursor_width, info.cache.measured.line_height),
1149+
Size::new(cursor_width, full_line_height),
11481150
),
11491151
highlight,
11501152
)
@@ -1189,7 +1191,7 @@ where
11891191

11901192
WidgetLayout {
11911193
size: available_space.fit_measured(measured_size),
1192-
baseline: Baseline::from(padding + info.cache.measured.ascent.into_unsigned()),
1194+
baseline: Baseline::from(padding + info.cache.measured.line_height.into_unsigned()),
11931195
}
11941196
}
11951197

0 commit comments

Comments
 (0)