mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #13604 - canaltinova:gradient, r=Manishearth
Implement all gradients <!-- Please describe your changes on the following line: --> Implementation of all gradients. r? @Manishearth --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #13549 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13604) <!-- Reviewable:end -->
This commit is contained in:
commit
fe6fac4ee2
9 changed files with 1080 additions and 429 deletions
|
@ -1175,55 +1175,137 @@ fn static_assert() {
|
|||
images: longhands::${shorthand}_image::computed_value::T) {
|
||||
use gecko_bindings::structs::nsStyleImage;
|
||||
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 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::{HorizontalDirection, VerticalDirection};
|
||||
use values::specified::{HorizontalDirection, SizeKeyword, VerticalDirection};
|
||||
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();
|
||||
if stop_count >= ::std::u32::MAX as usize {
|
||||
warn!("stylo: Prevented overflow due to too many gradient stops");
|
||||
return;
|
||||
}
|
||||
|
||||
let gecko_gradient = unsafe {
|
||||
Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8,
|
||||
NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as u8,
|
||||
/* repeating = */ false,
|
||||
/* legacy_syntax = */ false,
|
||||
stop_count as u32)
|
||||
};
|
||||
let gecko_gradient = match gradient.gradient_kind {
|
||||
GradientKind::Linear(angle_or_corner) => {
|
||||
let gecko_gradient = unsafe {
|
||||
Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8,
|
||||
NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as u8,
|
||||
gradient.repeating,
|
||||
/* legacy_syntax = */ false,
|
||||
stop_count as u32)
|
||||
};
|
||||
|
||||
match gradient.angle_or_corner {
|
||||
AngleOrCorner::Angle(angle) => {
|
||||
match angle_or_corner {
|
||||
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 {
|
||||
(*gecko_gradient).mAngle.set(angle);
|
||||
(*gecko_gradient).mAngle.set_value(CoordDataValue::None);
|
||||
(*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));
|
||||
// Setting radius values depending shape
|
||||
match shape {
|
||||
GradientShape::Circle(length) => {
|
||||
if let LengthOrKeyword::Length(len) = length {
|
||||
unsafe {
|
||||
(*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();
|
||||
for (index, stop) in gradient.stops.iter().enumerate() {
|
||||
|
@ -1277,8 +1359,8 @@ fn static_assert() {
|
|||
% if shorthand == "background":
|
||||
if let Some(image) = image.0 {
|
||||
match image {
|
||||
Image::LinearGradient(gradient) => {
|
||||
set_linear_gradient(gradient, &mut geckoimage.mImage)
|
||||
Image::Gradient(gradient) => {
|
||||
set_gradient(gradient, &mut geckoimage.mImage)
|
||||
},
|
||||
Image::Url(..) => {
|
||||
// let utf8_bytes = url.as_bytes();
|
||||
|
@ -1294,8 +1376,8 @@ fn static_assert() {
|
|||
use properties::longhands::mask_image::single_value::computed_value::T;
|
||||
match image {
|
||||
T::Image(image) => match image {
|
||||
Image::LinearGradient(gradient) => {
|
||||
set_linear_gradient(gradient, &mut geckoimage.mImage)
|
||||
Image::Gradient(gradient) => {
|
||||
set_gradient(gradient, &mut geckoimage.mImage)
|
||||
}
|
||||
_ => () // we need to support image values
|
||||
},
|
||||
|
|
|
@ -173,8 +173,10 @@
|
|||
use parser::{ParserContext, ParserContextExtraData};
|
||||
use properties::{CSSWideKeyword, DeclaredValue, Shorthand};
|
||||
% endif
|
||||
#[allow(unused_imports)]
|
||||
use cascade_info::CascadeInfo;
|
||||
use error_reporting::ParseErrorReporter;
|
||||
use parser::Parse;
|
||||
use properties::longhands;
|
||||
use properties::property_bit_field::PropertyBitField;
|
||||
use properties::{ComputedValues, PropertyDeclaration};
|
||||
|
@ -565,6 +567,8 @@
|
|||
<%self:shorthand name="${name}" sub_properties="${
|
||||
' '.join(sub_property_pattern % side
|
||||
for side in ['top', 'right', 'bottom', 'left'])}">
|
||||
#[allow(unused_imports)]
|
||||
use parser::Parse;
|
||||
use super::parse_four_sides;
|
||||
use values::specified;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ ${helpers.predefined_type("opacity",
|
|||
<%helpers:vector_longhand name="box-shadow" allow_empty="True" animatable="True">
|
||||
use cssparser::{self, ToCss};
|
||||
use std::fmt;
|
||||
use parser::Parse;
|
||||
use values::LocalToCss;
|
||||
use values::HasViewportPercentage;
|
||||
|
||||
|
@ -355,6 +356,7 @@ ${helpers.predefined_type("opacity",
|
|||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
use app_units::Au;
|
||||
use parser::Parse;
|
||||
use std::ascii::AsciiExt;
|
||||
use values::specified::Length;
|
||||
|
||||
|
@ -1199,6 +1201,7 @@ pub struct OriginParseResult {
|
|||
}
|
||||
|
||||
pub fn parse_origin(_: &ParserContext, input: &mut Parser) -> Result<OriginParseResult,()> {
|
||||
use parser::Parse;
|
||||
use values::specified::{LengthOrPercentage, Percentage};
|
||||
let (mut horizontal, mut vertical, mut depth) = (None, None, None);
|
||||
loop {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue