Skip to content

Commit 3f70869

Browse files
committed
feat: Change the image loading source when the environment changes
1 parent 46c7804 commit 3f70869

File tree

6 files changed

+194
-79
lines changed

6 files changed

+194
-79
lines changed

packages/blitz-dom/src/document.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ pub struct BaseDocument {
156156

157157
pub changed: HashSet<usize>,
158158

159+
// All image nodes.
160+
image_nodes: HashSet<usize>,
161+
159162
/// A map from control node ID's to their associated forms node ID's
160163
pub controls_to_form: HashMap<usize, usize>,
161164

@@ -248,6 +251,7 @@ impl BaseDocument {
248251
active_node_id: None,
249252
mousedown_node_id: None,
250253
changed: HashSet::new(),
254+
image_nodes: HashSet::new(),
251255
controls_to_form: HashMap::new(),
252256
net_provider: Arc::new(DummyNetProvider),
253257
navigation_provider: Arc::new(DummyNavigationProvider),
@@ -411,6 +415,11 @@ impl BaseDocument {
411415

412416
// Mark the new node as changed.
413417
self.changed.insert(id);
418+
419+
if self.is_img_node(id) {
420+
self.image_nodes.insert(id);
421+
}
422+
414423
id
415424
}
416425

@@ -505,6 +514,7 @@ impl BaseDocument {
505514
pub fn remove_and_drop_node(&mut self, node_id: usize) -> Option<Node> {
506515
fn remove_node_ignoring_parent(doc: &mut BaseDocument, node_id: usize) -> Option<Node> {
507516
let node = doc.nodes.try_remove(node_id);
517+
doc.image_nodes.remove(&node_id);
508518
if let Some(node) = &node {
509519
for &child in &node.children {
510520
remove_node_ignoring_parent(doc, child);
@@ -622,10 +632,13 @@ impl BaseDocument {
622632

623633
match kind {
624634
ImageType::Image => {
625-
node.element_data_mut().unwrap().node_specific_data =
626-
NodeSpecificData::Image(Box::new(ImageData::Raster(
627-
RasterImageData::new(width, height, image_data),
635+
if let NodeSpecificData::Image(context) =
636+
&mut node.element_data_mut().unwrap().node_specific_data
637+
{
638+
context.data = Some(ImageData::Raster(RasterImageData::new(
639+
width, height, image_data,
628640
)));
641+
}
629642

630643
// Clear layout cache
631644
node.cache.clear();
@@ -648,8 +661,11 @@ impl BaseDocument {
648661

649662
match kind {
650663
ImageType::Image => {
651-
node.element_data_mut().unwrap().node_specific_data =
652-
NodeSpecificData::Image(Box::new(ImageData::Svg(tree)));
664+
if let NodeSpecificData::Image(context) =
665+
&mut node.element_data_mut().unwrap().node_specific_data
666+
{
667+
context.data = Some(ImageData::Svg(tree));
668+
}
653669

654670
// Clear layout cache
655671
node.cache.clear();
@@ -1033,6 +1049,7 @@ impl BaseDocument {
10331049
self.viewport = viewport;
10341050
self.set_stylist_device(make_device(&self.viewport));
10351051
self.scroll_viewport_by(0.0, 0.0); // Clamp scroll offset
1052+
self.environment_changes();
10361053
}
10371054

10381055
pub fn viewport(&self) -> &Viewport {
@@ -1285,6 +1302,9 @@ impl BaseDocument {
12851302
chain
12861303
}
12871304

1305+
/// Used to determine whether a document matches a media query string,
1306+
/// and to monitor a document to detect when it matches (or stops matching) that media query.
1307+
///
12881308
/// https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
12891309
pub fn match_media(&self, media_query_string: &str) -> bool {
12901310
let mut input = cssparser::ParserInput::new(media_query_string);
@@ -1310,6 +1330,13 @@ impl BaseDocument {
13101330
let media_list = MediaList::parse(&context, &mut parser);
13111331
media_list.evaluate(self.stylist.device(), quirks_mode)
13121332
}
1333+
1334+
fn environment_changes(&mut self) {
1335+
let image_nodes = self.image_nodes.clone();
1336+
for node_id in image_nodes.into_iter() {
1337+
self.environment_changes_with_image(node_id);
1338+
}
1339+
}
13131340
}
13141341

13151342
impl AsRef<BaseDocument> for BaseDocument {

packages/blitz-dom/src/layout/construct.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use style::{
2020
use crate::{
2121
BaseDocument, ElementNodeData, Node, NodeData,
2222
node::{
23-
ListItemLayout, ListItemLayoutPosition, Marker, NodeKind, NodeSpecificData, TextBrush,
24-
TextInputData, TextLayout,
23+
ImageContext, ListItemLayout, ListItemLayoutPosition, Marker, NodeKind, NodeSpecificData,
24+
TextBrush, TextInputData, TextLayout, image::ImageSource,
2525
},
2626
stylo_to_parley,
2727
};
@@ -108,7 +108,10 @@ pub(crate) fn collect_layout_children(
108108
.unwrap()
109109
.element_data_mut()
110110
.unwrap()
111-
.node_specific_data = NodeSpecificData::Image(Box::new(svg.into()));
111+
.node_specific_data = NodeSpecificData::Image(Box::new(ImageContext {
112+
selected_source: ImageSource::new("about:blank".to_string()),
113+
data: Some(svg.into()),
114+
}));
112115
}
113116
Err(err) => {
114117
println!("{container_node_id} SVG parse failed");

packages/blitz-dom/src/layout/mod.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -228,21 +228,27 @@ impl LayoutPartialTree for BaseDocument {
228228

229229
// Get image's native size
230230
let inherent_size = match &element_data.node_specific_data {
231-
NodeSpecificData::Image(image_data) => match &**image_data {
232-
ImageData::Raster(image) => taffy::Size {
233-
width: image.width as f32,
234-
height: image.height as f32,
235-
},
236-
#[cfg(feature = "svg")]
237-
ImageData::Svg(svg) => {
238-
let size = svg.size();
239-
taffy::Size {
240-
width: size.width(),
241-
height: size.height(),
231+
NodeSpecificData::Image(context) => {
232+
if let Some(image_data) = &context.data {
233+
match image_data {
234+
ImageData::Raster(image) => taffy::Size {
235+
width: image.width as f32,
236+
height: image.height as f32,
237+
},
238+
#[cfg(feature = "svg")]
239+
ImageData::Svg(svg) => {
240+
let size = svg.size();
241+
taffy::Size {
242+
width: size.width(),
243+
height: size.height(),
244+
}
245+
}
246+
ImageData::None => taffy::Size::ZERO,
242247
}
248+
} else {
249+
taffy::Size::ZERO
243250
}
244-
ImageData::None => taffy::Size::ZERO,
245-
},
251+
}
246252
NodeSpecificData::None => taffy::Size::ZERO,
247253
_ => unreachable!(),
248254
};

packages/blitz-dom/src/mutator.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -401,15 +401,9 @@ impl<'doc> DocumentMutator<'doc> {
401401
);
402402
}
403403

404-
fn is_img_node(&self, node_id: usize) -> bool {
405-
self.doc.nodes[node_id]
406-
.data
407-
.is_element_with_tag_name(&local_name!("img"))
408-
}
409-
410-
fn maybe_load_image(&self, node_ids: &[usize]) {
404+
fn maybe_load_image(&mut self, node_ids: &[usize]) {
411405
for id in node_ids.iter() {
412-
if self.is_img_node(*id) {
406+
if self.doc.is_img_node(*id) {
413407
self.doc.load_image(*id);
414408
}
415409
}

packages/blitz-dom/src/node.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use crate::layout::table::TableContext;
3838
use blitz_traits::{BlitzMouseButtonEvent, DomEventData, HitResult};
3939

4040
pub mod image;
41+
use image::ImageSource;
4142

4243
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4344
pub enum DisplayOuter {
@@ -426,14 +427,14 @@ impl ElementNodeData {
426427

427428
pub fn image_data(&self) -> Option<&ImageData> {
428429
match &self.node_specific_data {
429-
NodeSpecificData::Image(data) => Some(&**data),
430+
NodeSpecificData::Image(context) => context.data.as_ref(),
430431
_ => None,
431432
}
432433
}
433434

434435
pub fn image_data_mut(&mut self) -> Option<&mut ImageData> {
435436
match self.node_specific_data {
436-
NodeSpecificData::Image(ref mut data) => Some(&mut **data),
437+
NodeSpecificData::Image(ref mut context) => context.data.as_mut(),
437438
_ => None,
438439
}
439440
}
@@ -583,6 +584,21 @@ impl From<usvg::Tree> for ImageData {
583584
}
584585
}
585586

587+
#[derive(Clone)]
588+
pub struct ImageContext {
589+
pub selected_source: ImageSource,
590+
pub data: Option<ImageData>,
591+
}
592+
593+
impl ImageContext {
594+
fn new(selected_source: ImageSource) -> Self {
595+
Self {
596+
selected_source,
597+
data: None,
598+
}
599+
}
600+
}
601+
586602
#[derive(Debug, Clone, PartialEq)]
587603
pub enum Status {
588604
Ok,
@@ -650,7 +666,7 @@ impl TextInputData {
650666
#[derive(Clone)]
651667
pub enum NodeSpecificData {
652668
/// The element's image content (\<img\> element's only)
653-
Image(Box<ImageData>),
669+
Image(Box<ImageContext>),
654670
/// Pre-computed table layout data
655671
TableRoot(Arc<TableContext>),
656672
/// Parley text editor (text inputs)
@@ -664,12 +680,18 @@ pub enum NodeSpecificData {
664680
impl std::fmt::Debug for NodeSpecificData {
665681
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
666682
match self {
667-
NodeSpecificData::Image(data) => match **data {
668-
ImageData::Raster(_) => f.write_str("NodeSpecificData::Image(Raster)"),
669-
#[cfg(feature = "svg")]
670-
ImageData::Svg(_) => f.write_str("NodeSpecificData::Image(Svg)"),
671-
ImageData::None => f.write_str("NodeSpecificData::Image(None)"),
672-
},
683+
NodeSpecificData::Image(context) => {
684+
if let Some(image_data) = &context.data {
685+
match image_data {
686+
ImageData::Raster(_) => f.write_str("NodeSpecificData::Image(Raster)"),
687+
#[cfg(feature = "svg")]
688+
ImageData::Svg(_) => f.write_str("NodeSpecificData::Image(Svg)"),
689+
ImageData::None => f.write_str("NodeSpecificData::Image(None)"),
690+
}
691+
} else {
692+
f.write_str("NodeSpecificData::Image(None)")
693+
}
694+
}
673695
NodeSpecificData::TableRoot(_) => f.write_str("NodeSpecificData::TableRoot"),
674696
NodeSpecificData::TextInput(_) => f.write_str("NodeSpecificData::TextInput"),
675697
NodeSpecificData::CheckboxInput(_) => f.write_str("NodeSpecificData::CheckboxInput"),

0 commit comments

Comments
 (0)