mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
style: Implement source selection for image-set.
This is based on the logic in ResponsiveImageSelector::SelectImage (just simplified because there's no viewport-dependent widths here). Differential Revision: https://phabricator.services.mozilla.com/D100698
This commit is contained in:
parent
4f28a8cd31
commit
7ddd46aba4
3 changed files with 71 additions and 13 deletions
|
@ -18,7 +18,7 @@ use crate::values::computed::{
|
|||
ToComputedValue, Resolution,
|
||||
};
|
||||
use crate::values::generics::image::{self as generic, GradientCompatMode};
|
||||
use crate::values::specified::image::LineDirection as SpecifiedLineDirection;
|
||||
use crate::values::specified::image as specified;
|
||||
use crate::values::specified::position::{HorizontalPositionKeyword, VerticalPositionKeyword};
|
||||
use std::f32::consts::PI;
|
||||
use std::fmt::{self, Write};
|
||||
|
@ -64,13 +64,66 @@ pub enum LineDirection {
|
|||
Corner(HorizontalPositionKeyword, VerticalPositionKeyword),
|
||||
}
|
||||
|
||||
/// The computed value for an `image-set()` image.
|
||||
pub type ImageSet = generic::GenericImageSet<Image, Resolution>;
|
||||
|
||||
impl ToComputedValue for specified::ImageSet {
|
||||
type ComputedValue = ImageSet;
|
||||
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
let items = self.items.to_computed_value(context);
|
||||
let dpr = context.device().device_pixel_ratio().get();
|
||||
let mut selected_index = 0;
|
||||
let mut selected_resolution = items[0].resolution.dppx();
|
||||
for (i, item) in items.iter().enumerate().skip(1) {
|
||||
let candidate_resolution = item.resolution.dppx();
|
||||
|
||||
// https://drafts.csswg.org/css-images-4/#image-set-notation:
|
||||
//
|
||||
// Make a UA-specific choice of which to load, based on whatever
|
||||
// criteria deemed relevant (such as the resolution of the
|
||||
// display, connection speed, etc).
|
||||
//
|
||||
// For now, select the lowest resolution greater than display
|
||||
// density, otherwise the greatest resolution available
|
||||
let better_candidate = || {
|
||||
if selected_resolution < dpr && candidate_resolution > selected_resolution {
|
||||
return true;
|
||||
}
|
||||
if candidate_resolution < selected_resolution && candidate_resolution >= dpr {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
};
|
||||
|
||||
if better_candidate() {
|
||||
selected_index = i;
|
||||
selected_resolution = candidate_resolution;
|
||||
}
|
||||
}
|
||||
|
||||
ImageSet {
|
||||
selected_index,
|
||||
items,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
Self {
|
||||
selected_index: 0,
|
||||
items: ToComputedValue::from_computed_value(&computed.items),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Computed values for `-moz-image-rect(...)`.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub type MozImageRect = generic::GenericMozImageRect<NumberOrPercentage, ComputedImageUrl>;
|
||||
|
||||
/// Empty enum on non-gecko
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
pub type MozImageRect = crate::values::specified::image::MozImageRect;
|
||||
pub type MozImageRect = specified::MozImageRect;
|
||||
|
||||
impl generic::LineDirection for LineDirection {
|
||||
fn points_downwards(&self, compat_mode: GradientCompatMode) -> bool {
|
||||
|
@ -116,28 +169,28 @@ impl generic::LineDirection for LineDirection {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedLineDirection {
|
||||
impl ToComputedValue for specified::LineDirection {
|
||||
type ComputedValue = LineDirection;
|
||||
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
SpecifiedLineDirection::Angle(ref angle) => {
|
||||
specified::LineDirection::Angle(ref angle) => {
|
||||
LineDirection::Angle(angle.to_computed_value(context))
|
||||
},
|
||||
SpecifiedLineDirection::Horizontal(x) => LineDirection::Horizontal(x),
|
||||
SpecifiedLineDirection::Vertical(y) => LineDirection::Vertical(y),
|
||||
SpecifiedLineDirection::Corner(x, y) => LineDirection::Corner(x, y),
|
||||
specified::LineDirection::Horizontal(x) => LineDirection::Horizontal(x),
|
||||
specified::LineDirection::Vertical(y) => LineDirection::Vertical(y),
|
||||
specified::LineDirection::Corner(x, y) => LineDirection::Corner(x, y),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
match *computed {
|
||||
LineDirection::Angle(ref angle) => {
|
||||
SpecifiedLineDirection::Angle(ToComputedValue::from_computed_value(angle))
|
||||
specified::LineDirection::Angle(ToComputedValue::from_computed_value(angle))
|
||||
},
|
||||
LineDirection::Horizontal(x) => SpecifiedLineDirection::Horizontal(x),
|
||||
LineDirection::Vertical(y) => SpecifiedLineDirection::Vertical(y),
|
||||
LineDirection::Corner(x, y) => SpecifiedLineDirection::Corner(x, y),
|
||||
LineDirection::Horizontal(x) => specified::LineDirection::Horizontal(x),
|
||||
LineDirection::Vertical(y) => specified::LineDirection::Vertical(y),
|
||||
LineDirection::Corner(x, y) => specified::LineDirection::Corner(x, y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ pub enum GenericImage<G, MozImageRect, ImageUrl, Color, Percentage, Resolution>
|
|||
CrossFade(Box<GenericCrossFade<Self, Color, Percentage>>),
|
||||
|
||||
/// An `image-set()` function.
|
||||
ImageSet(Box<GenericImageSet<Self, Resolution>>),
|
||||
ImageSet(#[compute(field_bound)] Box<GenericImageSet<Self, Resolution>>),
|
||||
}
|
||||
|
||||
pub use self::GenericImage as Image;
|
||||
|
@ -141,10 +141,14 @@ pub use self::GenericCrossFadeImage as CrossFadeImage;
|
|||
/// https://drafts.csswg.org/css-images-4/#image-set-notation
|
||||
#[css(comma, function = "image-set")]
|
||||
#[derive(
|
||||
Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem, ToCss, ToComputedValue,
|
||||
Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem, ToCss,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct GenericImageSet<Image, Resolution> {
|
||||
/// The index of the selected candidate. Zero for specified values.
|
||||
#[css(skip)]
|
||||
pub selected_index: usize,
|
||||
|
||||
/// All of the image and resolution pairs.
|
||||
#[css(iterable)]
|
||||
pub items: crate::OwnedSlice<GenericImageSetItem<Image, Resolution>>,
|
||||
|
|
|
@ -324,6 +324,7 @@ impl ImageSet {
|
|||
input.parse_comma_separated(|input| ImageSetItem::parse(context, input, cors_mode))
|
||||
})?;
|
||||
Ok(Self {
|
||||
selected_index: 0,
|
||||
items: items.into()
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue