blitz_dom/layout/
damage.rs1use crate::{BaseDocument, net::ImageHandler, node::BackgroundImageData, util::ImageType};
2use blitz_traits::net::Request;
3use style::properties::generated::longhands::position::computed_value::T as Position;
4use style::servo::url::ComputedUrl;
5use style::values::generics::image::Image as StyloImage;
6
7impl BaseDocument {
8 pub fn flush_styles_to_layout(&mut self, node_id: usize) {
10 let doc_id = self.id();
11
12 let display = {
13 let node = self.nodes.get_mut(node_id).unwrap();
14 let stylo_element_data = node.stylo_element_data.borrow();
15 let primary_styles = stylo_element_data
16 .as_ref()
17 .and_then(|data| data.styles.get_primary());
18
19 let Some(style) = primary_styles else {
20 return;
21 };
22
23 node.style = stylo_taffy::to_taffy_style(style);
24 node.display_constructed_as = style.clone_display();
25
26 if let Some(elem) = node.data.downcast_element_mut() {
29 let style_bgs = &style.get_background().background_image.0;
30 let elem_bgs = &mut elem.background_images;
31
32 let len = style_bgs.len();
33 elem_bgs.resize_with(len, || None);
34
35 for idx in 0..len {
36 let background_image = &style_bgs[idx];
37 let new_bg_image = match background_image {
38 StyloImage::Url(ComputedUrl::Valid(new_url)) => {
39 let old_bg_image = elem_bgs[idx].as_ref();
40 let old_bg_image_url = old_bg_image.map(|data| &data.url);
41 if old_bg_image_url.is_some_and(|old_url| **new_url == **old_url) {
42 break;
43 }
44
45 self.net_provider.fetch(
46 doc_id,
47 Request::get((**new_url).clone()),
48 Box::new(ImageHandler::new(node_id, ImageType::Background(idx))),
49 );
50
51 let bg_image_data = BackgroundImageData::new(new_url.clone());
52 Some(bg_image_data)
53 }
54 _ => None,
55 };
56
57 elem_bgs[idx] = new_bg_image;
59 }
60 }
61
62 node.cache.clear();
65
66 node.style.display
67 };
68
69 let children = self.nodes[node_id].layout_children.borrow_mut().take();
71 if let Some(mut children) = children {
72 for child in children.iter() {
74 self.flush_styles_to_layout(*child);
75 }
76
77 if matches!(display, taffy::Display::Flex | taffy::Display::Grid) {
79 children.sort_by(|left, right| {
80 let left_node = self.nodes.get(*left).unwrap();
81 let right_node = self.nodes.get(*right).unwrap();
82 left_node.order().cmp(&right_node.order())
83 });
84 }
85
86 *self.nodes[node_id].layout_children.borrow_mut() = Some(children);
88
89 self.nodes[node_id]
91 .paint_children
92 .borrow_mut()
93 .as_mut()
94 .unwrap()
95 .sort_by(|left, right| {
96 let left_node = self.nodes.get(*left).unwrap();
97 let right_node = self.nodes.get(*right).unwrap();
98 left_node
99 .z_index()
100 .cmp(&right_node.z_index())
101 .then_with(|| {
102 fn position_to_order(pos: Position) -> u8 {
103 match pos {
104 Position::Static | Position::Relative | Position::Sticky => 0,
105 Position::Absolute | Position::Fixed => 1,
106 }
107 }
108 let left_position = left_node
109 .primary_styles()
110 .map(|s| position_to_order(s.clone_position()))
111 .unwrap_or(0);
112 let right_position = right_node
113 .primary_styles()
114 .map(|s| position_to_order(s.clone_position()))
115 .unwrap_or(0);
116
117 left_position.cmp(&right_position)
118 })
119 })
120 }
121 }
122
123 pub(crate) fn invalidate_inline_contexts(&mut self) {
124 let root_node_id = self.root_node().id;
125 let scale = self.viewport.scale();
126 self.iter_subtree_mut(root_node_id, |node_id, doc| {
127 let node = &mut doc.nodes[node_id];
128 let Some(element) = node.data.downcast_element_mut() else {
129 return;
130 };
131
132 if let Some(input) = element.text_input_data_mut() {
133 input.editor.set_scale(scale);
134 let mut font_ctx = doc.font_ctx.lock().unwrap();
135 input
136 .editor
137 .refresh_layout(&mut font_ctx, &mut doc.layout_ctx);
138 }
139 });
140 }
141}