Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support interpolation between currentcolor and numeric color #17219

Merged
merged 10 commits into from Jun 8, 2017

Create RGBAColor for colors compute to RGBA.

  • Loading branch information
upsuper committed Jun 8, 2017
commit bf77f81ed639af0e9b305f6672db696f8a144ff4
@@ -422,17 +422,15 @@ pub trait FragmentDisplayListBuilding {
bounds: &Rect<Au>,
stops: &[GradientItem],
direction: &LineDirection,
repeating: bool,
style: &ServoComputedValues)
repeating: bool)
-> display_list::Gradient;

fn convert_radial_gradient(&self,
bounds: &Rect<Au>,
stops: &[GradientItem],
shape: &EndingShape,
center: &Position,
repeating: bool,
style: &ServoComputedValues)
repeating: bool)
-> display_list::RadialGradient;

/// Adds the display items necessary to paint the background linear gradient of this fragment
@@ -634,8 +632,7 @@ fn build_border_radius_for_inner_rect(outer_rect: &Rect<Au>,
}

fn convert_gradient_stops(gradient_items: &[GradientItem],
total_length: Au,
style: &ServoComputedValues) -> Vec<GradientStop> {
total_length: Au) -> Vec<GradientStop> {
// Determine the position of each stop per CSS-IMAGES § 3.4.

// Only keep the color stops, discard the color interpolation hints.
@@ -722,7 +719,7 @@ fn convert_gradient_stops(gradient_items: &[GradientItem],
};
stops.push(GradientStop {
offset: offset,
color: style.resolve_color(stop.color).to_gfx_color()
color: stop.color.to_gfx_color()
})
}
stops
@@ -1192,8 +1189,7 @@ impl FragmentDisplayListBuilding for Fragment {
bounds: &Rect<Au>,
stops: &[GradientItem],
direction: &LineDirection,
repeating: bool,
style: &ServoComputedValues)
repeating: bool)
-> display_list::Gradient {
let angle = match *direction {
LineDirection::Angle(angle) => angle.radians(),
@@ -1234,7 +1230,7 @@ impl FragmentDisplayListBuilding for Fragment {
let length = Au::from_f32_px(
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));

let mut stops = convert_gradient_stops(stops, length, style);
let mut stops = convert_gradient_stops(stops, length);

// Only clamped gradients need to be fixed because in repeating gradients
// there is no "first" or "last" stop because they repeat infinitly in
@@ -1258,8 +1254,7 @@ impl FragmentDisplayListBuilding for Fragment {
stops: &[GradientItem],
shape: &EndingShape,
center: &Position,
repeating: bool,
style: &ServoComputedValues)
repeating: bool)
-> display_list::RadialGradient {
let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width),
center.vertical.to_used_value(bounds.size.height));
@@ -1278,7 +1273,7 @@ impl FragmentDisplayListBuilding for Fragment {
},
};

