Skip to content

Commit 3f57f6d

Browse files
committed
feat: Change the image loading source when the environment changes
1 parent 282575e commit 3f57f6d

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
@@ -149,6 +149,9 @@ pub struct BaseDocument {
149149

150150
pub changed: HashSet<usize>,
151151

152+
// All image nodes.
153+
image_nodes: HashSet<usize>,
154+
152155
/// A map from control node ID's to their associated forms node ID's
153156
pub controls_to_form: HashMap<usize, usize>,
154157

@@ -237,6 +240,7 @@ impl BaseDocument {
237240
focus_node_id: None,
238241
active_node_id: None,
239242
changed: HashSet::new(),
243+
image_nodes: HashSet::new(),
240244
controls_to_form: HashMap::new(),
241245
net_provider: Arc::new(DummyNetProvider),
242246
navigation_provider: Arc::new(DummyNavigationProvider {}),
@@ -395,6 +399,11 @@ impl BaseDocument {
395399

396400
// Mark the new node as changed.
397401
self.changed.insert(id);
402+
403+
if self.is_img_node(id) {
404+
self.image_nodes.insert(id);
405+
}
406+
398407
id
399408
}
400409

@@ -489,6 +498,7 @@ impl BaseDocument {
489498
pub fn remove_and_drop_node(&mut self, node_id: usize) -> Option<Node> {
490499
fn remove_node_ignoring_parent(doc: &mut BaseDocument, node_id: usize) -> Option<Node> {
491500
let node = doc.nodes.try_remove(node_id);
501+
doc.image_nodes.remove(&node_id);
492502
if let Some(node) = &node {
493503
for &child in &node.children {
494504
remove_node_ignoring_parent(doc, child);
@@ -606,10 +616,13 @@ impl BaseDocument {
606616

607617
match kind {
608618
ImageType::Image => {
609-
node.element_data_mut().unwrap().node_specific_data =
610-
NodeSpecificData::Image(Box::new(ImageData::Raster(
611-
RasterImageData::new(width, height, image_data),
619+
if let NodeSpecificData::Image(context) =
620+
&mut node.element_data_mut().unwrap().node_specific_data
621+
{
622+
context.data = Some(ImageData::Raster(RasterImageData::new(
623+
width, height, image_data,
612624
)));
625+
}
613626

614627
// Clear layout cache
615628
node.cache.clear();
@@ -632,8 +645,11 @@ impl BaseDocument {
632645

633646
match kind {
634647
ImageType::Image => {
635-
node.element_data_mut().unwrap().node_specific_data =
636-
NodeSpecificData::Image(Box::new(ImageData::Svg(tree)));
648+
if let NodeSpecificData::Image(context) =
649+
&mut node.element_data_mut().unwrap().node_specific_data
650+
{
651+
context.data = Some(ImageData::Svg(tree));
652+
}
637653

638654
// Clear layout cache
639655
node.cache.clear();
@@ -1006,6 +1022,7 @@ impl BaseDocument {
10061022
pub fn set_viewport(&mut self, viewport: Viewport) {
10071023
self.viewport = viewport;
10081024
self.set_stylist_device(make_device(&self.viewport));
1025+
self.environment_changes();
10091026
}
10101027

10111028
pub fn get_viewport(&self) -> Viewport {
@@ -1230,6 +1247,9 @@ impl BaseDocument {
12301247
chain
12311248
}
12321249

1250+
/// Used to determine whether a document matches a media query string,
1251+
/// and to monitor a document to detect when it matches (or stops matching) that media query.
1252+
///
12331253
/// https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
12341254
pub fn match_media(&self, media_query_string: &str) -> bool {
12351255
let mut input = cssparser::ParserInput::new(media_query_string);
@@ -1255,6 +1275,13 @@ impl BaseDocument {
12551275
let media_list = MediaList::parse(&context, &mut parser);
12561276
media_list.evaluate(self.stylist.device(), quirks_mode)
12571277
}
1278+
1279+
fn environment_changes(&mut self) {
1280+
let image_nodes = self.image_nodes.clone();
1281+
for node_id in image_nodes.into_iter() {
1282+
self.environment_changes_with_image(node_id);
1283+
}
1284+
}
12581285
}
12591286

12601287
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
};
@@ -99,7 +99,10 @@ pub(crate) fn collect_layout_children(
9999
.unwrap()
100100
.element_data_mut()
101101
.unwrap()
102-
.node_specific_data = NodeSpecificData::Image(Box::new(svg.into()));
102+
.node_specific_data = NodeSpecificData::Image(Box::new(ImageContext {
103+
selected_source: ImageSource::new("about:blank".to_string()),
104+
data: Some(svg.into()),
105+
}));
103106
}
104107
Err(err) => {
105108
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
@@ -381,15 +381,9 @@ impl<'doc> DocumentMutator<'doc> {
381381
);
382382
}
383383

384-
fn is_img_node(&self, node_id: usize) -> bool {
385-
self.doc.nodes[node_id]
386-
.data
387-
.is_element_with_tag_name(&local_name!("img"))
388-
}
389-
390-
fn maybe_load_image(&self, node_ids: &[usize]) {
384+
fn maybe_load_image(&mut self, node_ids: &[usize]) {
391385
for id in node_ids.iter() {
392-
if self.is_img_node(*id) {
386+
if self.doc.is_img_node(*id) {
393387
self.doc.load_image(*id);
394388
}
395389
}

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)