diff options
-rw-r--r-- | Cargo.lock | 4 | ||||
-rw-r--r-- | components/layout/context.rs | 61 | ||||
-rw-r--r-- | components/layout/display_list/mod.rs | 12 | ||||
-rw-r--r-- | components/layout/replaced.rs | 6 |
4 files changed, 53 insertions, 30 deletions
diff --git a/Cargo.lock b/Cargo.lock index 4928ea1be00..e61960b60a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7409,9 +7409,9 @@ checksum = "e454d048db5527d000bfddb77bd072bbf3a1e2ae785f16d9bd116e07c2ab45eb" [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", diff --git a/components/layout/context.rs b/components/layout/context.rs index 71372ffe224..62f8a8cdae9 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -61,6 +61,20 @@ impl Drop for LayoutContext<'_> { } } +#[derive(Debug)] +pub enum ResolveImageError { + LoadError, + ImagePending, + ImageRequested, + OnlyMetadata, + InvalidUrl, + MissingNode, + ImageMissingFromImageSet, + FailedToResolveImageFromImageSet, + NotImplementedYet(&'static str), + None, +} + impl LayoutContext<'_> { #[inline(always)] pub fn shared_context(&self) -> &SharedStyleContext { @@ -72,7 +86,7 @@ impl LayoutContext<'_> { node: OpaqueNode, url: ServoUrl, use_placeholder: UsePlaceholder, - ) -> Option<ImageOrMetadataAvailable> { + ) -> Result<ImageOrMetadataAvailable, ResolveImageError> { // Check for available image or start tracking. let cache_result = self.image_cache.get_cached_image_status( url.clone(), @@ -82,7 +96,7 @@ impl LayoutContext<'_> { ); match cache_result { - ImageCacheResult::Available(img_or_meta) => Some(img_or_meta), + ImageCacheResult::Available(img_or_meta) => Ok(img_or_meta), // Image has been requested, is still pending. Return no image for this paint loop. // When the image loads it will trigger a reflow and/or repaint. ImageCacheResult::Pending(id) => { @@ -93,7 +107,7 @@ impl LayoutContext<'_> { origin: self.origin.clone(), }; self.pending_images.lock().push(image); - None + Result::Err(ResolveImageError::ImagePending) }, // Not yet requested - request image or metadata from the cache ImageCacheResult::ReadyForRequest(id) => { @@ -104,10 +118,10 @@ impl LayoutContext<'_> { origin: self.origin.clone(), }; self.pending_images.lock().push(image); - None + Result::Err(ResolveImageError::ImageRequested) }, // Image failed to load, so just return nothing - ImageCacheResult::LoadError => None, + ImageCacheResult::LoadError => Result::Err(ResolveImageError::LoadError), } } @@ -136,31 +150,34 @@ impl LayoutContext<'_> { node: OpaqueNode, url: ServoUrl, use_placeholder: UsePlaceholder, - ) -> Option<WebRenderImageInfo> { + ) -> Result<WebRenderImageInfo, ResolveImageError> { if let Some(existing_webrender_image) = self .webrender_image_cache .read() .get(&(url.clone(), use_placeholder)) { - return Some(*existing_webrender_image); + return Ok(*existing_webrender_image); } - - match self.get_or_request_image_or_meta(node, url.clone(), use_placeholder) { - Some(ImageOrMetadataAvailable::ImageAvailable { image, .. }) => { + let image_or_meta = + self.get_or_request_image_or_meta(node, url.clone(), use_placeholder)?; + match image_or_meta { + ImageOrMetadataAvailable::ImageAvailable { image, .. } => { self.handle_animated_image(node, image.clone()); let image_info = WebRenderImageInfo { size: Size2D::new(image.width, image.height), key: image.id, }; if image_info.key.is_none() { - Some(image_info) + Ok(image_info) } else { let mut webrender_image_cache = self.webrender_image_cache.write(); webrender_image_cache.insert((url, use_placeholder), image_info); - Some(image_info) + Ok(image_info) } }, - None | Some(ImageOrMetadataAvailable::MetadataAvailable(..)) => None, + ImageOrMetadataAvailable::MetadataAvailable(..) => { + Result::Err(ResolveImageError::OnlyMetadata) + }, } } @@ -168,11 +185,15 @@ impl LayoutContext<'_> { &self, node: Option<OpaqueNode>, image: &'a Image, - ) -> Option<ResolvedImage<'a>> { + ) -> Result<ResolvedImage<'a>, ResolveImageError> { match image { // TODO: Add support for PaintWorklet and CrossFade rendering. - Image::None | Image::CrossFade(_) | Image::PaintWorklet(_) => None, - Image::Gradient(gradient) => Some(ResolvedImage::Gradient(gradient)), + Image::None => Result::Err(ResolveImageError::None), + Image::CrossFade(_) => Result::Err(ResolveImageError::NotImplementedYet("CrossFade")), + Image::PaintWorklet(_) => { + Result::Err(ResolveImageError::NotImplementedYet("PaintWorklet")) + }, + Image::Gradient(gradient) => Ok(ResolvedImage::Gradient(gradient)), Image::Url(image_url) => { // FIXME: images won’t always have in intrinsic width or // height when support for SVG is added, or a WebRender @@ -180,18 +201,20 @@ impl LayoutContext<'_> { // // FIXME: It feels like this should take into account the pseudo // element and not just the node. - let image_url = image_url.url()?; + let image_url = image_url.url().ok_or(ResolveImageError::InvalidUrl)?; + let node = node.ok_or(ResolveImageError::MissingNode)?; let webrender_info = self.get_webrender_image_for_url( - node?, + node, image_url.clone().into(), UsePlaceholder::No, )?; - Some(ResolvedImage::Image(webrender_info)) + Ok(ResolvedImage::Image(webrender_info)) }, Image::ImageSet(image_set) => { image_set .items .get(image_set.selected_index) + .ok_or(ResolveImageError::ImageMissingFromImageSet) .and_then(|image| { self.resolve_image(node, &image.image) .map(|info| match info { diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs index fa313b306f4..912c69366bd 100644 --- a/components/layout/display_list/mod.rs +++ b/components/layout/display_list/mod.rs @@ -838,8 +838,8 @@ impl<'a> BuilderForBoxFragment<'a> { // Reverse because the property is top layer first, we want to paint bottom layer first. for (index, image) in b.background_image.0.iter().enumerate().rev() { match builder.context.resolve_image(node, image) { - None => {}, - Some(ResolvedImage::Gradient(gradient)) => { + Err(_) => {}, + Ok(ResolvedImage::Gradient(gradient)) => { let intrinsic = NaturalSizes::empty(); let Some(layer) = &background::layout_layer(self, painter, builder, index, intrinsic) @@ -875,7 +875,7 @@ impl<'a> BuilderForBoxFragment<'a> { }, } }, - Some(ResolvedImage::Image(image_info)) => { + Ok(ResolvedImage::Image(image_info)) => { // FIXME: https://drafts.csswg.org/css-images-4/#the-image-resolution let dppx = 1.0; let intrinsic = NaturalSizes::from_width_and_height( @@ -1063,8 +1063,8 @@ impl<'a> BuilderForBoxFragment<'a> { .context .resolve_image(node, &border.border_image_source) { - None => return false, - Some(ResolvedImage::Image(image_info)) => { + Err(_) => return false, + Ok(ResolvedImage::Image(image_info)) => { let Some(key) = image_info.key else { return false; }; @@ -1073,7 +1073,7 @@ impl<'a> BuilderForBoxFragment<'a> { height = image_info.size.height as f32; NinePatchBorderSource::Image(key, ImageRendering::Auto) }, - Some(ResolvedImage::Gradient(gradient)) => { + Ok(ResolvedImage::Gradient(gradient)) => { match gradient::build(&self.fragment.style, gradient, border_image_size, builder) { WebRenderGradient::Linear(gradient) => { NinePatchBorderSource::Gradient(gradient) diff --git a/components/layout/replaced.rs b/components/layout/replaced.rs index 6a6b1979ff9..b82fb947074 100644 --- a/components/layout/replaced.rs +++ b/components/layout/replaced.rs @@ -220,13 +220,13 @@ impl ReplacedContents { image_url.clone().into(), UsePlaceholder::No, ) { - Some(ImageOrMetadataAvailable::ImageAvailable { image, .. }) => { + Ok(ImageOrMetadataAvailable::ImageAvailable { image, .. }) => { (Some(image.clone()), image.width as f32, image.height as f32) }, - Some(ImageOrMetadataAvailable::MetadataAvailable(metadata, _id)) => { + Ok(ImageOrMetadataAvailable::MetadataAvailable(metadata, _id)) => { (None, metadata.width as f32, metadata.height as f32) }, - None => return None, + Err(_) => return None, }; return Some(Self { |