slint/internal/compiler/passes/apply_default_properties_from_style.rs
Milian Wolff f6da161dbb
Reduce SmolStr <-> &str conversions and copies (#6688)
SmolStr has an Arc internally for large strings. This allows
cheap copies of large strings, but we lose that ability
when we convert the SmolStr to a &str and then reconstruct a
SmolStr from that slice.

I was hoping for some larger gains here, considering the impact
of this code change, but it only removes ~50k allocations,
while the impact on the runtime is not noticeable at all.

Still, I believe this is the right thing to do.

Before:
```
        allocations:            2338981

  Time (mean ± σ):     988.3 ms ±  17.9 ms    [User: 690.2 ms, System: 206.4 ms]
  Range (min … max):   956.4 ms … 1016.3 ms    10 runs
```

After:
```
        allocations:            2287723

  Time (mean ± σ):     989.8 ms ±  23.2 ms    [User: 699.2 ms, System: 197.6 ms]
  Range (min … max):   945.3 ms … 1021.4 ms    10 runs
```
2024-11-19 10:07:16 +01:00

113 lines
4.9 KiB
Rust

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
//! Passe that apply the default property from the style.
//!
//! Note that the layout default property are handled in the lower_layout pass
use crate::diagnostics::BuildDiagnostics;
use crate::expression_tree::{Expression, NamedReference};
use crate::langtype::Type;
use crate::object_tree::Component;
use smol_str::SmolStr;
use std::rc::Rc;
/// Ideally we would be able to write this in builtin.slint, but the StyleMetrics is not available there
pub fn apply_default_properties_from_style(
root_component: &Rc<Component>,
style_metrics: &Rc<Component>,
palette: &Rc<Component>,
_diag: &mut BuildDiagnostics,
) {
crate::object_tree::recurse_elem_including_sub_components(
root_component,
&(),
&mut |elem, _| {
let mut elem = elem.borrow_mut();
match elem.builtin_type().as_ref().map_or("", |b| b.name.as_str()) {
"TextInput" => {
elem.set_binding_if_not_set("text-cursor-width".into(), || {
Expression::PropertyReference(NamedReference::new(
&style_metrics.root_element,
SmolStr::new_static("text-cursor-width"),
))
});
elem.set_binding_if_not_set("color".into(), || {
Expression::PropertyReference(NamedReference::new(
&palette.root_element,
SmolStr::new_static("foreground"),
))
.into()
});
elem.set_binding_if_not_set("selection-background-color".into(), || {
Expression::Cast {
from: Expression::PropertyReference(NamedReference::new(
&palette.root_element,
SmolStr::new_static("selection-background"),
))
.into(),
to: Type::Color,
}
});
elem.set_binding_if_not_set("selection-foreground-color".into(), || {
Expression::Cast {
from: Expression::PropertyReference(NamedReference::new(
&palette.root_element,
SmolStr::new_static("selection-foreground"),
))
.into(),
to: Type::Color,
}
});
}
"Text" => {
elem.set_binding_if_not_set("color".into(), || Expression::Cast {
from: Expression::PropertyReference(NamedReference::new(
&palette.root_element,
SmolStr::new_static("foreground"),
))
.into(),
to: Type::Brush,
});
}
"Dialog" | "Window" => {
elem.set_binding_if_not_set("background".into(), || Expression::Cast {
from: Expression::PropertyReference(NamedReference::new(
&palette.root_element,
SmolStr::new_static("background"),
))
.into(),
to: Type::Brush,
});
let mut bind_style_property_if_exists = |property_name, property_type| {
if !matches!(
style_metrics
.root_element
.borrow()
.lookup_property(property_name)
.property_type,
Type::Invalid,
) {
elem.set_binding_if_not_set(property_name.into(), || {
Expression::Cast {
from: Expression::PropertyReference(NamedReference::new(
&style_metrics.root_element,
SmolStr::new_static(property_name),
))
.into(),
to: property_type,
}
});
}
};
bind_style_property_if_exists("default-font-size", Type::LogicalLength);
bind_style_property_if_exists("default-font-family", Type::String);
}
_ => {}
}
},
)
}