style: Use rust types for gradient stops.

This doesn't clean up all that much, yet, but it's a step in the right
direction.

Differential Revision: https://phabricator.services.mozilla.com/D29168
This commit is contained in:
Emilio Cobos Álvarez 2019-04-30 20:37:54 +00:00
parent e40500622e
commit 8123007717
4 changed files with 52 additions and 63 deletions

View file

@ -24,7 +24,7 @@ use crate::values::computed::{Integer, LengthPercentage};
use crate::values::computed::{Length, Percentage, TextAlign}; use crate::values::computed::{Length, Percentage, TextAlign};
use crate::values::generics::box_::VerticalAlign; use crate::values::generics::box_::VerticalAlign;
use crate::values::generics::grid::{TrackListValue, TrackSize}; use crate::values::generics::grid::{TrackListValue, TrackSize};
use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage}; use crate::values::generics::image::{CompatMode, Image as GenericImage};
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::Zero; use crate::Zero;
use app_units::Au; use app_units::Au;
@ -154,7 +154,6 @@ impl nsStyleImage {
// FIXME(emilio): This is really complex, we should use cbindgen for this. // FIXME(emilio): This is really complex, we should use cbindgen for this.
fn set_gradient(&mut self, gradient: Gradient) { fn set_gradient(&mut self, gradient: Gradient) {
use self::structs::nsStyleCoord;
use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER as CLOSEST_CORNER; use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER as CLOSEST_CORNER;
use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE as CLOSEST_SIDE; use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE as CLOSEST_SIDE;
use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER;
@ -329,26 +328,9 @@ impl nsStyleImage {
}, },
}; };
for (index, item) in gradient.items.iter().enumerate() { for (index, item) in gradient.items.into_iter().enumerate() {
// NB: stops are guaranteed to be none in the gecko side by
// default.
let gecko_stop = unsafe { &mut (*gecko_gradient).mStops[index] }; let gecko_stop = unsafe { &mut (*gecko_gradient).mStops[index] };
let mut coord = nsStyleCoord::null(); *gecko_stop = item;
match *item {
GradientItem::ColorStop(ref stop) => {
gecko_stop.mColor = stop.color.into();
gecko_stop.mIsInterpolationHint = false;
coord.set(stop.position);
},
GradientItem::InterpolationHint(hint) => {
gecko_stop.mIsInterpolationHint = true;
coord.set(Some(hint));
},
}
gecko_stop.mLocation.move_from(coord);
} }
unsafe { unsafe {
@ -419,7 +401,7 @@ impl nsStyleImage {
use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER;
use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE as FARTHEST_SIDE; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE as FARTHEST_SIDE;
use crate::values::computed::position::Position; use crate::values::computed::position::Position;
use crate::values::generics::image::{Circle, ColorStop, Ellipse}; use crate::values::generics::image::{Circle, Ellipse};
use crate::values::generics::image::{EndingShape, GradientKind, ShapeExtent}; use crate::values::generics::image::{EndingShape, GradientKind, ShapeExtent};
let gecko_gradient = bindings::Gecko_GetGradientImageValue(self) let gecko_gradient = bindings::Gecko_GetGradientImageValue(self)
@ -531,24 +513,7 @@ impl nsStyleImage {
}, },
}; };
let items = gecko_gradient let items = gecko_gradient.mStops.iter().cloned().collect();
.mStops
.iter()
.map(|ref stop| {
if stop.mIsInterpolationHint {
GradientItem::InterpolationHint(
LengthPercentage::from_gecko_style_coord(&stop.mLocation)
.expect("mLocation could not convert to LengthPercentage"),
)
} else {
GradientItem::ColorStop(ColorStop {
color: stop.mColor.into(),
position: LengthPercentage::from_gecko_style_coord(&stop.mLocation),
})
}
})
.collect();
let compat_mode = if gecko_gradient.mMozLegacySyntax { let compat_mode = if gecko_gradient.mMozLegacySyntax {
CompatMode::Moz CompatMode::Moz
} else if gecko_gradient.mLegacySyntax { } else if gecko_gradient.mLegacySyntax {

View file

@ -55,7 +55,7 @@ pub enum LineDirection {
pub type EndingShape = generic::EndingShape<Length, LengthPercentage>; pub type EndingShape = generic::EndingShape<Length, LengthPercentage>;
/// A computed gradient item. /// A computed gradient item.
pub type GradientItem = generic::GradientItem<Color, LengthPercentage>; pub type GradientItem = generic::GenericGradientItem<Color, LengthPercentage>;
/// A computed color stop. /// A computed color stop.
pub type ColorStop = generic::ColorStop<Color, LengthPercentage>; pub type ColorStop = generic::ColorStop<Color, LengthPercentage>;

View file

@ -135,13 +135,23 @@ pub enum ShapeExtent {
#[derive( #[derive(
Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem, Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem,
)] )]
pub enum GradientItem<Color, LengthPercentage> { #[repr(C, u8)]
/// A color stop. pub enum GenericGradientItem<Color, LengthPercentage> {
ColorStop(ColorStop<Color, LengthPercentage>), /// A simple color stop, without position.
SimpleColorStop(Color),
/// A complex color stop, with a position.
ComplexColorStop {
/// The color for the stop.
color: Color,
/// The position for the stop.
position: LengthPercentage,
},
/// An interpolation hint. /// An interpolation hint.
InterpolationHint(LengthPercentage), InterpolationHint(LengthPercentage),
} }
pub use self::GenericGradientItem as GradientItem;
/// A color stop. /// A color stop.
/// <https://drafts.csswg.org/css-images/#typedef-color-stop-list> /// <https://drafts.csswg.org/css-images/#typedef-color-stop-list>
#[derive( #[derive(
@ -154,6 +164,20 @@ pub struct ColorStop<Color, LengthPercentage> {
pub position: Option<LengthPercentage>, pub position: Option<LengthPercentage>,
} }
impl<Color, LengthPercentage> ColorStop<Color, LengthPercentage> {
/// Convert the color stop into an appropriate `GradientItem`.
#[inline]
pub fn into_item(self) -> GradientItem<Color, LengthPercentage> {
match self.position {
Some(position) => GradientItem::ComplexColorStop {
color: self.color,
position,
},
None => GradientItem::SimpleColorStop(self.color),
}
}
}
/// Specified values for a paint worklet. /// Specified values for a paint worklet.
/// <https://drafts.css-houdini.org/css-paint-api/> /// <https://drafts.css-houdini.org/css-paint-api/>
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]

