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

style: Sync changes from mozilla-central. #21036

Merged
merged 40 commits into from Jun 12, 2018
Merged
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ea5417b
style: Make contain:paint trigger clipping independent of the overflo…
muhammedyusuf-sermet May 30, 2018
35a1a30
style: Remove invalid assertion.
emilio Jun 4, 2018
6940787
style: Make the transition-property code make more sense.
emilio Jun 1, 2018
f6f421f
style: Hide multiple -moz-window-* properties from content.
emilio Jun 1, 2018
90ef560
style: Move TransitionProperty where it belongs.
emilio Jun 1, 2018
ce5a85d
style: Use custom_properties::Name in TransitionProperty.
emilio Jun 4, 2018
1da798e
style: Introduce css(parse_condition).
emilio Jun 2, 2018
cf7b10a
style: Hide -moz- display values from content behind a pref.
emilio Jun 2, 2018
618eef7
style: Don't hide -moz-box / -moz-inline-box yet.
emilio Jun 2, 2018
0f1b793
style: Minor indentation cleanup.
emilio Jun 4, 2018
4b10b2a
style: Update smallbitvec to v2.1.1.
emilio Jun 4, 2018
2baa794
style: Sprinkle some inline in methods that are just pointer-chasing …
emilio Jun 4, 2018
710184b
style: Sprinkle some #[inline] on methods that have inline fast-paths.
emilio Jun 4, 2018
f829300
style: Don't look at the rule type from value parsing.
emilio Jun 1, 2018
8d069d1
style: Work around a bindgen bug on Android.
emilio Jun 4, 2018
8821ad7
style: Make pseudo-elements work with :host.
emilio Jun 4, 2018
2c0a19e
style: Move some parsing-only attributes to use #[parse(..)] instead …
emilio Jun 4, 2018
d461a7d
style: Make the threadsafe refcounting macros more reusable.
emilio Jun 4, 2018
63ca2a8
style: Make clearing atoms slightly more ergonomic.
emilio Jun 4, 2018
c6e43c0
style: Avoid useless allocations in custom property name serialization.
emilio Jun 5, 2018
7529788
style: Make getting a property name explicitly an indexing operation.
emilio Jun 4, 2018
915c872
style: Remove PropertyId::name.
emilio Jun 4, 2018
3816143
style: Use Atomic<bool> for the staticpref version of layout.css.font…
bzbarsky Jun 6, 2018
255fe05
style: Extend StyleComplexColor to support additive blending.
djg May 23, 2018
9c51d31
style: Inline some trivial bits.
emilio Jun 4, 2018
e052666
style: Fix a typo.
emilio Jun 5, 2018
6ca324f
style: Remove unused PropertyDeclarationBlock::set_importance.
emilio Jun 5, 2018
3c7fb2a
style: Add a before-change callback to remove_property.
emilio Jun 5, 2018
cdbc409
style: Trivially simplify a condition.
emilio Jun 5, 2018
314b14d
style: Fix nsStyleBorder::mBorderColor for GCC.
djg Jun 5, 2018
5f74a15
style: Extract {animated,computed}::Color common parts.
djg Jun 5, 2018
011cad2
style: Add a Servo API to get the serialized style of a property.
emilio Jun 7, 2018
d65b29d
style: Add CssPropFlags::SerializedByServo and use it on some simple …
emilio Jun 7, 2018
572a931
style: Add diagnostics.
emilio Jun 9, 2018
078df23
style: Update cssparser.
emilio Jun 11, 2018
e94395b
style_derive: Fix tidy lint.
emilio Jun 11, 2018
ab76003
style: Fix servo build.
emilio Jun 11, 2018
4cd16ee
style: Derive Animate for ComplexColorRatios.
emilio Jun 11, 2018
0d0b0e0
Update WPT expectations.
emilio Jun 12, 2018
2106cc4
style: Update cssparser again to avoid intermittent stack overflows o…
emilio Jun 12, 2018
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

style: Extend StyleComplexColor to support additive blending.

