Skip to content

Commit dbf9b2b

Browse files
committed
More optimization when the scale factor is constant
When compiled with a const scale factor, we don't want to register too many dependencies to the scale factor.
1 parent a235369 commit dbf9b2b

File tree

17 files changed

+106
-50
lines changed

17 files changed

+106
-50
lines changed

api/cpp/cbindgen.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ fn gen_corelib(
545545
"slint_windowrc_hide",
546546
"slint_windowrc_is_visible",
547547
"slint_windowrc_get_scale_factor",
548-
"slint_windowrc_set_scale_factor",
548+
"slint_windowrc_set_const_scale_factor",
549549
"slint_windowrc_get_text_input_focused",
550550
"slint_windowrc_set_text_input_focused",
551551
"slint_windowrc_set_focus_item",

api/cpp/include/slint_window.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ class WindowAdapterRc
8282
bool is_visible() const { return slint_windowrc_is_visible(&inner); }
8383

8484
float scale_factor() const { return slint_windowrc_get_scale_factor(&inner); }
85-
void set_scale_factor(float value) const { slint_windowrc_set_scale_factor(&inner, value); }
85+
void set_const_scale_factor(float value) const
86+
{
87+
slint_windowrc_set_const_scale_factor(&inner, value);
88+
}
8689

8790
cbindgen_private::ColorScheme color_scheme() const
8891
{

api/rs/build/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,12 @@ impl CompilerConfiguration {
170170
/// as constant value. This is only intended for MCU environments. Use
171171
/// in combination with [`Self::embed_resources`] to pre-scale images and glyphs
172172
/// accordingly.
173+
///
174+
/// If this is set, changing the scale factor at runtime will not have any effect.
173175
#[must_use]
174-
pub fn with_scale_factor(self, factor: f32) -> Self {
175-
let mut config = self.config;
176-
config.const_scale_factor = factor as f64;
177-
Self { config }
176+
pub fn with_scale_factor(mut self, factor: f32) -> Self {
177+
self.config.const_scale_factor = Some(factor);
178+
self
178179
}
179180

180181
/// Configures the compiler to bundle translations when compiling Slint code.

internal/compiler/expression_tree.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,9 @@ impl BuiltinFunction {
289289
/// It is const if the return value only depends on its argument and has no side effect
290290
fn is_const(&self, global_analysis: Option<&crate::passes::GlobalAnalysis>) -> bool {
291291
match self {
292-
BuiltinFunction::GetWindowScaleFactor => false,
292+
BuiltinFunction::GetWindowScaleFactor => {
293+
global_analysis.is_some_and(|x| x.const_scale_factor.is_some())
294+
}
293295
BuiltinFunction::GetWindowDefaultFontSize => {
294296
global_analysis.is_some_and(|x| x.default_font_size.is_const())
295297
}

internal/compiler/generator/cpp.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
// cSpell:ignore cmath constexpr cstdlib decltype intptr itertools nullptr prepended struc subcomponent uintptr vals
88

9-
use lyon_path::geom::euclid::approxeq::ApproxEq;
109
use std::collections::HashSet;
1110
use std::fmt::Write;
1211
use std::io::BufWriter;
@@ -769,11 +768,9 @@ pub fn generate(
769768
" auto &window = self->m_window.emplace(slint::private_api::WindowAdapterRc());".into(),
770769
];
771770

772-
if !compiler_config.const_scale_factor.approx_eq(&1.0) {
773-
window_creation_code.push(format!(
774-
"window.dispatch_scale_factor_change_event({});",
775-
compiler_config.const_scale_factor
776-
));
771+
if let Some(scale_factor) = compiler_config.const_scale_factor {
772+
window_creation_code
773+
.push(format!("window.window_handle().set_const_scale_factor({scale_factor});"));
777774
}
778775

779776
window_creation_code.extend([

internal/compiler/generator/rust.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::object_tree::Document;
2323
use crate::typeloader::LibraryInfo;
2424
use crate::CompilerConfiguration;
2525
use itertools::Either;
26-
use lyon_path::geom::euclid::approxeq::ApproxEq;
2726
use proc_macro2::{Ident, TokenStream, TokenTree};
2827
use quote::{format_ident, quote};
2928
use smol_str::SmolStr;
@@ -439,14 +438,9 @@ fn generate_shared_globals(
439438

440439
let from_library_global_types =
441440
llr.globals.iter().filter(|g| g.from_library).map(global_inner_name).collect::<Vec<_>>();
442-
let apply_constant_scale_factor = if !compiler_config.const_scale_factor.approx_eq(&1.0) {
443-
let factor = compiler_config.const_scale_factor as f32;
444-
Some(
445-
quote!(adapter.window().try_dispatch_event(slint::platform::WindowEvent::ScaleFactorChanged{ scale_factor: #factor })?;),
446-
)
447-
} else {
448-
None
449-
};
441+
let apply_constant_scale_factor = compiler_config.const_scale_factor.map(|factor| {
442+
quote!(sp::WindowInner::from_pub(adapter.window()).set_const_scale_factor(#factor);)
443+
});
450444

451445
let library_global_vars = llr
452446
.globals

internal/compiler/lib.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ pub struct CompilerConfiguration {
128128
pub inline_all_elements: bool,
129129

130130
/// Compile time scale factor to apply to embedded resources such as images and glyphs.
131-
/// If != 1.0 then the scale factor will be set on the `slint::Window`.
132-
pub const_scale_factor: f64,
131+
/// It will also be set as a const scale factor on the `slint::Window`.
132+
pub const_scale_factor: Option<f32>,
133133

134134
/// expose the accessible role and properties
135135
pub accessibility: bool,
@@ -209,9 +209,8 @@ impl CompilerConfiguration {
209209

210210
let const_scale_factor = std::env::var("SLINT_SCALE_FACTOR")
211211
.ok()
212-
.and_then(|x| x.parse::<f64>().ok())
213-
.filter(|f| *f > 0.)
214-
.unwrap_or(1.);
212+
.and_then(|x| x.parse::<f32>().ok())
213+
.filter(|f| *f > 0.);
215214

216215
let enable_experimental = std::env::var_os("SLINT_ENABLE_EXPERIMENTAL_FEATURES").is_some();
217216

internal/compiler/passes.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ pub async fn run_passes(
236236
embed_images::embed_images(
237237
doc,
238238
type_loader.compiler_config.embed_resources,
239-
type_loader.compiler_config.const_scale_factor,
239+
type_loader.compiler_config.const_scale_factor.unwrap_or(1.),
240240
&type_loader.compiler_config.resource_url_mapper,
241241
diag,
242242
)
@@ -265,15 +265,12 @@ pub async fn run_passes(
265265
crate::EmbedResourcesKind::EmbedTextures => {
266266
let mut characters_seen = std::collections::HashSet::new();
267267

268+
let sf = type_loader.compiler_config.const_scale_factor.unwrap_or(1.) as f64;
269+
268270
// Include at least the default font sizes used in the MCU backend
269-
let mut font_pixel_sizes =
270-
vec![(12. * type_loader.compiler_config.const_scale_factor) as i16];
271+
let mut font_pixel_sizes = vec![(12. * sf) as i16];
271272
doc.visit_all_used_components(|component| {
272-
embed_glyphs::collect_font_sizes_used(
273-
component,
274-
type_loader.compiler_config.const_scale_factor,
275-
&mut font_pixel_sizes,
276-
);
273+
embed_glyphs::collect_font_sizes_used(component, sf, &mut font_pixel_sizes);
277274
embed_glyphs::scan_string_literals(component, &mut characters_seen);
278275
});
279276

internal/compiler/passes/binding_analysis.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ impl DefaultFontSize {
4747
#[derive(Debug, Clone, PartialEq, Default)]
4848
pub struct GlobalAnalysis {
4949
pub default_font_size: DefaultFontSize,
50+
pub const_scale_factor: Option<f32>,
5051
}
5152

5253
/// Maps the alias in the other direction than what the BindingExpression::two_way_binding does.
@@ -60,6 +61,7 @@ pub fn binding_analysis(
6061
diag: &mut BuildDiagnostics,
6162
) -> GlobalAnalysis {
6263
let mut global_analysis = GlobalAnalysis::default();
64+
global_analysis.const_scale_factor = compiler_config.const_scale_factor;
6365
let mut reverse_aliases = Default::default();
6466
mark_used_base_properties(doc);
6567
propagate_is_set_on_aliases(doc, &mut reverse_aliases);

internal/compiler/passes/const_propagation.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ fn try_inline_builtin_function(
308308
let num = |n: f64| Some(Expression::NumberLiteral(n, Unit::None));
309309

310310
match b {
311+
BuiltinFunction::GetWindowScaleFactor => {
312+
ga.const_scale_factor.map(|factor| Expression::NumberLiteral(factor as _, Unit::None))
313+
}
311314
BuiltinFunction::GetWindowDefaultFontSize => match ga.default_font_size {
312315
crate::passes::binding_analysis::DefaultFontSize::LogicalValue(val) => {
313316
Some(Expression::NumberLiteral(val as _, Unit::Px))
@@ -484,3 +487,35 @@ export component Foo inherits Window {{
484487
check_expression(&out1_binding);
485488
}
486489
}
490+
491+
#[test]
492+
fn test_const_scale_factor() {
493+
let source = r#"
494+
export component Foo inherits Window {
495+
out property <length> test: 10phx;
496+
}"#;
497+
498+
let mut test_diags = crate::diagnostics::BuildDiagnostics::default();
499+
let doc_node = crate::parser::parse(
500+
source.to_string(),
501+
Some(std::path::Path::new("HELLO")),
502+
&mut test_diags,
503+
);
504+
let mut compiler_config =
505+
crate::CompilerConfiguration::new(crate::generator::OutputFormat::Interpreter);
506+
compiler_config.style = Some("fluent".into());
507+
compiler_config.const_scale_factor = Some(2.);
508+
let (doc, diag, _) =
509+
spin_on::spin_on(crate::compile_syntax_node(doc_node, test_diags, compiler_config));
510+
assert!(!diag.has_errors(), "slint compile error {:#?}", diag.to_string_vec());
511+
512+
let bindings = &doc.inner_components.last().unwrap().root_element.borrow().bindings;
513+
let mut test_binding = bindings.get("test").unwrap().borrow().expression.clone();
514+
if let Expression::Cast { from, to: _ } = test_binding {
515+
test_binding = *from;
516+
}
517+
assert!(
518+
matches!(test_binding, Expression::NumberLiteral(val, _) if val == 5.0),
519+
"Expression should be 5.0: {test_binding:?}"
520+
);
521+
}

0 commit comments

Comments
 (0)