sixtyfps-compilerlib 0.1.6

Internal SixtyFPS compiler library
Documentation
// Copyright © SixtyFPS GmbH <info@sixtyfps.io>
// SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)

//! Remove the rectangles that serves no purposes
//!
//! Rectangles which do not draw anything and have no x or y don't need to be in
//! the item tree, we can just remove them.

use crate::{langtype::Type, object_tree::*};
use std::rc::Rc;

pub fn optimize_useless_rectangles(root_component: &Rc<Component>) {
    recurse_elem_including_sub_components(root_component, &(), &mut |parent, _| {
        let mut parent = parent.borrow_mut();
        let children = std::mem::take(&mut parent.children);

        for elem in children {
            if !can_optimize(&elem) {
                parent.children.push(elem);
                continue;
            }

            parent.children.extend(std::mem::take(&mut elem.borrow_mut().children));

            parent
                .enclosing_component
                .upgrade()
                .unwrap()
                .optimized_elements
                .borrow_mut()
                .push(elem);
        }
    });
}

/// Check that this is a element we can optimize
fn can_optimize(elem: &ElementRc) -> bool {
    let e = elem.borrow();
    if e.is_flickable_viewport || e.child_of_layout {
        return false;
    };

    let base_type = match &e.base_type {
        Type::Builtin(base_type) if base_type.name == "Rectangle" => base_type,
        _ => return false,
    };

    // Check that no Rectangle property other than height and width are set
    let analysis = e.property_analysis.borrow();
    !e.bindings.keys().chain(analysis.iter().filter(|(_, v)| v.is_set).map(|(k, _)| k)).any(|k| {
        !matches!(k.as_str(), "height" | "width")
            && !e.property_declarations.contains_key(k.as_str())
            && base_type.properties.contains_key(k.as_str())
    })
}