Refactored StyleComplexColor to support "complex" blending between
background (numeric) color and foreground color (currentColor).
Made explicit the distinction between numeric, currentColor and a
complex blend in Gecko and Stylo.

This is to support SMIL animation, for example, of the form:

     <animate from="rgb(10,20,30)" by="currentColor" ... />

Bug: 1465307
Reviewed-by: hiro,xidorn
MozReview-Commit-ID: IUAK8P07gtm
  • Loading branch information
djg authored and emilio committed Jun 12, 2018
commit 255fe05d404a216fe6f2e9d0142d321c9eaf49c1
@@ -5,57 +5,88 @@
//! Rust helpers to interact with Gecko's StyleComplexColor.

use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use gecko_bindings::structs::{nscolor, StyleComplexColor};
use gecko_bindings::structs::StyleComplexColor;
use gecko_bindings::structs::StyleComplexColor_Tag as Tag;
use values::{Auto, Either};
use values::computed::Color as ComputedColor;
use values::computed::{Color as ComputedColor, RGBAColor as ComputedRGBA};
use values::computed::ComplexColorRatios;
use values::computed::ui::ColorOrAuto;

impl From<nscolor> for StyleComplexColor {
fn from(other: nscolor) -> Self {
StyleComplexColor {
mColor: other,
mForegroundRatio: 0,
mIsAuto: false,
}
}
}

impl StyleComplexColor {
/// Create a `StyleComplexColor` value that represents `currentColor`.
pub fn current_color() -> Self {
StyleComplexColor {
mColor: 0,
mForegroundRatio: 255,
mIsAuto: false,
mBgRatio: 0.,
mFgRatio: 1.,
mTag: Tag::eForeground,
}
}

/// Create a `StyleComplexColor` value that represents `auto`.
pub fn auto() -> Self {
StyleComplexColor {
mColor: 0,
mForegroundRatio: 255,
mIsAuto: true,
mBgRatio: 0.,
mFgRatio: 1.,
mTag: Tag::eAuto,
}
}
}

impl From<ComputedRGBA> for StyleComplexColor {
fn from(other: ComputedRGBA) -> Self {
StyleComplexColor {
mColor: convert_rgba_to_nscolor(&other),
mBgRatio: 1.,
mFgRatio: 0.,
mTag: Tag::eNumeric,
}
}
}

