Implement all gradients in stylo

This commit is contained in:
Nazım Can Altınova 2016-10-09 17:17:31 +03:00
parent 26c98edd68
commit 7300d9ab54

View file

@ -1165,55 +1165,137 @@ fn static_assert() {
images: longhands::${shorthand}_image::computed_value::T) { images: longhands::${shorthand}_image::computed_value::T) {
use gecko_bindings::structs::nsStyleImage; use gecko_bindings::structs::nsStyleImage;
use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType; use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER}; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SHAPE_CIRCULAR};
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER};
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER};
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
use gecko_bindings::structs::nsStyleCoord; use gecko_bindings::structs::nsStyleCoord;
use values::computed::{Image, LinearGradient}; use values::computed::{Image, Gradient, GradientKind, GradientShape, Length, LengthOrKeyword};
use values::computed::{LengthOrPercentage, LengthOrPercentageOrKeyword};
use values::specified::AngleOrCorner; use values::specified::AngleOrCorner;
use values::specified::{HorizontalDirection, VerticalDirection}; use values::specified::{HorizontalDirection, SizeKeyword, VerticalDirection};
use cssparser::Color as CSSColor; use cssparser::Color as CSSColor;
fn set_linear_gradient(gradient: LinearGradient, geckoimage: &mut nsStyleImage) { fn set_gradient(gradient: Gradient, geckoimage: &mut nsStyleImage) {
let stop_count = gradient.stops.len(); let stop_count = gradient.stops.len();
if stop_count >= ::std::u32::MAX as usize { if stop_count >= ::std::u32::MAX as usize {
warn!("stylo: Prevented overflow due to too many gradient stops"); warn!("stylo: Prevented overflow due to too many gradient stops");
return; return;
} }
let gecko_gradient = unsafe { let gecko_gradient = match gradient.gradient_kind {
Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8, GradientKind::Linear(angle_or_corner) => {
NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as u8, let gecko_gradient = unsafe {
/* repeating = */ false, Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8,
/* legacy_syntax = */ false, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as u8,
stop_count as u32) gradient.repeating,
}; /* legacy_syntax = */ false,
stop_count as u32)
};
match gradient.angle_or_corner { match angle_or_corner {
AngleOrCorner::Angle(angle) => { AngleOrCorner::Angle(angle) => {
unsafe {
(*gecko_gradient).mAngle.set(angle);
(*gecko_gradient).mBgPosX.set_value(CoordDataValue::None);
(*gecko_gradient).mBgPosY.set_value(CoordDataValue::None);
}
},
AngleOrCorner::Corner(horiz, vert) => {
let percent_x = match horiz {
HorizontalDirection::Left => 0.0,
HorizontalDirection::Right => 1.0,
};
let percent_y = match vert {
VerticalDirection::Top => 0.0,
VerticalDirection::Bottom => 1.0,
};
unsafe {
(*gecko_gradient).mAngle.set_value(CoordDataValue::None);
(*gecko_gradient).mBgPosX
.set_value(CoordDataValue::Percent(percent_x));
(*gecko_gradient).mBgPosY
.set_value(CoordDataValue::Percent(percent_y));
}
}
}
gecko_gradient
},
GradientKind::Radial(shape, position) => {
let (gecko_shape, gecko_size) = match shape {
GradientShape::Circle(ref length) => {
let size = match *length {
LengthOrKeyword::Keyword(keyword) => {
match keyword {
SizeKeyword::ClosestSide => NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
SizeKeyword::FarthestSide => NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE,
SizeKeyword::ClosestCorner => NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER,
SizeKeyword::FarthestCorner => NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
}
},
_ => NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE,
};
(NS_STYLE_GRADIENT_SHAPE_CIRCULAR as u8, size as u8)
},
GradientShape::Ellipse(ref length) => {
let size = match *length {
LengthOrPercentageOrKeyword::Keyword(keyword) => {
match keyword {
SizeKeyword::ClosestSide => NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
SizeKeyword::FarthestSide => NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE,
SizeKeyword::ClosestCorner => NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER,
SizeKeyword::FarthestCorner => NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
}
},
_ => NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE,
};
(NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL as u8, size as u8)
}
};
let gecko_gradient = unsafe {
Gecko_CreateGradient(gecko_shape,
gecko_size,
gradient.repeating,
/* legacy_syntax = */ false,
stop_count as u32)
};
// Clear mAngle and mBgPos fields
unsafe { unsafe {
(*gecko_gradient).mAngle.set(angle); (*gecko_gradient).mAngle.set_value(CoordDataValue::None);
(*gecko_gradient).mBgPosX.set_value(CoordDataValue::None); (*gecko_gradient).mBgPosX.set_value(CoordDataValue::None);
(*gecko_gradient).mBgPosY.set_value(CoordDataValue::None); (*gecko_gradient).mBgPosY.set_value(CoordDataValue::None);
} }
}
AngleOrCorner::Corner(horiz, vert) => {
let percent_x = match horiz {
HorizontalDirection::Left => 0.0,
HorizontalDirection::Right => 1.0,
};
let percent_y = match vert {
VerticalDirection::Top => 0.0,
VerticalDirection::Bottom => 1.0,
};
unsafe { // Setting radius values depending shape
(*gecko_gradient).mAngle.set_value(CoordDataValue::None); match shape {
(*gecko_gradient).mBgPosX GradientShape::Circle(length) => {
.set_value(CoordDataValue::Percent(percent_x)); if let LengthOrKeyword::Length(len) = length {
(*gecko_gradient).mBgPosY unsafe {
.set_value(CoordDataValue::Percent(percent_y)); (*gecko_gradient).mRadiusX.set_value(CoordDataValue::Coord(len.0));
(*gecko_gradient).mRadiusY.set_value(CoordDataValue::Coord(len.0));
}
}
},
GradientShape::Ellipse(length) => {
if let LengthOrPercentageOrKeyword::LengthOrPercentage(first_len, second_len) = length {
unsafe {
(*gecko_gradient).mRadiusX.set(first_len);
(*gecko_gradient).mRadiusY.set(second_len);
}
}
},
} }
} unsafe {
} (*gecko_gradient).mBgPosX.set(position.horizontal);
(*gecko_gradient).mBgPosY.set(position.vertical);
}
gecko_gradient
},
};
let mut coord: nsStyleCoord = nsStyleCoord::null(); let mut coord: nsStyleCoord = nsStyleCoord::null();
for (index, stop) in gradient.stops.iter().enumerate() { for (index, stop) in gradient.stops.iter().enumerate() {
@ -1267,8 +1349,8 @@ fn static_assert() {
% if shorthand == "background": % if shorthand == "background":
if let Some(image) = image.0 { if let Some(image) = image.0 {
match image { match image {
Image::LinearGradient(gradient) => { Image::Gradient(gradient) => {
set_linear_gradient(gradient, &mut geckoimage.mImage) set_gradient(gradient, &mut geckoimage.mImage)
}, },
Image::Url(..) => { Image::Url(..) => {
// let utf8_bytes = url.as_bytes(); // let utf8_bytes = url.as_bytes();
@ -1284,8 +1366,8 @@ fn static_assert() {
use properties::longhands::mask_image::single_value::computed_value::T; use properties::longhands::mask_image::single_value::computed_value::T;
match image { match image {
T::Image(image) => match image { T::Image(image) => match image {
Image::LinearGradient(gradient) => { Image::Gradient(gradient) => {
set_linear_gradient(gradient, &mut geckoimage.mImage) set_gradient(gradient, &mut geckoimage.mImage)
} }
_ => () // we need to support image values _ => () // we need to support image values
}, },