diff options
author | ToBinio <Tobias.frischmann1@gmail.com> | 2025-04-07 15:54:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-07 13:54:29 +0000 |
commit | 4f41354349bfbf0802f417ccd57d8b11b30637d9 (patch) | |
tree | b1bf3d93570b392c6782ef47ab5fd291c5706d1e /components | |
parent | 3e249c9bc42e16963a1a3f745d9e846d0051e187 (diff) | |
download | servo-4f41354349bfbf0802f417ccd57d8b11b30637d9.tar.gz servo-4f41354349bfbf0802f417ccd57d8b11b30637d9.zip |
layout: Scale images in `image_set` by their specified resolution (#36374)
This PR makes it so the `resolution` factor in `image-set` also affects
the image size.
For instance, in the example below:
```css
background-image: image-set("./small.png" 1x, "./large.png" 2x);
```
if `large.png` is used, an image which is 32x32 will be rendered as
16x16. This is specified
in <https://drafts.csswg.org/css-images-4/#image-set-notation>.
Testing:
- `css/css-images/image-set/image-set-resolution-002.html`
---------
Signed-off-by: tobinio <Tobias.frischmann1@gmail.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Diffstat (limited to 'components')
-rw-r--r-- | components/layout_2020/context.rs | 31 | ||||
-rw-r--r-- | components/layout_2020/display_list/mod.rs | 11 |
2 files changed, 30 insertions, 12 deletions
diff --git a/components/layout_2020/context.rs b/components/layout_2020/context.rs index 04374849f74..71372ffe224 100644 --- a/components/layout_2020/context.rs +++ b/components/layout_2020/context.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use base::id::PipelineId; +use euclid::Size2D; use fnv::FnvHashMap; use fonts::FontContext; use fxhash::FxHashMap; @@ -148,8 +149,7 @@ impl LayoutContext<'_> { Some(ImageOrMetadataAvailable::ImageAvailable { image, .. }) => { self.handle_animated_image(node, image.clone()); let image_info = WebRenderImageInfo { - width: image.width, - height: image.height, + size: Size2D::new(image.width, image.height), key: image.id, }; if image_info.key.is_none() { @@ -188,10 +188,29 @@ impl LayoutContext<'_> { )?; Some(ResolvedImage::Image(webrender_info)) }, - Image::ImageSet(image_set) => image_set - .items - .get(image_set.selected_index) - .and_then(|image| self.resolve_image(node, &image.image)), + Image::ImageSet(image_set) => { + image_set + .items + .get(image_set.selected_index) + .and_then(|image| { + self.resolve_image(node, &image.image) + .map(|info| match info { + ResolvedImage::Image(mut image_info) => { + // From <https://drafts.csswg.org/css-images-4/#image-set-notation>: + // > A <resolution> (optional). This is used to help the UA decide + // > which <image-set-option> to choose. If the image reference is + // > for a raster image, it also specifies the image’s natural + // > resolution, overriding any other source of data that might + // > supply a natural resolution. + image_info.size = (image_info.size.to_f32() / + image.resolution.dppx()) + .to_u32(); + ResolvedImage::Image(image_info) + }, + _ => info, + }) + }) + }, } } } diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs index 0e71f8505dc..8a746a01184 100644 --- a/components/layout_2020/display_list/mod.rs +++ b/components/layout_2020/display_list/mod.rs @@ -61,8 +61,7 @@ pub use stacking_context::*; #[derive(Clone, Copy)] pub struct WebRenderImageInfo { - pub width: u32, - pub height: u32, + pub size: Size2D<u32, UnknownUnit>, pub key: Option<wr::ImageKey>, } @@ -817,8 +816,8 @@ impl<'a> BuilderForBoxFragment<'a> { // FIXME: https://drafts.csswg.org/css-images-4/#the-image-resolution let dppx = 1.0; let intrinsic = NaturalSizes::from_width_and_height( - image_info.width as f32 / dppx, - image_info.height as f32 / dppx, + image_info.size.width as f32 / dppx, + image_info.size.height as f32 / dppx, ); let Some(image_key) = image_info.key else { continue; @@ -1007,8 +1006,8 @@ impl<'a> BuilderForBoxFragment<'a> { return false; }; - width = image_info.width as f32; - height = image_info.height as f32; + width = image_info.size.width as f32; + height = image_info.size.height as f32; NinePatchBorderSource::Image(key, ImageRendering::Auto) }, Some(ResolvedImage::Gradient(gradient)) => { |