let mut stops = convert_gradient_stops(stops, radius.width, style);
let mut stops = convert_gradient_stops(stops, radius.width);
// Repeating gradients have no last stops that can be ignored. So
// fixup is not necessary but may actually break the gradient.
if !repeating {
@@ -1322,8 +1317,7 @@ impl FragmentDisplayListBuilding for Fragment {
let gradient = self.convert_linear_gradient(&bounds,
&gradient.items[..],
angle_or_corner,
gradient.repeating,
style);
gradient.repeating);
DisplayItem::Gradient(box GradientDisplayItem {
base: base,
gradient: gradient,
@@ -1334,8 +1328,7 @@ impl FragmentDisplayListBuilding for Fragment {
&gradient.items[..],
shape,
center,
gradient.repeating,
style);
gradient.repeating);
DisplayItem::RadialGradient(box RadialGradientDisplayItem {
base: base,
gradient: gradient,
@@ -1459,8 +1452,7 @@ impl FragmentDisplayListBuilding for Fragment {
let grad = self.convert_linear_gradient(&bounds,
&gradient.items[..],
&angle_or_corner,
gradient.repeating,
style);
gradient.repeating);

state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
base: base,
@@ -1478,8 +1470,7 @@ impl FragmentDisplayListBuilding for Fragment {
&gradient.items[..],
shape,
center,
gradient.repeating,
style);
gradient.repeating);
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
base: base,
border_widths: border.to_physical(style.writing_mode),
@@ -183,7 +183,6 @@ impl nsStyleImage {
}

fn set_gradient(&mut self, gradient: Gradient) {
use cssparser::Color as CSSColor;
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_CIRCULAR, NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL};
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER};
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
@@ -321,19 +320,7 @@ impl nsStyleImage {

match *item {
GradientItem::ColorStop(ref stop) => {
gecko_stop.mColor = match stop.color {
CSSColor::CurrentColor => {
// TODO(emilio): gecko just stores an nscolor,
// and it doesn't seem to support currentColor
// as value in a gradient.
//
// Double-check it and either remove
// currentColor for servo or see how gecko
// handles this.
0
},
CSSColor::RGBA(ref rgba) => convert_rgba_to_nscolor(rgba),
};
gecko_stop.mColor = convert_rgba_to_nscolor(&stop.color);
gecko_stop.mIsInterpolationHint = false;
coord.set(stop.position);
},
@@ -11,7 +11,6 @@
<%namespace name="helpers" file="/helpers.mako.rs" />

use app_units::Au;
use cssparser::Color;
use custom_properties::ComputedValuesMap;
use gecko_bindings::bindings;
% for style_struct in data.style_structs:
@@ -316,26 +315,18 @@ def set_gecko_property(ffi_name, expr):
}
</%def>

/// Convert a Servo color into an nscolor; with currentColor as 0
///
/// Call sites will need to be updated after https://bugzilla.mozilla.org/show_bug.cgi?id=760345
fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
match color {
Color::RGBA(rgba) => {
convert_rgba_to_nscolor(&rgba)
},
Color::CurrentColor => 0,
}
}

<%def name="impl_color_setter(ident, gecko_ffi_name, complex_color=True)">
#[allow(unreachable_code)]
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
% if complex_color:
let result = v.into();
% else:
let result = color_to_nscolor_zero_currentcolor(v);
let result = match color {
Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba),
// FIXME handle currentcolor
Color::CurrentColor => 0,
};
% endif
${set_gecko_property(gecko_ffi_name, "result")}
}
@@ -416,6 +407,20 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
% endif
</%def>

<%def name="impl_rgba_color(ident, gecko_ffi_name, need_clone=False)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
${set_gecko_property(gecko_ffi_name, "convert_rgba_to_nscolor(&v)")}
}
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
% if need_clone:
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)})
}
% endif
</%def>

<%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False, complex_color=True)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) {
@@ -444,14 +449,14 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
SVGPaintKind::Color(color) => {
paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color;
unsafe {
*paint.mPaint.mColor.as_mut() = color_to_nscolor_zero_currentcolor(color);
*paint.mPaint.mColor.as_mut() = convert_rgba_to_nscolor(&color);
}
}
}

if let Some(fallback) = fallback {
paint.mFallbackType = nsStyleSVGFallbackType::eStyleSVGFallbackType_Color;
paint.mFallbackColor = color_to_nscolor_zero_currentcolor(fallback);
paint.mFallbackColor = convert_rgba_to_nscolor(&fallback);
}
}