View file

@ -484,24 +484,24 @@ impl Gradient {
if reverse_stops { if reverse_stops {
p.reverse(); p.reverse();
} }
Ok(generic::GradientItem::ColorStop(generic::ColorStop { Ok(generic::GradientItem::ComplexColorStop {
color: color, color,
position: Some(p.into()), position: p.into(),
})) })
}) })
}) })
.unwrap_or(vec![]); .unwrap_or(vec![]);
if items.is_empty() { if items.is_empty() {
items = vec![ items = vec![
generic::GradientItem::ColorStop(generic::ColorStop { generic::GradientItem::ComplexColorStop {
color: Color::transparent().into(), color: Color::transparent().into(),
position: Some(Percentage::zero().into()), position: Percentage::zero().into(),
}), },
generic::GradientItem::ColorStop(generic::ColorStop { generic::GradientItem::ComplexColorStop {
color: Color::transparent().into(), color: Color::transparent().into(),
position: Some(Percentage::hundred().into()), position: Percentage::hundred().into(),
}), },
]; ];
} else if items.len() == 1 { } else if items.len() == 1 {
let first = items[0].clone(); let first = items[0].clone();
@ -510,12 +510,12 @@ impl Gradient {
items.sort_by(|a, b| { items.sort_by(|a, b| {
match (a, b) { match (a, b) {
( (
&generic::GradientItem::ColorStop(ref a), &generic::GradientItem::ComplexColorStop { position: ref a_position, .. },
&generic::GradientItem::ColorStop(ref b), &generic::GradientItem::ComplexColorStop { position: ref b_position, .. },
) => match (&a.position, &b.position) { ) => match (a_position, b_position) {
( (
&Some(LengthPercentage::Percentage(a)), &LengthPercentage::Percentage(a),
&Some(LengthPercentage::Percentage(b)), &LengthPercentage::Percentage(b),
) => { ) => {
return a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal); return a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal);
}, },
@ -960,13 +960,13 @@ impl GradientItem {
if let Ok(multi_position) = input.try(|i| LengthPercentage::parse(context, i)) { if let Ok(multi_position) = input.try(|i| LengthPercentage::parse(context, i)) {
let stop_color = stop.color.clone(); let stop_color = stop.color.clone();
items.push(generic::GradientItem::ColorStop(stop)); items.push(stop.into_item());
items.push(generic::GradientItem::ColorStop(ColorStop { items.push(ColorStop {
color: stop_color, color: stop_color,
position: Some(multi_position), position: Some(multi_position),
})); }.into_item());
} else { } else {
items.push(generic::GradientItem::ColorStop(stop)); items.push(stop.into_item());
} }
seen_stop = true; seen_stop = true;