1mod apply_default_properties_from_style;
5mod binding_analysis;
6mod border_radius;
7mod check_expressions;
8mod check_public_api;
9mod check_rotation;
10mod clip;
11mod collect_custom_fonts;
12mod collect_globals;
13mod collect_init_code;
14mod collect_structs_and_enums;
15mod collect_subcomponents;
16mod compile_paths;
17mod const_propagation;
18mod deduplicate_property_read;
19mod default_geometry;
20#[cfg(feature = "software-renderer")]
21mod embed_glyphs;
22mod embed_images;
23mod ensure_window;
24mod flickable;
25mod focus_handling;
26pub mod generate_item_indices;
27pub mod infer_aliases_types;
28mod inject_debug_hooks;
29mod inlining;
30mod lower_absolute_coordinates;
31mod lower_accessibility;
32mod lower_component_container;
33mod lower_layout;
34mod lower_menus;
35mod lower_platform;
36mod lower_popups;
37mod lower_property_to_element;
38mod lower_shadows;
39mod lower_states;
40mod lower_tabwidget;
41mod lower_text_input_interface;
42mod lower_timers;
43pub mod materialize_fake_properties;
44pub mod move_declarations;
45mod optimize_useless_rectangles;
46mod purity_check;
47mod remove_aliases;
48mod remove_return;
49mod remove_unused_properties;
50mod repeater_component;
51pub mod resolve_native_classes;
52pub mod resolving;
53mod unique_id;
54mod visible;
55mod z_order;
56
57use crate::expression_tree::Expression;
58use crate::namedreference::NamedReference;
59use smol_str::SmolStr;
60
61pub fn ignore_debug_hooks(expr: &Expression) -> &Expression {
62 let mut expr = expr;
63 loop {
64 match expr {
65 Expression::DebugHook { expression, .. } => expr = expression.as_ref(),
66 _ => return expr,
67 }
68 }
69}
70
71pub async fn run_passes(
72 doc: &mut crate::object_tree::Document,
73 type_loader: &mut crate::typeloader::TypeLoader,
74 keep_raw: bool,
75 diag: &mut crate::diagnostics::BuildDiagnostics,
76) -> Option<crate::typeloader::TypeLoader> {
77 let style_metrics = {
78 let mut build_diags_to_ignore = crate::diagnostics::BuildDiagnostics::default();
80 type_loader
81 .import_component("std-widgets.slint", "StyleMetrics", &mut build_diags_to_ignore)
82 .await
83 .unwrap_or_else(|| panic!("can't load style metrics"))
84 };
85
86 let palette = {
87 let mut build_diags_to_ignore = crate::diagnostics::BuildDiagnostics::default();
89 type_loader
90 .import_component("std-widgets.slint", "Palette", &mut build_diags_to_ignore)
91 .await
92 .unwrap_or_else(|| panic!("can't load palette"))
93 };
94
95 let global_type_registry = type_loader.global_type_registry.clone();
96
97 run_import_passes(doc, type_loader, diag);
98 check_public_api::check_public_api(doc, &type_loader.compiler_config, diag);
99
100 let raw_type_loader =
101 keep_raw.then(|| crate::typeloader::snapshot_with_extra_doc(type_loader, doc).unwrap());
102
103 collect_subcomponents::collect_subcomponents(doc);
104 doc.visit_all_used_components(|component| {
105 compile_paths::compile_paths(
106 component,
107 &doc.local_registry,
108 type_loader.compiler_config.embed_resources,
109 diag,
110 );
111 });
112 lower_tabwidget::lower_tabwidget(doc, type_loader, diag).await;
113 lower_menus::lower_menus(doc, type_loader, diag).await;
114 lower_component_container::lower_component_container(doc, type_loader, diag);
115 collect_subcomponents::collect_subcomponents(doc);
116
117 doc.visit_all_used_components(|component| {
118 apply_default_properties_from_style::apply_default_properties_from_style(
119 component,
120 &style_metrics,
121 &palette,
122 diag,
123 );
124 lower_states::lower_states(component, &doc.local_registry, diag);
125 lower_text_input_interface::lower_text_input_interface(component);
126 repeater_component::process_repeater_components(component);
127 lower_popups::lower_popups(component, &doc.local_registry, diag);
128 collect_init_code::collect_init_code(component);
129 lower_timers::lower_timers(component, diag);
130 });
131
132 inlining::inline(doc, inlining::InlineSelection::InlineOnlyRequiredComponents, diag);
133 collect_subcomponents::collect_subcomponents(doc);
134
135 for root_component in doc.exported_roots() {
136 focus_handling::call_focus_on_init(&root_component);
137 ensure_window::ensure_window(&root_component, &doc.local_registry, &style_metrics, diag);
138 }
139 if let Some(popup_menu_impl) = &doc.popup_menu_impl {
140 focus_handling::call_focus_on_init(popup_menu_impl);
141 }
142
143 doc.visit_all_used_components(|component| {
144 border_radius::handle_border_radius(component, diag);
145 flickable::handle_flickable(component, &global_type_registry.borrow());
146 lower_layout::lower_layouts(component, type_loader, &style_metrics, diag);
147 default_geometry::default_geometry(component, diag);
148 lower_absolute_coordinates::lower_absolute_coordinates(component);
149 z_order::reorder_by_z_order(component, diag);
150 lower_property_to_element::lower_property_to_element(
151 component,
152 "opacity",
153 core::iter::empty(),
154 None,
155 &SmolStr::new_static("Opacity"),
156 &global_type_registry.borrow(),
157 diag,
158 );
159 lower_property_to_element::lower_property_to_element(
160 component,
161 "cache-rendering-hint",
162 core::iter::empty(),
163 None,
164 &SmolStr::new_static("Layer"),
165 &global_type_registry.borrow(),
166 diag,
167 );
168 visible::handle_visible(component, &global_type_registry.borrow(), diag);
169 lower_shadows::lower_shadow_properties(component, &doc.local_registry, diag);
170 lower_property_to_element::lower_property_to_element(
171 component,
172 crate::typeregister::RESERVED_ROTATION_PROPERTIES[0].0,
173 crate::typeregister::RESERVED_ROTATION_PROPERTIES[1..]
174 .iter()
175 .map(|(prop_name, _)| *prop_name),
176 Some(&|e, prop| Expression::BinaryExpression {
177 lhs: Expression::PropertyReference(NamedReference::new(
178 e,
179 match prop {
180 "rotation-origin-x" => SmolStr::new_static("width"),
181 "rotation-origin-y" => SmolStr::new_static("height"),
182 "rotation-angle" => return Expression::Invalid,
183 _ => unreachable!(),
184 },
185 ))
186 .into(),
187 op: '/',
188 rhs: Expression::NumberLiteral(2., Default::default()).into(),
189 }),
190 &SmolStr::new_static("Rotate"),
191 &global_type_registry.borrow(),
192 diag,
193 );
194 clip::handle_clip(component, &global_type_registry.borrow(), diag);
195 if type_loader.compiler_config.accessibility {
196 lower_accessibility::lower_accessibility_properties(component, diag);
197 }
198 materialize_fake_properties::materialize_fake_properties(component);
199 });
200 for root_component in doc.exported_roots() {
201 lower_layout::check_window_layout(&root_component);
202 }
203 collect_globals::collect_globals(doc, diag);
204
205 if type_loader.compiler_config.inline_all_elements {
206 inlining::inline(doc, inlining::InlineSelection::InlineAllComponents, diag);
207 doc.used_types.borrow_mut().sub_components.clear();
208 }
209
210 binding_analysis::binding_analysis(doc, &type_loader.compiler_config, diag);
211 unique_id::assign_unique_id(doc);
212
213 doc.visit_all_used_components(|component| {
214 lower_platform::lower_platform(component, type_loader);
215
216 if !type_loader.compiler_config.debug_info {
221 optimize_useless_rectangles::optimize_useless_rectangles(component);
222 }
223 move_declarations::move_declarations(component);
224 });
225
226 remove_aliases::remove_aliases(doc, diag);
227 remove_return::remove_return(doc);
228
229 doc.visit_all_used_components(|component| {
230 if !diag.has_errors() {
231 const_propagation::const_propagation(component);
233 }
234 deduplicate_property_read::deduplicate_property_read(component);
235 if !component.is_global() {
236 resolve_native_classes::resolve_native_classes(component);
237 }
238 });
239
240 remove_unused_properties::remove_unused_properties(doc);
241 collect_globals::collect_globals(doc, diag);
243 collect_structs_and_enums::collect_structs_and_enums(doc);
244
245 doc.visit_all_used_components(|component| {
246 if !component.is_global() {
247 generate_item_indices::generate_item_indices(component);
248 }
249 });
250
251 embed_images::embed_images(
252 doc,
253 type_loader.compiler_config.embed_resources,
254 type_loader.compiler_config.const_scale_factor,
255 &type_loader.compiler_config.resource_url_mapper,
256 diag,
257 )
258 .await;
259
260 #[cfg(feature = "bundle-translations")]
261 if let Some(path) = &type_loader.compiler_config.translation_path_bundle {
262 match crate::translations::TranslationsBuilder::load_translations(
263 path,
264 type_loader.compiler_config.translation_domain.as_deref().unwrap_or(""),
265 ) {
266 Ok(builder) => {
267 doc.translation_builder = Some(builder);
268 }
269 Err(err) => {
270 diag.push_error(
271 format!("Cannot load bundled translation: {err}"),
272 doc.node.as_ref().expect("Unexpected empty document"),
273 );
274 }
275 }
276 }
277
278 match type_loader.compiler_config.embed_resources {
279 #[cfg(feature = "software-renderer")]
280 crate::EmbedResourcesKind::EmbedTextures => {
281 let mut characters_seen = std::collections::HashSet::new();
282
283 let mut font_pixel_sizes =
285 vec![(12. * type_loader.compiler_config.const_scale_factor) as i16];
286 doc.visit_all_used_components(|component| {
287 embed_glyphs::collect_font_sizes_used(
288 component,
289 type_loader.compiler_config.const_scale_factor,
290 &mut font_pixel_sizes,
291 );
292 embed_glyphs::scan_string_literals(component, &mut characters_seen);
293 });
294
295 #[cfg(feature = "bundle-translations")]
297 if let Some(translation_builder) = doc.translation_builder.as_ref() {
298 translation_builder.collect_characters_seen(&mut characters_seen);
299 }
300
301 embed_glyphs::embed_glyphs(
302 doc,
303 &type_loader.compiler_config,
304 font_pixel_sizes,
305 characters_seen,
306 std::iter::once(&*doc).chain(type_loader.all_documents()),
307 diag,
308 );
309 }
310 _ => {
311 collect_custom_fonts::collect_custom_fonts(
313 doc,
314 std::iter::once(&*doc).chain(type_loader.all_documents()),
315 type_loader.compiler_config.embed_resources
316 == crate::EmbedResourcesKind::EmbedAllResources,
317 );
318 }
319 };
320
321 raw_type_loader
322}
323
324pub fn run_import_passes(
326 doc: &crate::object_tree::Document,
327 type_loader: &crate::typeloader::TypeLoader,
328 diag: &mut crate::diagnostics::BuildDiagnostics,
329) {
330 inject_debug_hooks::inject_debug_hooks(doc, type_loader);
331 infer_aliases_types::resolve_aliases(doc, diag);
332 resolving::resolve_expressions(doc, type_loader, diag);
333 purity_check::purity_check(doc, diag);
334 focus_handling::replace_forward_focus_bindings_with_focus_functions(doc, diag);
335 check_expressions::check_expressions(doc, diag);
336 check_rotation::check_rotation(doc, diag);
337 unique_id::check_unique_id(doc, diag);
338}