@@ -472,7 +477,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
use self::structs::nsStyleSVGFallbackType;
let ref paint = ${get_gecko_property(gecko_ffi_name)};
let fallback = if let nsStyleSVGFallbackType::eStyleSVGFallbackType_Color = paint.mFallbackType {
Some(Color::RGBA(convert_nscolor_to_rgba(paint.mFallbackColor)))
Some(convert_nscolor_to_rgba(paint.mFallbackColor))
} else {
None
};
@@ -485,7 +490,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
SVGPaintKind::None
}
nsStyleSVGPaintType::eStyleSVGPaintType_Color => {
unsafe { SVGPaintKind::Color(Color::RGBA(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref()))) }
unsafe { SVGPaintKind::Color(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref())) }
}
};
SVGPaint {
@@ -717,6 +722,7 @@ impl Debug for ${style_struct.gecko_struct_name} {
"Integer": impl_simple,
"Opacity": impl_simple,
"CSSColor": impl_color,
"RGBAColor": impl_rgba_color,
"SVGPaint": impl_svg_paint,
"UrlOrNone": impl_css_url,
}
@@ -948,7 +954,7 @@ fn static_assert() {
structs::Side::eSide${to_camel_case(side.ident)});
}
for color in colors {
let c = color_to_nscolor_zero_currentcolor(*color);
let c = convert_rgba_to_nscolor(color);
unsafe {
bindings::Gecko_AppendMozBorderColors(&mut self.gecko,
structs::Side::eSide${to_camel_case(side.ident)},
@@ -2823,9 +2823,9 @@ impl From<IntermediateColor> for CSSParserColor {
}

/// Animatable SVGPaint
pub type IntermediateSVGPaint = SVGPaint<IntermediateColor>;
pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA>;
/// Animatable SVGPaintKind
pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateColor>;
pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateRGBA>;

impl From<::values::computed::SVGPaint> for IntermediateSVGPaint {
fn from(paint: ::values::computed::SVGPaint) -> IntermediateSVGPaint {
@@ -66,21 +66,21 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
ignored_when_colors_disabled="True">
use std::fmt;
use style_traits::ToCss;
use values::specified::CSSColor;
use values::specified::RGBAColor;
no_viewport_percentage!(SpecifiedValue);

pub mod computed_value {
use values::computed::CSSColor;
use cssparser::RGBA;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub Option<Vec<CSSColor>>);
pub struct T(pub Option<Vec<RGBA>>);
}

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
None,
Colors(Vec<CSSColor>),
Colors(Vec<RGBAColor>),
}

impl ToCss for computed_value::T {
@@ -168,7 +168,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
}

let mut result = Vec::new();
while let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
while let Ok(value) = input.try(|i| RGBAColor::parse(context, i)) {
result.push(value);
}

@@ -20,8 +20,8 @@ ${helpers.single_keyword("vector-effect", "none non-scaling-stroke",
// Section 13 - Gradients and Patterns

${helpers.predefined_type(
"stop-color", "CSSColor",
"CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))",
"stop-color", "RGBAColor",
"RGBA::new(0, 0, 0, 255)",
products="gecko",
animation_value_type="none",
spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty")}
@@ -34,8 +34,8 @@ ${helpers.predefined_type("stop-opacity", "Opacity", "1.0",
// Section 15 - Filter Effects

${helpers.predefined_type(
"flood-color", "CSSColor",
"CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))",
"flood-color", "RGBAColor",
"RGBA::new(0, 0, 0, 255)",
products="gecko",
animation_value_type="none",
spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty")}
@@ -45,8 +45,8 @@ ${helpers.predefined_type("flood-opacity", "Opacity",
spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty")}

${helpers.predefined_type(
"lighting-color", "CSSColor",
"CSSParserColor::RGBA(RGBA::new(255, 255, 255, 255))",
"lighting-color", "RGBAColor",
"RGBA::new(255, 255, 255, 255)",
products="gecko",
animation_value_type="none",
spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")}
@@ -0,0 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Computed color values.

use cssparser::RGBA;

/// Computed value type for the specified RGBAColor.
pub type RGBAColor = RGBA;
@@ -7,7 +7,7 @@
//!
//! [image]: https://drafts.csswg.org/css-images/#image-values

use cssparser::Color as CSSColor;
use cssparser::RGBA;
use std::f32::consts::PI;
use std::fmt;
use style_traits::ToCss;
@@ -35,7 +35,7 @@ pub type Gradient = GenericGradient<
Length,
LengthOrPercentage,
Position,
CSSColor,
RGBA,
>;

/// A computed gradient kind.
@@ -60,10 +60,10 @@ pub enum LineDirection {
pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>;

/// A computed gradient item.
pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
pub type GradientItem = GenericGradientItem<RGBA, LengthOrPercentage>;

/// A computed color stop.
pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
pub type ColorStop = GenericColorStop<RGBA, LengthOrPercentage>;

/// Computed values for ImageRect.
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.