Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ style_traits = { version = "0.4", package = "stylo_traits" }
style_config = { version = "0.4", package = "stylo_config" }
style_dom = { version = "0.4", package = "stylo_dom" }
selectors = { version = "0.29", package = "selectors" }
cssparser = "0.35"
mime = "0.3"

markup5ever = "0.16.2" # needs to match stylo web_atoms version
html5ever = "0.32" # needs to match stylo web_atoms version
Expand Down
2 changes: 2 additions & 0 deletions packages/blitz-dom/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ euclid = { workspace = true }
atomic_refcell = { workspace = true }
markup5ever = { workspace = true }
smallvec = { workspace = true }
cssparser = { workspace = true }
mime = { workspace = true }

# DioxusLabs dependencies
taffy = { workspace = true }
Expand Down
68 changes: 62 additions & 6 deletions packages/blitz-dom/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,15 @@ use style::values::computed::Overflow;
use style::{
dom::{TDocument, TNode},
media_queries::{Device, MediaList},
parser::ParserContext,
selector_parser::SnapshotMap,
shared_lock::{SharedRwLock, StylesheetGuards},
stylesheets::{AllowImportRules, DocumentStyleSheet, Origin, Stylesheet, UrlExtraData},
stylesheets::{
AllowImportRules, CssRuleType, DocumentStyleSheet, Origin, Stylesheet, UrlExtraData,
},
stylist::Stylist,
};
use style_traits::ParsingMode;
use taffy::AvailableSpace;
use url::Url;