impl From<ComputedColor> for StyleComplexColor {
fn from(other: ComputedColor) -> Self {
StyleComplexColor {
mColor: convert_rgba_to_nscolor(&other.color).into(),
mForegroundRatio: other.foreground_ratio,
mIsAuto: false,
match other {
ComputedColor::Numeric(color) => color.into(),
ComputedColor::Foreground => Self::current_color(),
ComputedColor::Complex(color, ratios) => {
debug_assert!(ratios != ComplexColorRatios::NUMERIC);
debug_assert!(ratios != ComplexColorRatios::FOREGROUND);
StyleComplexColor {
mColor: convert_rgba_to_nscolor(&color).into(),
mBgRatio: ratios.bg,
mFgRatio: ratios.fg,
mTag: Tag::eComplex,
}
}
}
}
}

impl From<StyleComplexColor> for ComputedColor {
fn from(other: StyleComplexColor) -> Self {
debug_assert!(!other.mIsAuto);
ComputedColor {
color: convert_nscolor_to_rgba(other.mColor),
foreground_ratio: other.mForegroundRatio,
match other.mTag {
Tag::eNumeric => {
debug_assert!(other.mBgRatio == 1. && other.mFgRatio == 0.);
ComputedColor::Numeric(convert_nscolor_to_rgba(other.mColor))
}
Tag::eForeground => {
debug_assert!(other.mBgRatio == 0. && other.mFgRatio == 1.);
ComputedColor::Foreground
}
Tag::eComplex => {
debug_assert!(other.mBgRatio != 1. || other.mFgRatio != 0.);
debug_assert!(other.mBgRatio != 0. || other.mFgRatio != 1.);
ComputedColor::Complex(
convert_nscolor_to_rgba(other.mColor),
ComplexColorRatios {
bg: other.mBgRatio,
fg: other.mFgRatio,
},
)
}
Tag::eAuto => unreachable!("Unsupport StyleComplexColor with tag eAuto"),
}
}
}
@@ -71,7 +102,7 @@ impl From<ColorOrAuto> for StyleComplexColor {

impl From<StyleComplexColor> for ColorOrAuto {
fn from(other: StyleComplexColor) -> Self {
if !other.mIsAuto {
if other.mTag != Tag::eAuto {
Either::First(other.into())
} else {
Either::Second(Auto)
@@ -6,6 +6,7 @@

use values::animated::{Animate, Procedure, ToAnimatedZero};
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::computed::ComplexColorRatios;

/// An animated RGBA color.
///
@@ -91,42 +92,51 @@ impl ComputeSquaredDistance for RGBA {
}
}

impl Animate for ComplexColorRatios {
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
let bg = self.bg.animate(&other.bg, procedure)?;
let fg = self.fg.animate(&other.fg, procedure)?;

Ok(ComplexColorRatios { bg, fg })
}
}

#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Color {
pub color: RGBA,
pub foreground_ratio: f32,
pub enum Color {
Numeric(RGBA),
Foreground,
Complex(RGBA, ComplexColorRatios),
}

impl Color {
fn currentcolor() -> Self {
Color {
color: RGBA::transparent(),
foreground_ratio: 1.,
}
Color::Foreground
}

/// Returns a transparent intermediate color.
pub fn transparent() -> Self {
Color {
color: RGBA::transparent(),
foreground_ratio: 0.,
}
Color::Numeric(RGBA::transparent())
}

fn is_currentcolor(&self) -> bool {
self.foreground_ratio >= 1.
}

fn is_numeric(&self) -> bool {
self.foreground_ratio <= 0.
fn effective_intermediate_rgba(&self) -> RGBA {
match *self {
Color::Numeric(color) => color,
Color::Foreground => RGBA::transparent(),
Color::Complex(color, ratios) => RGBA {
alpha: color.alpha * ratios.bg,
..color.clone()
},
}
}

fn effective_intermediate_rgba(&self) -> RGBA {
RGBA {
alpha: self.color.alpha * (1. - self.foreground_ratio),
..self.color
fn effective_ratios(&self) -> ComplexColorRatios {
match *self {
Color::Numeric(..) => ComplexColorRatios::NUMERIC,
Color::Foreground => ComplexColorRatios::FOREGROUND,
Color::Complex(.., ratios) => ratios,
}
}
}
@@ -136,78 +146,93 @@ impl Animate for Color {
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
// Common cases are interpolating between two numeric colors,
// two currentcolors, and a numeric color and a currentcolor.
//
// Note: this algorithm assumes self_portion + other_portion
// equals to one, so it may be broken for additive operation.
// To properly support additive color interpolation, we would
// need two ratio fields in computed color types.
let (this_weight, other_weight) = procedure.weights();
if self.foreground_ratio == other.foreground_ratio {
if self.is_currentcolor() {
Ok(Color::currentcolor())
} else {
Ok(Color {
color: self.color.animate(&other.color, procedure)?,
foreground_ratio: self.foreground_ratio,
})

Ok(match (*self, *other, procedure) {
// Any interpolation of currentColor with currentColor returns currentColor.
(Color::Foreground, Color::Foreground, Procedure::Interpolate { .. }) => {
Color::currentcolor()
}
// Animating two numeric colors.
(Color::Numeric(c1), Color::Numeric(c2), _) => {
Color::Numeric(c1.animate(&c2, procedure)?)
}
} else if self.is_currentcolor() && other.is_numeric() {
Ok(Color {
color: other.color,
foreground_ratio: this_weight as f32,
})
} else if self.is_numeric() && other.is_currentcolor() {
Ok(Color {
color: self.color,
foreground_ratio: other_weight as f32,
})
} else {
// For interpolating between two complex colors, we need to
// generate colors with effective alpha value.
let self_color = self.effective_intermediate_rgba();
let other_color = other.effective_intermediate_rgba();
let color = self_color.animate(&other_color, procedure)?;
// Then we compute the final foreground ratio, and derive
// the final alpha value from the effective alpha value.
let foreground_ratio = self.foreground_ratio
.animate(&other.foreground_ratio, procedure)?;
let alpha = color.alpha / (1. - foreground_ratio);
Ok(Color {
color: RGBA {
alpha: alpha,
..color
// Combinations of numeric color and currentColor
(Color::Foreground, Color::Numeric(color), _) => Color::Complex(
color,
ComplexColorRatios {
bg: other_weight as f32,
fg: this_weight as f32,
},
foreground_ratio: foreground_ratio,
})
}
),
(Color::Numeric(color), Color::Foreground, _) => Color::Complex(
color,
ComplexColorRatios {
bg: this_weight as f32,
fg: other_weight as f32,
},
),

// Any other animation of currentColor with currentColor is complex.
(Color::Foreground, Color::Foreground, _) => Color::Complex(
RGBA::transparent(),
ComplexColorRatios {
bg: 0.,
fg: (this_weight + other_weight) as f32,
},
),

// Defer to complex calculations
_ => {
// For interpolating between two complex colors, we need to
// generate colors with effective alpha value.
let self_color = self.effective_intermediate_rgba();
let other_color = other.effective_intermediate_rgba();
let color = self_color.animate(&other_color, procedure)?;
// Then we compute the final background ratio, and derive
// the final alpha value from the effective alpha value.
let self_ratios = self.effective_ratios();
let other_ratios = other.effective_ratios();
let ratios = self_ratios.animate(&other_ratios, procedure)?;
let alpha = color.alpha / ratios.bg;
let color = RGBA { alpha, ..color };

if ratios == ComplexColorRatios::NUMERIC {
Color::Numeric(color)
} else if ratios == ComplexColorRatios::FOREGROUND {
Color::Foreground
} else {
Color::Complex(color, ratios)
}
}
})
}
}

impl ComputeSquaredDistance for Color {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
// All comments from the Animate impl also applies here.
if self.foreground_ratio == other.foreground_ratio {
if self.is_currentcolor() {
Ok(SquaredDistance::from_sqrt(0.))
} else {
self.color.compute_squared_distance(&other.color)
Ok(match (*self, *other) {
(Color::Foreground, Color::Foreground) => SquaredDistance::from_sqrt(0.),
(Color::Numeric(c1), Color::Numeric(c2)) => c1.compute_squared_distance(&c2)?,
(Color::Foreground, Color::Numeric(color))
| (Color::Numeric(color), Color::Foreground) => {
// `computed_squared_distance` is symmetic.
color.compute_squared_distance(&RGBA::transparent())?
+ SquaredDistance::from_sqrt(1.)
}
} else if self.is_currentcolor() && other.is_numeric() {
Ok(
RGBA::transparent().compute_squared_distance(&other.color)? +
SquaredDistance::from_sqrt(1.),
)
} else if self.is_numeric() && other.is_currentcolor() {
Ok(self.color.compute_squared_distance(&RGBA::transparent())? +
SquaredDistance::from_sqrt(1.))
} else {
let self_color = self.effective_intermediate_rgba();
let other_color = other.effective_intermediate_rgba();
Ok(self_color.compute_squared_distance(&other_color)? +
self.foreground_ratio
.compute_squared_distance(&other.foreground_ratio)?)
}
(_, _) => {
let self_color = self.effective_intermediate_rgba();
let other_color = other.effective_intermediate_rgba();
let self_ratios = self.effective_ratios();
let other_ratios = other.effective_ratios();

self_color.compute_squared_distance(&other_color)?
+ self_ratios.bg.compute_squared_distance(&other_ratios.bg)?
+ self_ratios.fg.compute_squared_distance(&other_ratios.fg)?
}
})
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.