Skip to content

Commit

Permalink
Box image data (memory usage optimisation)
Browse files Browse the repository at this point in the history
Signed-off-by: Nico Burns <[email protected]>
  • Loading branch information
nicoburns committed Jan 20, 2025
1 parent a69bf40 commit 90455b9
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 36 deletions.
4 changes: 2 additions & 2 deletions packages/blitz-dom/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ impl BaseDocument {
match kind {
ImageType::Image => {
node.element_data_mut().unwrap().node_specific_data =
NodeSpecificData::Image(ImageData::from(image));
NodeSpecificData::Image(Box::new(ImageData::from(image)));

// Clear layout cache
node.cache.clear();
Expand All @@ -609,7 +609,7 @@ impl BaseDocument {
match kind {
ImageType::Image => {
node.element_data_mut().unwrap().node_specific_data =
NodeSpecificData::Image(ImageData::Svg(*tree));
NodeSpecificData::Image(Box::new(ImageData::Svg(*tree)));

// Clear layout cache
node.cache.clear();
Expand Down
3 changes: 2 additions & 1 deletion packages/blitz-dom/src/layout/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ pub(crate) fn collect_layout_children(
.unwrap()
.element_data_mut()
.unwrap()
.node_specific_data = NodeSpecificData::Image(ImageData::Svg(svg));
.node_specific_data =
NodeSpecificData::Image(Box::new(ImageData::Svg(svg)));
}
Err(err) => {
println!("{} SVG parse failed", container_node_id);
Expand Down
28 changes: 14 additions & 14 deletions packages/blitz-dom/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,22 +236,22 @@ impl LayoutPartialTree for BaseDocument {

// Get image's native size
let inherent_size = match &element_data.node_specific_data {
NodeSpecificData::Image(ImageData::Raster(data)) => taffy::Size {
width: data.image.width() as f32,
height: data.image.height() as f32,
},
#[cfg(feature = "svg")]
NodeSpecificData::Image(ImageData::Svg(svg)) => {
let size = svg.size();
taffy::Size {
width: size.width(),
height: size.height(),
NodeSpecificData::Image(image_data) => match &**image_data {
ImageData::Raster(data) => taffy::Size {
width: data.image.width() as f32,
height: data.image.height() as f32,
},
#[cfg(feature = "svg")]
ImageData::Svg(svg) => {
let size = svg.size();
taffy::Size {
width: size.width(),
height: size.height(),
}
}
}
NodeSpecificData::None => taffy::Size {
width: 0.0,
height: 0.0,
ImageData::None => taffy::Size::ZERO,
},
NodeSpecificData::None => taffy::Size::ZERO,
_ => unreachable!(),
};

Expand Down
34 changes: 24 additions & 10 deletions packages/blitz-dom/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,32 +412,46 @@ impl ElementNodeData {
attr.value.parse::<T>().ok()
}

pub fn raster_image_data(&self) -> Option<&RasterImageData> {
pub fn image_data(&self) -> Option<&ImageData> {
match self.node_specific_data {
NodeSpecificData::Image(ImageData::Raster(ref data)) => Some(data),
NodeSpecificData::Image(ref data) => Some(&**data),
_ => None,
}
}

pub fn raster_image_data_mut(&mut self) -> Option<&mut RasterImageData> {
pub fn image_data_mut(&mut self) -> Option<&mut ImageData> {
match self.node_specific_data {
NodeSpecificData::Image(ImageData::Raster(ref mut data)) => Some(data),
NodeSpecificData::Image(ref mut data) => Some(&mut **data),
_ => None,
}
}

pub fn raster_image_data(&self) -> Option<&RasterImageData> {
match self.image_data()? {
ImageData::Raster(ref data) => Some(data),
_ => None,
}
}

pub fn raster_image_data_mut(&mut self) -> Option<&mut RasterImageData> {
match self.image_data_mut()? {
ImageData::Raster(ref mut data) => Some(data),
_ => None,
}
}

#[cfg(feature = "svg")]
pub fn svg_data(&self) -> Option<&usvg::Tree> {
match self.node_specific_data {
NodeSpecificData::Image(ImageData::Svg(ref data)) => Some(data),
match self.image_data()? {
ImageData::Svg(ref data) => Some(data),
_ => None,
}
}

#[cfg(feature = "svg")]
pub fn svg_data_mut(&mut self) -> Option<&mut usvg::Tree> {
match self.node_specific_data {
NodeSpecificData::Image(ImageData::Svg(ref mut data)) => Some(data),
match self.image_data_mut()? {
ImageData::Svg(ref mut data) => Some(data),
_ => None,
}
}
Expand Down Expand Up @@ -626,7 +640,7 @@ impl TextInputData {
#[derive(Clone)]
pub enum NodeSpecificData {
/// The element's image content (\<img\> element's only)
Image(ImageData),
Image(Box<ImageData>),
/// Pre-computed table layout data
TableRoot(Arc<TableContext>),
/// Parley text editor (text inputs)
Expand All @@ -640,7 +654,7 @@ pub enum NodeSpecificData {
impl std::fmt::Debug for NodeSpecificData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
NodeSpecificData::Image(data) => match data {
NodeSpecificData::Image(data) => match **data {
ImageData::Raster(_) => f.write_str("NodeSpecificData::Image(Raster)"),
#[cfg(feature = "svg")]
ImageData::Svg(_) => f.write_str("NodeSpecificData::Image(Svg)"),
Expand Down
7 changes: 2 additions & 5 deletions packages/blitz-dom/src/stylo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,7 @@ impl selectors::Element for BlitzNode<'_> {
}

fn is_link(&self) -> bool {
self.data
.is_element_with_tag_name(&local_name!("a"))
self.data.is_element_with_tag_name(&local_name!("a"))
}

fn is_html_slot_element(&self) -> bool {
Expand Down Expand Up @@ -834,9 +833,7 @@ impl<'a> TElement for BlitzNode<'a> {

fn is_html_document_body_element(&self) -> bool {
// Check node is a <body> element
let is_body_element = self
.data
.is_element_with_tag_name(&local_name!("body"));
let is_body_element = self.data.is_element_with_tag_name(&local_name!("body"));

// If it isn't then return early
if !is_body_element {
Expand Down
8 changes: 4 additions & 4 deletions packages/blitz-renderer-vello/src/renderer/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ impl VelloSceneGenerator<'_> {
.children
.iter()
.find_map(|id| {
self.dom.as_ref().get_node(*id).filter(|node| {
node.data
.is_element_with_tag_name(&local_name!("body"))
})
self.dom
.as_ref()
.get_node(*id)
.filter(|node| node.data.is_element_with_tag_name(&local_name!("body")))
})
.and_then(|body| body.primary_styles())
.map(|style| {
Expand Down

0 comments on commit 90455b9

Please sign in to comment.