From 7300d9ab540eca39128cd0b8b00d9c55fa046e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Sun, 9 Oct 2016 17:17:31 +0300 Subject: [PATCH] Implement all gradients in stylo --- components/style/properties/gecko.mako.rs | 154 +++++++++++++++++----- 1 file changed, 118 insertions(+), 36 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 99f6c0cdda3..b0b9b96ae2c 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1165,55 +1165,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() { @@ -1267,8 +1349,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(); @@ -1284,8 +1366,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 },