slint/sixtyfps_compiler/passes/embed_resources.rs
Simon Hausmann fa95064363 Fix resource embedding across component boundaries
When referencing an image a repeated element and were targeting a
configuration that requires resource embedding, then that image would
not embedded.

This was due to the fact that we didn't recurse into sub-components in
the resource collection phase and the generators made a per-component
embedding decision. The field responsible for that was also not
propagated to sub-components.

This patch addresses these two bugs by cleaning up the entire mechanism:

The compiler first generates the new ResourceReference::AbsolutePath for
all img!"foo.png" expressions. If the compiler is configured to embed
resources, then the embed_resources pass will traverse all
sub-components and expressions in them to change them to
ResourceReference::EmbeddedData with a unique integer id. Simultaenously
all the resources to be embedded get also collected in the root
component, so that the build script as well as the generator can take
care of dependency handling and actual resource embedding.
2020-11-23 13:47:16 +01:00

45 lines
1.7 KiB
Rust

/* LICENSE BEGIN
This file is part of the SixtyFPS Project -- https://sixtyfps.io
Copyright (c) 2020 Olivier Goffart <olivier.goffart@sixtyfps.io>
Copyright (c) 2020 Simon Hausmann <simon.hausmann@sixtyfps.io>
SPDX-License-Identifier: GPL-3.0-only
This file is also available under commercial licensing terms.
Please contact info@sixtyfps.io for more information.
LICENSE END */
use crate::expression_tree::{Expression, ResourceReference};
use crate::object_tree::*;
use std::{cell::RefCell, collections::HashMap, rc::Rc};
pub fn embed_resources(component: &Rc<Component>) {
let global_embedded_resources = &component.embedded_file_resources;
recurse_elem_including_sub_components(&component.root_element, &(), &mut |elem, _| {
visit_element_expressions(elem, |e, _, _| {
embed_resources_from_expression(e, component, global_embedded_resources)
});
})
}
fn embed_resources_from_expression(
e: &mut Expression,
component: &Rc<Component>,
global_embedded_resources: &RefCell<HashMap<String, usize>>,
) {
match e {
Expression::ResourceReference(ref mut resource_ref) => match resource_ref {
ResourceReference::AbsolutePath(path) => {
let mut resources = global_embedded_resources.borrow_mut();
let maybe_id = resources.len();
let resource_id = *resources.entry(path.clone()).or_insert(maybe_id);
*resource_ref = ResourceReference::EmbeddedData(resource_id)
}
ResourceReference::EmbeddedData(_) => {}
},
_ => {}
};
e.visit_mut(|mut e| {
embed_resources_from_expression(&mut e, component, global_embedded_resources)
});
}