Expand Down Expand Up @@ -153,6 +157,9 @@ pub struct BaseDocument {

pub changed: HashSet<usize>,

// All image nodes.
image_nodes: HashSet<usize>,

/// A map from control node ID's to their associated forms node ID's
pub controls_to_form: HashMap<usize, usize>,

Expand Down Expand Up @@ -246,6 +253,7 @@ impl BaseDocument {
mousedown_node_id: None,
is_animating: false,
changed: HashSet::new(),
image_nodes: HashSet::new(),
controls_to_form: HashMap::new(),
net_provider: Arc::new(DummyNetProvider),
navigation_provider: Arc::new(DummyNavigationProvider),
Expand Down Expand Up @@ -414,6 +422,11 @@ impl BaseDocument {

// Mark the new node as changed.
self.changed.insert(id);

if self.is_img_node(id) {
self.image_nodes.insert(id);
}

id
}

Expand Down Expand Up @@ -569,10 +582,13 @@ impl BaseDocument {

match kind {
ImageType::Image => {
node.element_data_mut().unwrap().special_data =
SpecialElementData::Image(Box::new(ImageData::Raster(
RasterImageData::new(width, height, image_data),
if let SpecialElementData::Image(context) =
&mut node.element_data_mut().unwrap().special_data
{
context.data = Some(ImageData::Raster(RasterImageData::new(
width, height, image_data,
)));
}

// Clear layout cache
node.cache.clear();
Expand All @@ -595,8 +611,11 @@ impl BaseDocument {

match kind {
ImageType::Image => {
node.element_data_mut().unwrap().special_data =
SpecialElementData::Image(Box::new(ImageData::Svg(tree)));
if let SpecialElementData::Image(context) =
&mut node.element_data_mut().unwrap().special_data
{
context.data = Some(ImageData::Svg(tree));
}

// Clear layout cache
node.cache.clear();
Expand Down Expand Up @@ -892,6 +911,7 @@ impl BaseDocument {
self.stylist.set_device(device, &guards)
};
self.stylist.force_stylesheet_origins_dirty(origins);
self.environment_changes();
}

pub fn stylist_device(&mut self) -> &Device {
Expand Down Expand Up @@ -1092,6 +1112,42 @@ impl BaseDocument {
false
})
}

/// Used to determine whether a document matches a media query string,
/// and to monitor a document to detect when it matches (or stops matching) that media query.
///
/// https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
pub fn match_media(&self, media_query_string: &str) -> bool {
let mut input = cssparser::ParserInput::new(media_query_string);
let mut parser = cssparser::Parser::new(&mut input);

let url_data = UrlExtraData::from(
self.base_url
.clone()
.unwrap_or_else(|| "about:blank".parse::<Url>().unwrap()),
);
let quirks_mode = self.stylist.quirks_mode();
let context = ParserContext::new(
Origin::Author,
&url_data,
Some(CssRuleType::Style),
ParsingMode::all(),
quirks_mode,
Default::default(),
None,
None,
);

let media_list = MediaList::parse(&context, &mut parser);
media_list.evaluate(self.stylist.device(), quirks_mode)
}

fn environment_changes(&mut self) {
let image_nodes = self.image_nodes.clone();
for node_id in image_nodes.into_iter() {
self.environment_changes_with_image(node_id);
}
}
}

impl AsRef<BaseDocument> for BaseDocument {
Expand Down
10 changes: 7 additions & 3 deletions packages/blitz-dom/src/layout/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use style::{
use crate::{
BaseDocument, ElementData, Node, NodeData,
node::{
ListItemLayout, ListItemLayoutPosition, Marker, NodeFlags, NodeKind, SpecialElementData,
TextBrush, TextInputData, TextLayout,
ImageContext, ImageSource, ListItemLayout, ListItemLayoutPosition, Marker, NodeFlags,
NodeKind, SpecialElementData, TextBrush, TextInputData, TextLayout,
},
stylo_to_parley,
};
Expand Down Expand Up @@ -110,7 +110,11 @@ pub(crate) fn collect_layout_children(
.unwrap()
.element_data_mut()
.unwrap()
.special_data = SpecialElementData::Image(Box::new(svg.into()));
.special_data =
SpecialElementData::Image(Box::new(ImageContext::new_with_data(
ImageSource::new("about:blank".to_string()),
svg.into(),
)));
}
Err(err) => {
println!("{container_node_id} SVG parse failed");
Expand Down
34 changes: 20 additions & 14 deletions packages/blitz-dom/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,23 +227,29 @@ impl LayoutPartialTree for BaseDocument {
.and_then(|val| val.parse::<f32>().ok()),
};

// Get image's native sizespecial_data
// Get image's native size
let inherent_size = match &element_data.special_data {
SpecialElementData::Image(image_data) => match &**image_data {
ImageData::Raster(image) => taffy::Size {
width: image.width as f32,
height: image.height as f32,
},
#[cfg(feature = "svg")]
ImageData::Svg(svg) => {
let size = svg.size();
taffy::Size {
width: size.width(),
height: size.height(),
SpecialElementData::Image(context) => {
if let Some(image_data) = &context.data {
match image_data {
ImageData::Raster(image) => taffy::Size {
width: image.width as f32,
height: image.height as f32,
},
#[cfg(feature = "svg")]
ImageData::Svg(svg) => {
let size = svg.size();
taffy::Size {
width: size.width(),
height: size.height(),
}
}
ImageData::None => taffy::Size::ZERO,
}
} else {
taffy::Size::ZERO
}
ImageData::None => taffy::Size::ZERO,
},
}
SpecialElementData::Canvas(_) => taffy::Size::ZERO,
SpecialElementData::None => taffy::Size::ZERO,
_ => unreachable!(),
Expand Down
13 changes: 12 additions & 1 deletion packages/blitz-dom/src/mutator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,11 @@ impl DocumentMutator<'_> {
element.flush_style_attribute(&self.doc.guard, self.doc.base_url.clone());
} else if (tag, attr) == tag_and_attr!("input", "checked") {
set_input_checked_state(element, value.to_string());
} else if (tag, attr) == tag_and_attr!("img", "src") {
} else if *tag == local_name!("img")
&& (*attr == local_name!("src") || *attr == local_name!("srcset"))
{
self.load_image(node_id);
// self.doc.load_image(node_id);
} else if (tag, attr) == tag_and_attr!("canvas", "src") {
self.load_custom_paint_src(node_id);
}
Expand Down Expand Up @@ -582,6 +585,14 @@ impl<'doc> DocumentMutator<'doc> {
}
}

// fn maybe_load_image(&mut self, node_ids: &[usize]) {
// for id in node_ids.iter() {
// if self.doc.is_img_node(*id) {
// self.doc.load_image(*id);
// }
// }
// }

fn load_custom_paint_src(&mut self, target_id: usize) {
let node = &mut self.doc.nodes[target_id];
if let Some(raw_src) = node.attr(local_name!("src")) {
Expand Down
67 changes: 56 additions & 11 deletions packages/blitz-dom/src/node/element.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use blitz_traits::net::AbortController;
use color::{AlphaColor, Srgb};
use markup5ever::{LocalName, QualName, local_name};
use parley::{FontContext, LayoutContext};
Expand All @@ -14,7 +15,7 @@ use style::{
};
use url::Url;

use super::{Attribute, Attributes};
use super::{Attribute, Attributes, ImageSource};
use crate::layout::table::TableContext;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -73,7 +74,7 @@ pub enum SpecialElementType {
pub enum SpecialElementData {
Stylesheet(DocumentStyleSheet),
/// An \<img\> element's image data
Image(Box<ImageData>),
Image(Box<ImageContext>),
/// A \<canvas\> element's custom paint source
Canvas(CanvasData),
/// Pre-computed table layout data
Expand Down Expand Up @@ -137,15 +138,15 @@ impl ElementData {
}

pub fn image_data(&self) -> Option<&ImageData> {
match &self.special_data {
SpecialElementData::Image(data) => Some(&**data),
match self.special_data {
SpecialElementData::Image(ref context) => context.data.as_ref(),
_ => None,
}
}

pub fn image_data_mut(&mut self) -> Option<&mut ImageData> {
match self.special_data {
SpecialElementData::Image(ref mut data) => Some(&mut **data),
SpecialElementData::Image(ref mut context) => context.data.as_mut(),
_ => None,
}
}
Expand Down Expand Up @@ -302,6 +303,44 @@ impl From<usvg::Tree> for ImageData {
}
}

#[derive(Debug)]
pub struct ImageContext {
pub selected_source: ImageSource,
pub data: Option<ImageData>,
pub controller: Option<AbortController>,
}

impl Clone for ImageContext {
fn clone(&self) -> Self {
Self {
selected_source: self.selected_source.clone(),
data: self.data.clone(),
controller: None,
}
}
}

impl ImageContext {
pub(crate) fn new_with_controller(
selected_source: ImageSource,
controller: AbortController,
) -> Self {
Self {
selected_source,
data: None,
controller: Some(controller),
}
}

pub fn new_with_data(selected_source: ImageSource, data: ImageData) -> Self {
Self {
selected_source,
data: Some(data),
controller: None,
}
}
}

#[derive(Debug, Clone, PartialEq)]
pub enum Status {
Ok,
Expand Down Expand Up @@ -374,12 +413,18 @@ impl std::fmt::Debug for SpecialElementData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SpecialElementData::Stylesheet(_) => f.write_str("NodeSpecificData::Stylesheet"),
SpecialElementData::Image(data) => match **data {
ImageData::Raster(_) => f.write_str("NodeSpecificData::Image(Raster)"),
#[cfg(feature = "svg")]
ImageData::Svg(_) => f.write_str("NodeSpecificData::Image(Svg)"),
ImageData::None => f.write_str("NodeSpecificData::Image(None)"),
},
SpecialElementData::Image(context) => {
if let Some(image_data) = &context.data {
match image_data {
ImageData::Raster(_) => f.write_str("NodeSpecificData::Image(Raster)"),
#[cfg(feature = "svg")]
ImageData::Svg(_) => f.write_str("NodeSpecificData::Image(Svg)"),
ImageData::None => f.write_str("NodeSpecificData::Image(None)"),
}
} else {
f.write_str("NodeSpecificData::Image(None)")
}
}
SpecialElementData::Canvas(_) => f.write_str("NodeSpecificData::Canvas"),
SpecialElementData::TableRoot(_) => f.write_str("NodeSpecificData::TableRoot"),
SpecialElementData::TextInput(_) => f.write_str("NodeSpecificData::TextInput"),
Expand Down
Loading
Loading