mirror of
https://github.com/servo/servo.git
synced 2025-07-31 11:10:22 +01:00
Auto merge of #17219 - upsuper:currentcolor, r=Manishearth,birtles
Support interpolation between currentcolor and numeric color This is the Servo side change of [bug 1345709](https://bugzilla.mozilla.org/show_bug.cgi?id=1345709). <!-- 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/17219) <!-- Reviewable:end -->
This commit is contained in:
commit
24e944ad94
40 changed files with 828 additions and 700 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1419,7 +1419,6 @@ dependencies = [
|
||||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"canvas_traits 0.0.1",
|
"canvas_traits 0.0.1",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gfx 0.0.1",
|
"gfx 0.0.1",
|
||||||
|
|
|
@ -14,7 +14,6 @@ app_units = "0.4.1"
|
||||||
atomic_refcell = "0.1"
|
atomic_refcell = "0.1"
|
||||||
bitflags = "0.7"
|
bitflags = "0.7"
|
||||||
canvas_traits = {path = "../canvas_traits"}
|
canvas_traits = {path = "../canvas_traits"}
|
||||||
cssparser = "0.13.7"
|
|
||||||
euclid = "0.13"
|
euclid = "0.13"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
gfx = {path = "../gfx"}
|
gfx = {path = "../gfx"}
|
||||||
|
|
|
@ -422,8 +422,7 @@ pub trait FragmentDisplayListBuilding {
|
||||||
bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
stops: &[GradientItem],
|
stops: &[GradientItem],
|
||||||
direction: &LineDirection,
|
direction: &LineDirection,
|
||||||
repeating: bool,
|
repeating: bool)
|
||||||
style: &ServoComputedValues)
|
|
||||||
-> display_list::Gradient;
|
-> display_list::Gradient;
|
||||||
|
|
||||||
fn convert_radial_gradient(&self,
|
fn convert_radial_gradient(&self,
|
||||||
|
@ -431,8 +430,7 @@ pub trait FragmentDisplayListBuilding {
|
||||||
stops: &[GradientItem],
|
stops: &[GradientItem],
|
||||||
shape: &EndingShape,
|
shape: &EndingShape,
|
||||||
center: &Position,
|
center: &Position,
|
||||||
repeating: bool,
|
repeating: bool)
|
||||||
style: &ServoComputedValues)
|
|
||||||
-> display_list::RadialGradient;
|
-> display_list::RadialGradient;
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background linear gradient of this fragment
|
/// 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],
|
fn convert_gradient_stops(gradient_items: &[GradientItem],
|
||||||
total_length: Au,
|
total_length: Au) -> Vec<GradientStop> {
|
||||||
style: &ServoComputedValues) -> Vec<GradientStop> {
|
|
||||||
// Determine the position of each stop per CSS-IMAGES § 3.4.
|
// Determine the position of each stop per CSS-IMAGES § 3.4.
|
||||||
|
|
||||||
// Only keep the color stops, discard the color interpolation hints.
|
// Only keep the color stops, discard the color interpolation hints.
|
||||||
|
@ -722,7 +719,7 @@ fn convert_gradient_stops(gradient_items: &[GradientItem],
|
||||||
};
|
};
|
||||||
stops.push(GradientStop {
|
stops.push(GradientStop {
|
||||||
offset: offset,
|
offset: offset,
|
||||||
color: style.resolve_color(stop.color).to_gfx_color()
|
color: stop.color.to_gfx_color()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
stops
|
stops
|
||||||
|
@ -1192,8 +1189,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
stops: &[GradientItem],
|
stops: &[GradientItem],
|
||||||
direction: &LineDirection,
|
direction: &LineDirection,
|
||||||
repeating: bool,
|
repeating: bool)
|
||||||
style: &ServoComputedValues)
|
|
||||||
-> display_list::Gradient {
|
-> display_list::Gradient {
|
||||||
let angle = match *direction {
|
let angle = match *direction {
|
||||||
LineDirection::Angle(angle) => angle.radians(),
|
LineDirection::Angle(angle) => angle.radians(),
|
||||||
|
@ -1234,7 +1230,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let length = Au::from_f32_px(
|
let length = Au::from_f32_px(
|
||||||
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
|
(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
|
// Only clamped gradients need to be fixed because in repeating gradients
|
||||||
// there is no "first" or "last" stop because they repeat infinitly in
|
// there is no "first" or "last" stop because they repeat infinitly in
|
||||||
|
@ -1258,8 +1254,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
stops: &[GradientItem],
|
stops: &[GradientItem],
|
||||||
shape: &EndingShape,
|
shape: &EndingShape,
|
||||||
center: &Position,
|
center: &Position,
|
||||||
repeating: bool,
|
repeating: bool)
|
||||||
style: &ServoComputedValues)
|
|
||||||
-> display_list::RadialGradient {
|
-> display_list::RadialGradient {
|
||||||
let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width),
|
let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width),
|
||||||
center.vertical.to_used_value(bounds.size.height));
|
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
|
// Repeating gradients have no last stops that can be ignored. So
|
||||||
// fixup is not necessary but may actually break the gradient.
|
// fixup is not necessary but may actually break the gradient.
|
||||||
if !repeating {
|
if !repeating {
|
||||||
|
@ -1322,8 +1317,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let gradient = self.convert_linear_gradient(&bounds,
|
let gradient = self.convert_linear_gradient(&bounds,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
angle_or_corner,
|
angle_or_corner,
|
||||||
gradient.repeating,
|
gradient.repeating);
|
||||||
style);
|
|
||||||
DisplayItem::Gradient(box GradientDisplayItem {
|
DisplayItem::Gradient(box GradientDisplayItem {
|
||||||
base: base,
|
base: base,
|
||||||
gradient: gradient,
|
gradient: gradient,
|
||||||
|
@ -1334,8 +1328,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
shape,
|
shape,
|
||||||
center,
|
center,
|
||||||
gradient.repeating,
|
gradient.repeating);
|
||||||
style);
|
|
||||||
DisplayItem::RadialGradient(box RadialGradientDisplayItem {
|
DisplayItem::RadialGradient(box RadialGradientDisplayItem {
|
||||||
base: base,
|
base: base,
|
||||||
gradient: gradient,
|
gradient: gradient,
|
||||||
|
@ -1459,8 +1452,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let grad = self.convert_linear_gradient(&bounds,
|
let grad = self.convert_linear_gradient(&bounds,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
&angle_or_corner,
|
&angle_or_corner,
|
||||||
gradient.repeating,
|
gradient.repeating);
|
||||||
style);
|
|
||||||
|
|
||||||
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
||||||
base: base,
|
base: base,
|
||||||
|
@ -1478,8 +1470,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
shape,
|
shape,
|
||||||
center,
|
center,
|
||||||
gradient.repeating,
|
gradient.repeating);
|
||||||
style);
|
|
||||||
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
||||||
base: base,
|
base: base,
|
||||||
border_widths: border.to_physical(style.writing_mode),
|
border_widths: border.to_physical(style.writing_mode),
|
||||||
|
|
|
@ -16,7 +16,6 @@ extern crate atomic_refcell;
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
extern crate canvas_traits;
|
extern crate canvas_traits;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
extern crate cssparser;
|
|
||||||
extern crate euclid;
|
extern crate euclid;
|
||||||
extern crate fnv;
|
extern crate fnv;
|
||||||
extern crate gfx;
|
extern crate gfx;
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
|
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use cssparser::Color;
|
|
||||||
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
|
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
|
||||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
|
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
|
||||||
use flow::{self, Flow, FlowClass, IS_ABSOLUTELY_POSITIONED, OpaqueFlow};
|
use flow::{self, Flow, FlowClass, IS_ABSOLUTELY_POSITIONED, OpaqueFlow};
|
||||||
|
@ -22,6 +21,7 @@ use std::fmt;
|
||||||
use style::computed_values::{border_collapse, border_top_style, vertical_align};
|
use style::computed_values::{border_collapse, border_top_style, vertical_align};
|
||||||
use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode};
|
use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode};
|
||||||
use style::properties::ServoComputedValues;
|
use style::properties::ServoComputedValues;
|
||||||
|
use style::values::computed::Color;
|
||||||
use table::InternalTable;
|
use table::InternalTable;
|
||||||
use table_row::{CollapsedBorder, CollapsedBorderProvenance};
|
use table_row::{CollapsedBorder, CollapsedBorderProvenance};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use block::{BlockFlow, ISizeAndMarginsComputer};
|
use block::{BlockFlow, ISizeAndMarginsComputer};
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use cssparser::{Color, RGBA};
|
|
||||||
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
|
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
|
||||||
use euclid::Point2D;
|
use euclid::Point2D;
|
||||||
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
|
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
|
||||||
|
@ -26,7 +25,7 @@ use style::computed_values::{border_collapse, border_spacing, border_top_style};
|
||||||
use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode};
|
use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode};
|
||||||
use style::properties::ServoComputedValues;
|
use style::properties::ServoComputedValues;
|
||||||
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
|
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||||
use style::values::computed::LengthOrPercentageOrAuto;
|
use style::values::computed::{Color, LengthOrPercentageOrAuto};
|
||||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt};
|
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt};
|
||||||
use table_cell::{CollapsedBordersForCell, TableCellFlow};
|
use table_cell::{CollapsedBordersForCell, TableCellFlow};
|
||||||
|
|
||||||
|
@ -606,7 +605,7 @@ impl CollapsedBorder {
|
||||||
CollapsedBorder {
|
CollapsedBorder {
|
||||||
style: border_top_style::T::none,
|
style: border_top_style::T::none,
|
||||||
width: Au(0),
|
width: Au(0),
|
||||||
color: Color::RGBA(RGBA::transparent()),
|
color: Color::transparent(),
|
||||||
provenance: CollapsedBorderProvenance::FromTable,
|
provenance: CollapsedBorderProvenance::FromTable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
//! Element nodes.
|
//! Element nodes.
|
||||||
|
|
||||||
use cssparser::Color;
|
|
||||||
use devtools_traits::AttrInfo;
|
use devtools_traits::AttrInfo;
|
||||||
use dom::activation::Activatable;
|
use dom::activation::Activatable;
|
||||||
use dom::attr::{Attr, AttrHelpersForLayout};
|
use dom::attr::{Attr, AttrHelpersForLayout};
|
||||||
|
@ -113,7 +112,7 @@ use style::stylearc::Arc;
|
||||||
use style::stylist::ApplicableDeclarationBlock;
|
use style::stylist::ApplicableDeclarationBlock;
|
||||||
use style::thread_state;
|
use style::thread_state;
|
||||||
use style::values::{CSSFloat, Either};
|
use style::values::{CSSFloat, Either};
|
||||||
use style::values::specified::{self, CSSColor};
|
use style::values::specified;
|
||||||
use stylesheet_loader::StylesheetOwner;
|
use stylesheet_loader::StylesheetOwner;
|
||||||
|
|
||||||
// TODO: Update focus state when the top-level browsing context gains or loses system focus,
|
// TODO: Update focus state when the top-level browsing context gains or loses system focus,
|
||||||
|
@ -422,8 +421,8 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
if let Some(color) = bgcolor {
|
if let Some(color) = bgcolor {
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
shared_lock,
|
shared_lock,
|
||||||
PropertyDeclaration::BackgroundColor(
|
PropertyDeclaration::BackgroundColor(color.into())
|
||||||
CSSColor { parsed: Color::RGBA(color), authored: None })));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let background = if let Some(this) = self.downcast::<HTMLBodyElement>() {
|
let background = if let Some(this) = self.downcast::<HTMLBodyElement>() {
|
||||||
|
@ -457,10 +456,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
shared_lock,
|
shared_lock,
|
||||||
PropertyDeclaration::Color(
|
PropertyDeclaration::Color(
|
||||||
longhands::color::SpecifiedValue(CSSColor {
|
longhands::color::SpecifiedValue(color.into())
|
||||||
parsed: Color::RGBA(color),
|
|
||||||
authored: None,
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,6 @@ impl nsStyleImage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_gradient(&mut self, gradient: Gradient) {
|
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_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_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER};
|
||||||
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
|
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
|
||||||
|
@ -321,19 +320,7 @@ impl nsStyleImage {
|
||||||
|
|
||||||
match *item {
|
match *item {
|
||||||
GradientItem::ColorStop(ref stop) => {
|
GradientItem::ColorStop(ref stop) => {
|
||||||
gecko_stop.mColor = match stop.color {
|
gecko_stop.mColor = convert_rgba_to_nscolor(&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.mIsInterpolationHint = false;
|
gecko_stop.mIsInterpolationHint = false;
|
||||||
coord.set(stop.position);
|
coord.set(stop.position);
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
//! Rust helpers for Gecko's `nsCSSShadowItem`.
|
//! Rust helpers for Gecko's `nsCSSShadowItem`.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::Color;
|
|
||||||
use gecko::values::{convert_rgba_to_nscolor, convert_nscolor_to_rgba};
|
use gecko::values::{convert_rgba_to_nscolor, convert_nscolor_to_rgba};
|
||||||
use gecko_bindings::structs::nsCSSShadowItem;
|
use gecko_bindings::structs::nsCSSShadowItem;
|
||||||
use values::computed::Shadow;
|
use values::computed::{Color, Shadow};
|
||||||
|
|
||||||
impl nsCSSShadowItem {
|
impl nsCSSShadowItem {
|
||||||
/// Set this item to the given shadow value.
|
/// Set this item to the given shadow value.
|
||||||
|
@ -18,14 +17,14 @@ impl nsCSSShadowItem {
|
||||||
self.mRadius = other.blur_radius.0;
|
self.mRadius = other.blur_radius.0;
|
||||||
self.mSpread = other.spread_radius.0;
|
self.mSpread = other.spread_radius.0;
|
||||||
self.mInset = other.inset;
|
self.mInset = other.inset;
|
||||||
self.mColor = match other.color {
|
if other.color.is_currentcolor() {
|
||||||
Color::RGBA(rgba) => {
|
|
||||||
self.mHasColor = true;
|
|
||||||
convert_rgba_to_nscolor(&rgba)
|
|
||||||
},
|
|
||||||
// TODO handle currentColor
|
// TODO handle currentColor
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=760345
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=760345
|
||||||
Color::CurrentColor => 0,
|
self.mHasColor = false;
|
||||||
|
self.mColor = 0;
|
||||||
|
} else {
|
||||||
|
self.mHasColor = true;
|
||||||
|
self.mColor = convert_rgba_to_nscolor(&other.color.color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +36,7 @@ impl nsCSSShadowItem {
|
||||||
blur_radius: Au(self.mRadius),
|
blur_radius: Au(self.mRadius),
|
||||||
spread_radius: Au(self.mSpread),
|
spread_radius: Au(self.mSpread),
|
||||||
inset: self.mInset,
|
inset: self.mInset,
|
||||||
color: Color::RGBA(convert_nscolor_to_rgba(self.mColor)),
|
color: Color::rgba(convert_nscolor_to_rgba(self.mColor)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
//! Rust helpers to interact with Gecko's StyleComplexColor.
|
//! Rust helpers to interact with Gecko's StyleComplexColor.
|
||||||
|
|
||||||
use cssparser;
|
|
||||||
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
||||||
use gecko_bindings::structs::{nscolor, StyleComplexColor};
|
use gecko_bindings::structs::{nscolor, StyleComplexColor};
|
||||||
use values;
|
use values::{Auto, Either};
|
||||||
|
use values::computed::Color as ComputedColor;
|
||||||
|
|
||||||
impl From<nscolor> for StyleComplexColor {
|
impl From<nscolor> for StyleComplexColor {
|
||||||
fn from(other: nscolor) -> Self {
|
fn from(other: nscolor) -> Self {
|
||||||
|
@ -39,40 +39,41 @@ impl StyleComplexColor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<cssparser::Color> for StyleComplexColor {
|
impl From<ComputedColor> for StyleComplexColor {
|
||||||
fn from(other: cssparser::Color) -> Self {
|
fn from(other: ComputedColor) -> Self {
|
||||||
use cssparser::Color;
|
StyleComplexColor {
|
||||||
|
mColor: convert_rgba_to_nscolor(&other.color).into(),
|
||||||
match other {
|
mForegroundRatio: other.foreground_ratio,
|
||||||
Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba).into(),
|
mIsAuto: false,
|
||||||
Color::CurrentColor => StyleComplexColor::current_color(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StyleComplexColor> for values::computed::ColorOrAuto {
|
impl From<StyleComplexColor> for ComputedColor {
|
||||||
fn from(color: StyleComplexColor) -> Self {
|
|
||||||
use values::{Auto, Either};
|
|
||||||
|
|
||||||
if color.mIsAuto {
|
|
||||||
return Either::Second(Auto);
|
|
||||||
}
|
|
||||||
|
|
||||||
Either::First(color.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<StyleComplexColor> for cssparser::Color {
|
|
||||||
fn from(other: StyleComplexColor) -> Self {
|
fn from(other: StyleComplexColor) -> Self {
|
||||||
use cssparser::Color;
|
debug_assert!(!other.mIsAuto);
|
||||||
|
ComputedColor {
|
||||||
if other.mForegroundRatio == 0 {
|
color: convert_nscolor_to_rgba(other.mColor),
|
||||||
Color::RGBA(convert_nscolor_to_rgba(other.mColor))
|
foreground_ratio: other.mForegroundRatio,
|
||||||
} else if other.mForegroundRatio == 255 {
|
}
|
||||||
Color::CurrentColor
|
}
|
||||||
} else {
|
}
|
||||||
// FIXME #13546 handle interpolation values
|
|
||||||
Color::CurrentColor
|
impl From<Either<ComputedColor, Auto>> for StyleComplexColor {
|
||||||
|
fn from(other: Either<ComputedColor, Auto>) -> Self {
|
||||||
|
match other {
|
||||||
|
Either::First(color) => color.into(),
|
||||||
|
Either::Second(_auto) => StyleComplexColor::auto(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<StyleComplexColor> for Either<ComputedColor, Auto> {
|
||||||
|
fn from(other: StyleComplexColor) -> Self {
|
||||||
|
if !other.mIsAuto {
|
||||||
|
Either::First(other.into())
|
||||||
|
} else {
|
||||||
|
Either::Second(Auto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ class Longhand(object):
|
||||||
def __init__(self, style_struct, name, spec=None, animation_value_type=None, derived_from=None, keyword=None,
|
def __init__(self, style_struct, name, spec=None, animation_value_type=None, derived_from=None, keyword=None,
|
||||||
predefined_type=None, custom_cascade=False, experimental=False, internal=False,
|
predefined_type=None, custom_cascade=False, experimental=False, internal=False,
|
||||||
need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False,
|
need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False,
|
||||||
allowed_in_keyframe_block=True, complex_color=False, cast_type='u8',
|
allowed_in_keyframe_block=True, cast_type='u8',
|
||||||
has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False,
|
has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False,
|
||||||
flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False,
|
flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False,
|
||||||
vector=False):
|
vector=False):
|
||||||
|
@ -169,7 +169,6 @@ class Longhand(object):
|
||||||
self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
|
self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
|
||||||
self.depend_on_viewport_size = depend_on_viewport_size
|
self.depend_on_viewport_size = depend_on_viewport_size
|
||||||
self.derived_from = (derived_from or "").split()
|
self.derived_from = (derived_from or "").split()
|
||||||
self.complex_color = complex_color
|
|
||||||
self.cast_type = cast_type
|
self.cast_type = cast_type
|
||||||
self.logical = arg_to_bool(logical)
|
self.logical = arg_to_bool(logical)
|
||||||
self.alias = alias.split() if alias else []
|
self.alias = alias.split() if alias else []
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::Color;
|
|
||||||
use custom_properties::ComputedValuesMap;
|
use custom_properties::ComputedValuesMap;
|
||||||
use gecko_bindings::bindings;
|
use gecko_bindings::bindings;
|
||||||
% for style_struct in data.style_structs:
|
% for style_struct in data.style_structs:
|
||||||
|
@ -43,7 +42,7 @@ use gecko_bindings::bindings::Gecko_SetNullImageValue;
|
||||||
use gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
|
use gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
|
||||||
use gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom};
|
use gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom};
|
||||||
use gecko_bindings::bindings::RawGeckoPresContextBorrowed;
|
use gecko_bindings::bindings::RawGeckoPresContextBorrowed;
|
||||||
use gecko_bindings::structs::{self, StyleComplexColor};
|
use gecko_bindings::structs;
|
||||||
use gecko_bindings::structs::nsCSSPropertyID;
|
use gecko_bindings::structs::nsCSSPropertyID;
|
||||||
use gecko_bindings::structs::nsStyleVariables;
|
use gecko_bindings::structs::nsStyleVariables;
|
||||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
|
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
|
||||||
|
@ -316,32 +315,15 @@ def set_gecko_property(ffi_name, expr):
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
/// Convert a Servo color into an nscolor; with currentColor as 0
|
<%def name="impl_color_setter(ident, gecko_ffi_name)">
|
||||||
///
|
|
||||||
/// 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(unreachable_code)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||||
% if complex_color:
|
${set_gecko_property(gecko_ffi_name, "v.into()")}
|
||||||
let result = v.into();
|
|
||||||
% else:
|
|
||||||
let result = color_to_nscolor_zero_currentcolor(v);
|
|
||||||
% endif
|
|
||||||
${set_gecko_property(gecko_ffi_name, "result")}
|
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_color_copy(ident, gecko_ffi_name, complex_color=True)">
|
<%def name="impl_color_copy(ident, gecko_ffi_name)">
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||||
let color = ${get_gecko_property(gecko_ffi_name, self_param = "other")};
|
let color = ${get_gecko_property(gecko_ffi_name, self_param = "other")};
|
||||||
|
@ -349,14 +331,10 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_color_clone(ident, gecko_ffi_name, complex_color=True)">
|
<%def name="impl_color_clone(ident, gecko_ffi_name)">
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||||
% if complex_color:
|
${get_gecko_property(gecko_ffi_name)}.into()
|
||||||
${get_gecko_property(gecko_ffi_name)}.into()
|
|
||||||
% else:
|
|
||||||
Color::RGBA(convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)}))
|
|
||||||
% endif
|
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -408,15 +386,29 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_color(ident, gecko_ffi_name, need_clone=False, complex_color=True)">
|
<%def name="impl_color(ident, gecko_ffi_name, need_clone=False)">
|
||||||
<%call expr="impl_color_setter(ident, gecko_ffi_name, complex_color)"></%call>
|
<%call expr="impl_color_setter(ident, gecko_ffi_name)"></%call>
|
||||||
<%call expr="impl_color_copy(ident, gecko_ffi_name, complex_color)"></%call>
|
<%call expr="impl_color_copy(ident, gecko_ffi_name)"></%call>
|
||||||
% if need_clone:
|
% if need_clone:
|
||||||
<%call expr="impl_color_clone(ident, gecko_ffi_name, complex_color)"></%call>
|
<%call expr="impl_color_clone(ident, gecko_ffi_name)"></%call>
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False, complex_color=True)">
|
<%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)">
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) {
|
pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) {
|
||||||
use values::generics::SVGPaintKind;
|
use values::generics::SVGPaintKind;
|
||||||
|
@ -444,14 +436,14 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
|
||||||
SVGPaintKind::Color(color) => {
|
SVGPaintKind::Color(color) => {
|
||||||
paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color;
|
paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color;
|
||||||
unsafe {
|
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 {
|
if let Some(fallback) = fallback {
|
||||||
paint.mFallbackType = nsStyleSVGFallbackType::eStyleSVGFallbackType_Color;
|
paint.mFallbackType = nsStyleSVGFallbackType::eStyleSVGFallbackType_Color;
|
||||||
paint.mFallbackColor = color_to_nscolor_zero_currentcolor(fallback);
|
paint.mFallbackColor = convert_rgba_to_nscolor(&fallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +464,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
|
||||||
use self::structs::nsStyleSVGFallbackType;
|
use self::structs::nsStyleSVGFallbackType;
|
||||||
let ref paint = ${get_gecko_property(gecko_ffi_name)};
|
let ref paint = ${get_gecko_property(gecko_ffi_name)};
|
||||||
let fallback = if let nsStyleSVGFallbackType::eStyleSVGFallbackType_Color = paint.mFallbackType {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -485,7 +477,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
|
||||||
SVGPaintKind::None
|
SVGPaintKind::None
|
||||||
}
|
}
|
||||||
nsStyleSVGPaintType::eStyleSVGPaintType_Color => {
|
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 {
|
SVGPaint {
|
||||||
|
@ -716,7 +708,8 @@ impl Debug for ${style_struct.gecko_struct_name} {
|
||||||
"Number": impl_simple,
|
"Number": impl_simple,
|
||||||
"Integer": impl_simple,
|
"Integer": impl_simple,
|
||||||
"Opacity": impl_simple,
|
"Opacity": impl_simple,
|
||||||
"CSSColor": impl_color,
|
"Color": impl_color,
|
||||||
|
"RGBAColor": impl_rgba_color,
|
||||||
"SVGPaint": impl_svg_paint,
|
"SVGPaint": impl_svg_paint,
|
||||||
"UrlOrNone": impl_css_url,
|
"UrlOrNone": impl_css_url,
|
||||||
}
|
}
|
||||||
|
@ -736,8 +729,6 @@ impl Debug for ${style_struct.gecko_struct_name} {
|
||||||
args.update(cast_type=longhand.cast_type)
|
args.update(cast_type=longhand.cast_type)
|
||||||
else:
|
else:
|
||||||
method = predefined_types[longhand.predefined_type]
|
method = predefined_types[longhand.predefined_type]
|
||||||
if longhand.predefined_type in ["CSSColor"]:
|
|
||||||
args.update(complex_color=longhand.complex_color)
|
|
||||||
|
|
||||||
method(**args)
|
method(**args)
|
||||||
|
|
||||||
|
@ -948,7 +939,7 @@ fn static_assert() {
|
||||||
structs::Side::eSide${to_camel_case(side.ident)});
|
structs::Side::eSide${to_camel_case(side.ident)});
|
||||||
}
|
}
|
||||||
for color in colors {
|
for color in colors {
|
||||||
let c = color_to_nscolor_zero_currentcolor(*color);
|
let c = convert_rgba_to_nscolor(color);
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_AppendMozBorderColors(&mut self.gecko,
|
bindings::Gecko_AppendMozBorderColors(&mut self.gecko,
|
||||||
structs::Side::eSide${to_camel_case(side.ident)},
|
structs::Side::eSide${to_camel_case(side.ident)},
|
||||||
|
@ -4268,25 +4259,7 @@ clip-path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_caret_color(&mut self, v: longhands::caret_color::computed_value::T){
|
<%call expr="impl_color('caret_color', 'mCaretColor', need_clone=True)"></%call>
|
||||||
use values::Either;
|
|
||||||
|
|
||||||
match v {
|
|
||||||
Either::First(color) => {
|
|
||||||
self.gecko.mCaretColor = StyleComplexColor::from(color);
|
|
||||||
}
|
|
||||||
Either::Second(_auto) => {
|
|
||||||
self.gecko.mCaretColor = StyleComplexColor::auto();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy_caret_color_from(&mut self, other: &Self){
|
|
||||||
self.gecko.mCaretColor = other.gecko.mCaretColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
<%call expr="impl_color_clone('caret_color', 'mCaretColor')"></%call>
|
|
||||||
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="Column"
|
<%self:impl_trait style_struct_name="Column"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<% from data import SYSTEM_FONT_LONGHANDS %>
|
<% from data import SYSTEM_FONT_LONGHANDS %>
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{Color as CSSParserColor, Parser, RGBA, serialize_identifier};
|
use cssparser::{Parser, RGBA, serialize_identifier};
|
||||||
use euclid::{Point2D, Size2D};
|
use euclid::{Point2D, Size2D};
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::bindings::RawServoAnimationValueMap;
|
#[cfg(feature = "gecko")] use gecko_bindings::bindings::RawServoAnimationValueMap;
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::structs::RawGeckoGfxMatrix4x4;
|
#[cfg(feature = "gecko")] use gecko_bindings::structs::RawGeckoGfxMatrix4x4;
|
||||||
|
@ -38,7 +38,7 @@ use values::CSSFloat;
|
||||||
use values::{Auto, Either};
|
use values::{Auto, Either};
|
||||||
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
||||||
use values::computed::{BorderCornerRadius, ClipRect};
|
use values::computed::{BorderCornerRadius, ClipRect};
|
||||||
use values::computed::{CalcLengthOrPercentage, Context, ComputedValueAsSpecified};
|
use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified};
|
||||||
use values::computed::{LengthOrPercentage, MaxLength, MozLength, Shadow, ToComputedValue};
|
use values::computed::{LengthOrPercentage, MaxLength, MozLength, Shadow, ToComputedValue};
|
||||||
use values::generics::{SVGPaint, SVGPaintKind};
|
use values::generics::{SVGPaint, SVGPaintKind};
|
||||||
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
||||||
|
@ -2721,38 +2721,19 @@ impl Animatable for IntermediateRGBA {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Either<CSSParserColor, Auto>> for Either<IntermediateColor, Auto> {
|
impl From<Either<Color, Auto>> for Either<IntermediateColor, Auto> {
|
||||||
fn from(from: Either<CSSParserColor, Auto>) -> Either<IntermediateColor, Auto> {
|
fn from(from: Either<Color, Auto>) -> Either<IntermediateColor, Auto> {
|
||||||
match from {
|
match from {
|
||||||
Either::First(from) =>
|
Either::First(from) => Either::First(from.into()),
|
||||||
match from {
|
|
||||||
CSSParserColor::RGBA(color) =>
|
|
||||||
Either::First(IntermediateColor::IntermediateRGBA(
|
|
||||||
IntermediateRGBA::new(color.red_f32(),
|
|
||||||
color.green_f32(),
|
|
||||||
color.blue_f32(),
|
|
||||||
color.alpha_f32()))),
|
|
||||||
CSSParserColor::CurrentColor =>
|
|
||||||
Either::First(IntermediateColor::CurrentColor),
|
|
||||||
},
|
|
||||||
Either::Second(Auto) => Either::Second(Auto),
|
Either::Second(Auto) => Either::Second(Auto),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Either<IntermediateColor, Auto>> for Either<CSSParserColor, Auto> {
|
impl From<Either<IntermediateColor, Auto>> for Either<Color, Auto> {
|
||||||
fn from(from: Either<IntermediateColor, Auto>) -> Either<CSSParserColor, Auto> {
|
fn from(from: Either<IntermediateColor, Auto>) -> Either<Color, Auto> {
|
||||||
match from {
|
match from {
|
||||||
Either::First(from) =>
|
Either::First(from) => Either::First(from.into()),
|
||||||
match from {
|
|
||||||
IntermediateColor::IntermediateRGBA(color) =>
|
|
||||||
Either::First(CSSParserColor::RGBA(RGBA::from_floats(color.red,
|
|
||||||
color.green,
|
|
||||||
color.blue,
|
|
||||||
color.alpha))),
|
|
||||||
IntermediateColor::CurrentColor =>
|
|
||||||
Either::First(CSSParserColor::CurrentColor),
|
|
||||||
},
|
|
||||||
Either::Second(Auto) => Either::Second(Auto),
|
Either::Second(Auto) => Either::Second(Auto),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2761,22 +2742,89 @@ impl From<Either<IntermediateColor, Auto>> for Either<CSSParserColor, Auto> {
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub enum IntermediateColor {
|
pub struct IntermediateColor {
|
||||||
CurrentColor,
|
color: IntermediateRGBA,
|
||||||
IntermediateRGBA(IntermediateRGBA),
|
foreground_ratio: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntermediateColor {
|
||||||
|
fn currentcolor() -> Self {
|
||||||
|
IntermediateColor {
|
||||||
|
color: IntermediateRGBA::transparent(),
|
||||||
|
foreground_ratio: 1.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transparent() -> Self {
|
||||||
|
IntermediateColor {
|
||||||
|
color: IntermediateRGBA::transparent(),
|
||||||
|
foreground_ratio: 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_currentcolor(&self) -> bool {
|
||||||
|
self.foreground_ratio >= 1.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_numeric(&self) -> bool {
|
||||||
|
self.foreground_ratio <= 0.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn effective_intermediate_rgba(&self) -> IntermediateRGBA {
|
||||||
|
IntermediateRGBA {
|
||||||
|
alpha: self.color.alpha * (1. - self.foreground_ratio),
|
||||||
|
.. self.color
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Animatable for IntermediateColor {
|
impl Animatable for IntermediateColor {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||||
match (*self, *other) {
|
// Common cases are interpolating between two numeric colors,
|
||||||
(IntermediateColor::IntermediateRGBA(ref this),
|
// two currentcolors, and a numeric color and a currentcolor.
|
||||||
IntermediateColor::IntermediateRGBA(ref other)) => {
|
//
|
||||||
this.add_weighted(other, self_portion, other_portion)
|
// Note: this algorithm assumes self_portion + other_portion
|
||||||
.map(IntermediateColor::IntermediateRGBA)
|
// 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.
|
||||||
|
if self.foreground_ratio == other.foreground_ratio {
|
||||||
|
if self.is_currentcolor() {
|
||||||
|
Ok(IntermediateColor::currentcolor())
|
||||||
|
} else {
|
||||||
|
Ok(IntermediateColor {
|
||||||
|
color: self.color.add_weighted(&other.color, self_portion, other_portion)?,
|
||||||
|
foreground_ratio: self.foreground_ratio,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
// FIXME: Bug 1345709: Implement currentColor animations.
|
} else if self.is_currentcolor() && other.is_numeric() {
|
||||||
_ => Err(()),
|
Ok(IntermediateColor {
|
||||||
|
color: other.color,
|
||||||
|
foreground_ratio: self_portion as f32,
|
||||||
|
})
|
||||||
|
} else if self.is_numeric() && other.is_currentcolor() {
|
||||||
|
Ok(IntermediateColor {
|
||||||
|
color: self.color,
|
||||||
|
foreground_ratio: other_portion 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.add_weighted(&other_color, self_portion, other_portion)?;
|
||||||
|
// Then we compute the final foreground ratio, and derive
|
||||||
|
// the final alpha value from the effective alpha value.
|
||||||
|
let foreground_ratio = self.foreground_ratio
|
||||||
|
.add_weighted(&other.foreground_ratio, self_portion, other_portion)?;
|
||||||
|
let alpha = color.alpha / (1. - foreground_ratio);
|
||||||
|
Ok(IntermediateColor {
|
||||||
|
color: IntermediateRGBA {
|
||||||
|
alpha: alpha,
|
||||||
|
.. color
|
||||||
|
},
|
||||||
|
foreground_ratio: foreground_ratio,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2787,45 +2835,49 @@ impl Animatable for IntermediateColor {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
|
||||||
match (*self, *other) {
|
// All comments in add_weighted also applies here.
|
||||||
(IntermediateColor::IntermediateRGBA(ref this), IntermediateColor::IntermediateRGBA(ref other)) => {
|
if self.foreground_ratio == other.foreground_ratio {
|
||||||
this.compute_squared_distance(other)
|
if self.is_currentcolor() {
|
||||||
},
|
Ok(0.)
|
||||||
_ => Ok(0.0),
|
} else {
|
||||||
|
self.color.compute_squared_distance(&other.color)
|
||||||
|
}
|
||||||
|
} else if self.is_currentcolor() && other.is_numeric() {
|
||||||
|
Ok(IntermediateRGBA::transparent().compute_squared_distance(&other.color)? + 1.)
|
||||||
|
} else if self.is_numeric() && other.is_currentcolor() {
|
||||||
|
Ok(self.color.compute_squared_distance(&IntermediateRGBA::transparent())? + 1.)
|
||||||
|
} else {
|
||||||
|
let self_color = self.effective_intermediate_rgba();
|
||||||
|
let other_color = other.effective_intermediate_rgba();
|
||||||
|
let dist = self_color.compute_squared_distance(&other_color)?;
|
||||||
|
let ratio_diff = (self.foreground_ratio - other.foreground_ratio) as f64;
|
||||||
|
Ok(dist + ratio_diff * ratio_diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CSSParserColor> for IntermediateColor {
|
impl From<Color> for IntermediateColor {
|
||||||
fn from(color: CSSParserColor) -> IntermediateColor {
|
fn from(color: Color) -> IntermediateColor {
|
||||||
match color {
|
IntermediateColor {
|
||||||
CSSParserColor::RGBA(color) =>
|
color: color.color.into(),
|
||||||
IntermediateColor::IntermediateRGBA(IntermediateRGBA::new(color.red_f32(),
|
foreground_ratio: color.foreground_ratio as f32 * (1. / 255.),
|
||||||
color.green_f32(),
|
|
||||||
color.blue_f32(),
|
|
||||||
color.alpha_f32())),
|
|
||||||
CSSParserColor::CurrentColor => IntermediateColor::CurrentColor,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IntermediateColor> for CSSParserColor {
|
impl From<IntermediateColor> for Color {
|
||||||
fn from(color: IntermediateColor) -> CSSParserColor {
|
fn from(color: IntermediateColor) -> Color {
|
||||||
match color {
|
Color {
|
||||||
IntermediateColor::IntermediateRGBA(color) =>
|
color: color.color.into(),
|
||||||
CSSParserColor::RGBA(RGBA::from_floats(color.red,
|
foreground_ratio: (color.foreground_ratio * 255.).round() as u8,
|
||||||
color.green,
|
|
||||||
color.blue,
|
|
||||||
color.alpha)),
|
|
||||||
IntermediateColor::CurrentColor => CSSParserColor::CurrentColor,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Animatable SVGPaint
|
/// Animatable SVGPaint
|
||||||
pub type IntermediateSVGPaint = SVGPaint<IntermediateColor>;
|
pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA>;
|
||||||
/// Animatable SVGPaintKind
|
/// Animatable SVGPaintKind
|
||||||
pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateColor>;
|
pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateRGBA>;
|
||||||
|
|
||||||
impl From<::values::computed::SVGPaint> for IntermediateSVGPaint {
|
impl From<::values::computed::SVGPaint> for IntermediateSVGPaint {
|
||||||
fn from(paint: ::values::computed::SVGPaint) -> IntermediateSVGPaint {
|
fn from(paint: ::values::computed::SVGPaint) -> IntermediateSVGPaint {
|
||||||
|
@ -3024,7 +3076,7 @@ impl Animatable for IntermediateShadowList {
|
||||||
offset_y: Au(0),
|
offset_y: Au(0),
|
||||||
blur_radius: Au(0),
|
blur_radius: Au(0),
|
||||||
spread_radius: Au(0),
|
spread_radius: Au(0),
|
||||||
color: IntermediateColor::IntermediateRGBA(IntermediateRGBA::transparent()),
|
color: IntermediateColor::transparent(),
|
||||||
inset: false,
|
inset: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,11 @@
|
||||||
|
|
||||||
<% data.new_style_struct("Background", inherited=False) %>
|
<% data.new_style_struct("Background", inherited=False) %>
|
||||||
|
|
||||||
${helpers.predefined_type("background-color", "CSSColor",
|
${helpers.predefined_type("background-color", "Color",
|
||||||
"::cssparser::Color::RGBA(::cssparser::RGBA::transparent())",
|
"computed_value::T::transparent()",
|
||||||
initial_specified_value="SpecifiedValue::transparent()",
|
initial_specified_value="SpecifiedValue::transparent()",
|
||||||
spec="https://drafts.csswg.org/css-backgrounds/#background-color",
|
spec="https://drafts.csswg.org/css-backgrounds/#background-color",
|
||||||
animation_value_type="IntermediateColor",
|
animation_value_type="IntermediateColor",
|
||||||
complex_color=True,
|
|
||||||
ignored_when_colors_disabled=True,
|
ignored_when_colors_disabled=True,
|
||||||
allow_quirks=True)}
|
allow_quirks=True)}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
return "https://drafts.csswg.org/css-backgrounds/#border-%s-%s" % (side[0], kind)
|
return "https://drafts.csswg.org/css-backgrounds/#border-%s-%s" % (side[0], kind)
|
||||||
%>
|
%>
|
||||||
% for side in ALL_SIDES:
|
% for side in ALL_SIDES:
|
||||||
${helpers.predefined_type("border-%s-color" % side[0], "CSSColor",
|
${helpers.predefined_type("border-%s-color" % side[0], "Color",
|
||||||
"::cssparser::Color::CurrentColor",
|
"computed_value::T::currentcolor()",
|
||||||
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-color"),
|
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-color"),
|
||||||
spec=maybe_logical_spec(side, "color"),
|
spec=maybe_logical_spec(side, "color"),
|
||||||
animation_value_type="IntermediateColor",
|
animation_value_type="IntermediateColor",
|
||||||
|
@ -66,21 +66,21 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
|
||||||
ignored_when_colors_disabled="True">
|
ignored_when_colors_disabled="True">
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::specified::CSSColor;
|
use values::specified::RGBAColor;
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use values::computed::CSSColor;
|
use cssparser::RGBA;
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct T(pub Option<Vec<CSSColor>>);
|
pub struct T(pub Option<Vec<RGBA>>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum SpecifiedValue {
|
pub enum SpecifiedValue {
|
||||||
None,
|
None,
|
||||||
Colors(Vec<CSSColor>),
|
Colors(Vec<RGBAColor>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for computed_value::T {
|
impl ToCss for computed_value::T {
|
||||||
|
@ -168,7 +168,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = Vec::new();
|
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);
|
result.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,25 +13,26 @@
|
||||||
ignored_when_colors_disabled="True"
|
ignored_when_colors_disabled="True"
|
||||||
spec="https://drafts.csswg.org/css-color/#color">
|
spec="https://drafts.csswg.org/css-color/#color">
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use values::specified::{AllowQuirks, Color, CSSColor};
|
use values::specified::{AllowQuirks, Color};
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
type ComputedValue = computed_value::T;
|
type ComputedValue = computed_value::T;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
self.0.parsed.to_computed_value(context)
|
self.0.to_computed_value(context)
|
||||||
|
.to_rgba(context.inherited_style.get_color().clone_color())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||||
SpecifiedValue(Color::RGBA(*computed).into())
|
SpecifiedValue(Color::rgba(*computed).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Debug, PartialEq, ToCss)]
|
#[derive(Clone, Debug, PartialEq, ToCss)]
|
||||||
pub struct SpecifiedValue(pub CSSColor);
|
pub struct SpecifiedValue(pub Color);
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
RGBA::new(0, 0, 0, 255) // black
|
RGBA::new(0, 0, 0, 255) // black
|
||||||
}
|
}
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
CSSColor::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
|
Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(#15973): Add servo support for system colors
|
// FIXME(#15973): Add servo support for system colors
|
||||||
|
|
|
@ -51,12 +51,11 @@ ${helpers.predefined_type("column-rule-width",
|
||||||
extra_prefixes="moz")}
|
extra_prefixes="moz")}
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-multicol-1/#crc
|
// https://drafts.csswg.org/css-multicol-1/#crc
|
||||||
${helpers.predefined_type("column-rule-color", "CSSColor",
|
${helpers.predefined_type("column-rule-color", "Color",
|
||||||
"::cssparser::Color::CurrentColor",
|
"computed_value::T::currentcolor()",
|
||||||
initial_specified_value="specified::CSSColor::currentcolor()",
|
initial_specified_value="specified::Color::currentcolor()",
|
||||||
products="gecko", animation_value_type="IntermediateColor", extra_prefixes="moz",
|
products="gecko", animation_value_type="IntermediateColor", extra_prefixes="moz",
|
||||||
complex_color=True, need_clone=True,
|
need_clone=True, ignored_when_colors_disabled=True,
|
||||||
ignored_when_colors_disabled=True,
|
|
||||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")}
|
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")}
|
||||||
|
|
||||||
${helpers.single_keyword("column-span", "none all",
|
${helpers.single_keyword("column-span", "none all",
|
||||||
|
|
|
@ -685,12 +685,11 @@ ${helpers.predefined_type("word-spacing",
|
||||||
% endif
|
% endif
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
${helpers.predefined_type("text-emphasis-color", "CSSColor",
|
${helpers.predefined_type("text-emphasis-color", "Color",
|
||||||
"::cssparser::Color::CurrentColor",
|
"computed_value::T::currentcolor()",
|
||||||
initial_specified_value="specified::CSSColor::currentcolor()",
|
initial_specified_value="specified::Color::currentcolor()",
|
||||||
products="gecko", animation_value_type="IntermediateColor",
|
products="gecko", animation_value_type="IntermediateColor",
|
||||||
complex_color=True, need_clone=True,
|
need_clone=True, ignored_when_colors_disabled=True,
|
||||||
ignored_when_colors_disabled=True,
|
|
||||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-color")}
|
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-color")}
|
||||||
|
|
||||||
|
|
||||||
|
@ -705,20 +704,18 @@ ${helpers.predefined_type(
|
||||||
// CSS Compatibility
|
// CSS Compatibility
|
||||||
// https://compat.spec.whatwg.org
|
// https://compat.spec.whatwg.org
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"-webkit-text-fill-color", "CSSColor",
|
"-webkit-text-fill-color", "Color",
|
||||||
"CSSParserColor::CurrentColor",
|
"computed_value::T::currentcolor()",
|
||||||
products="gecko", animation_value_type="IntermediateColor",
|
products="gecko", animation_value_type="IntermediateColor",
|
||||||
complex_color=True, need_clone=True,
|
need_clone=True, ignored_when_colors_disabled=True,
|
||||||
ignored_when_colors_disabled=True,
|
|
||||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")}
|
spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")}
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"-webkit-text-stroke-color", "CSSColor",
|
"-webkit-text-stroke-color", "Color",
|
||||||
"CSSParserColor::CurrentColor",
|
"computed_value::T::currentcolor()",
|
||||||
initial_specified_value="specified::CSSColor::currentcolor()",
|
initial_specified_value="specified::Color::currentcolor()",
|
||||||
products="gecko", animation_value_type="IntermediateColor",
|
products="gecko", animation_value_type="IntermediateColor",
|
||||||
complex_color=True, need_clone=True,
|
need_clone=True, ignored_when_colors_disabled=True,
|
||||||
ignored_when_colors_disabled=True,
|
|
||||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")}
|
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")}
|
||||||
|
|
||||||
${helpers.predefined_type("-webkit-text-stroke-width",
|
${helpers.predefined_type("-webkit-text-stroke-width",
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
additional_methods=[Method("outline_has_nonzero_width", "bool")]) %>
|
additional_methods=[Method("outline_has_nonzero_width", "bool")]) %>
|
||||||
|
|
||||||
// TODO(pcwalton): `invert`
|
// TODO(pcwalton): `invert`
|
||||||
${helpers.predefined_type("outline-color", "CSSColor", "computed::CSSColor::CurrentColor",
|
${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentcolor()",
|
||||||
initial_specified_value="specified::CSSColor::currentcolor()",
|
initial_specified_value="specified::Color::currentcolor()",
|
||||||
animation_value_type="IntermediateColor", complex_color=True, need_clone=True,
|
animation_value_type="IntermediateColor", need_clone=True,
|
||||||
ignored_when_colors_disabled=True,
|
ignored_when_colors_disabled=True,
|
||||||
spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")}
|
spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ ${helpers.single_keyword("vector-effect", "none non-scaling-stroke",
|
||||||
// Section 13 - Gradients and Patterns
|
// Section 13 - Gradients and Patterns
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"stop-color", "CSSColor",
|
"stop-color", "RGBAColor",
|
||||||
"CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))",
|
"RGBA::new(0, 0, 0, 255)",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
animation_value_type="none",
|
animation_value_type="none",
|
||||||
spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty")}
|
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
|
// Section 15 - Filter Effects
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"flood-color", "CSSColor",
|
"flood-color", "RGBAColor",
|
||||||
"CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))",
|
"RGBA::new(0, 0, 0, 255)",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
animation_value_type="none",
|
animation_value_type="none",
|
||||||
spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty")}
|
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")}
|
spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty")}
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"lighting-color", "CSSColor",
|
"lighting-color", "RGBAColor",
|
||||||
"CSSParserColor::RGBA(RGBA::new(255, 255, 255, 255))",
|
"RGBA::new(255, 255, 255, 255)",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
animation_value_type="none",
|
animation_value_type="none",
|
||||||
spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")}
|
spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")}
|
||||||
|
|
|
@ -278,10 +278,9 @@ ${helpers.single_keyword("text-decoration-style",
|
||||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")}
|
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")}
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"text-decoration-color", "CSSColor",
|
"text-decoration-color", "Color",
|
||||||
"computed::CSSColor::CurrentColor",
|
"computed_value::T::currentcolor()",
|
||||||
initial_specified_value="specified::CSSColor::currentcolor()",
|
initial_specified_value="specified::Color::currentcolor()",
|
||||||
complex_color=True,
|
|
||||||
products="gecko",
|
products="gecko",
|
||||||
animation_value_type="IntermediateColor",
|
animation_value_type="IntermediateColor",
|
||||||
ignored_when_colors_disabled=True,
|
ignored_when_colors_disabled=True,
|
||||||
|
|
|
@ -18,7 +18,7 @@ use std::ops::Deref;
|
||||||
use stylearc::{Arc, UniqueArc};
|
use stylearc::{Arc, UniqueArc};
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
#[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA};
|
#[cfg(feature = "servo")] use cssparser::RGBA;
|
||||||
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
|
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
|
||||||
use error_reporting::ParseErrorReporter;
|
use error_reporting::ParseErrorReporter;
|
||||||
#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
|
#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
|
||||||
|
@ -40,7 +40,6 @@ use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraDat
|
||||||
#[cfg(feature = "servo")] use values::Either;
|
#[cfg(feature = "servo")] use values::Either;
|
||||||
use values::generics::text::LineHeight;
|
use values::generics::text::LineHeight;
|
||||||
use values::computed;
|
use values::computed;
|
||||||
use values::specified::Color;
|
|
||||||
use cascade_info::CascadeInfo;
|
use cascade_info::CascadeInfo;
|
||||||
use rule_tree::{CascadeLevel, StrongRuleNode};
|
use rule_tree::{CascadeLevel, StrongRuleNode};
|
||||||
use style_adjuster::StyleAdjuster;
|
use style_adjuster::StyleAdjuster;
|
||||||
|
@ -1938,11 +1937,8 @@ impl ComputedValues {
|
||||||
/// Usage example:
|
/// Usage example:
|
||||||
/// let top_color = style.resolve_color(style.Border.border_top_color);
|
/// let top_color = style.resolve_color(style.Border.border_top_color);
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resolve_color(&self, color: CSSParserColor) -> RGBA {
|
pub fn resolve_color(&self, color: computed::Color) -> RGBA {
|
||||||
match color {
|
color.to_rgba(self.get_color().color)
|
||||||
CSSParserColor::RGBA(rgba) => rgba,
|
|
||||||
CSSParserColor::CurrentColor => self.get_color().color,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the logical computed inline size.
|
/// Get the logical computed inline size.
|
||||||
|
@ -2626,7 +2622,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
||||||
let ignore_colors = !device.use_document_colors();
|
let ignore_colors = !device.use_document_colors();
|
||||||
let default_background_color_decl = if ignore_colors {
|
let default_background_color_decl = if ignore_colors {
|
||||||
let color = device.default_background_color();
|
let color = device.default_background_color();
|
||||||
Some(PropertyDeclaration::BackgroundColor(Color::RGBA(color).into()))
|
Some(PropertyDeclaration::BackgroundColor(color.into()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
use properties::longhands::background_clip;
|
use properties::longhands::background_clip;
|
||||||
use properties::longhands::background_clip::single_value::computed_value::T as Clip;
|
use properties::longhands::background_clip::single_value::computed_value::T as Clip;
|
||||||
use properties::longhands::background_origin::single_value::computed_value::T as Origin;
|
use properties::longhands::background_origin::single_value::computed_value::T as Origin;
|
||||||
use values::specified::{CSSColor, Position, PositionComponent};
|
use values::specified::{Color, Position, PositionComponent};
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
|
|
||||||
impl From<background_origin::single_value::SpecifiedValue> for background_clip::single_value::SpecifiedValue {
|
impl From<background_origin::single_value::SpecifiedValue> for background_clip::single_value::SpecifiedValue {
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
% endfor
|
% endfor
|
||||||
loop {
|
loop {
|
||||||
if background_color.is_none() {
|
if background_color.is_none() {
|
||||||
if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
|
if let Ok(value) = input.try(|i| Color::parse(context, i)) {
|
||||||
background_color = Some(value);
|
background_color = Some(value);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
background_color: background_color.unwrap_or(CSSColor::transparent()),
|
background_color: background_color.unwrap_or(Color::transparent()),
|
||||||
background_image: background_image,
|
background_image: background_image,
|
||||||
background_position_x: background_position_x,
|
background_position_x: background_position_x,
|
||||||
background_position_y: background_position_y,
|
background_position_y: background_position_y,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
<% from data import to_rust_ident, ALL_SIDES, PHYSICAL_SIDES, maybe_moz_logical_alias %>
|
<% from data import to_rust_ident, ALL_SIDES, PHYSICAL_SIDES, maybe_moz_logical_alias %>
|
||||||
|
|
||||||
${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::CSSColor::parse",
|
${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::Color::parse",
|
||||||
spec="https://drafts.csswg.org/css-backgrounds/#border-color",
|
spec="https://drafts.csswg.org/css-backgrounds/#border-color",
|
||||||
allow_quirks=True)}
|
allow_quirks=True)}
|
||||||
|
|
||||||
|
@ -44,10 +44,10 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
-> Result<(specified::CSSColor,
|
-> Result<(specified::Color,
|
||||||
specified::BorderStyle,
|
specified::BorderStyle,
|
||||||
specified::BorderSideWidth), ()> {
|
specified::BorderSideWidth), ()> {
|
||||||
use values::specified::{CSSColor, BorderStyle, BorderSideWidth};
|
use values::specified::{Color, BorderStyle, BorderSideWidth};
|
||||||
let _unused = context;
|
let _unused = context;
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
let mut style = None;
|
let mut style = None;
|
||||||
|
@ -55,7 +55,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
loop {
|
loop {
|
||||||
if color.is_none() {
|
if color.is_none() {
|
||||||
if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
|
if let Ok(value) = input.try(|i| Color::parse(context, i)) {
|
||||||
color = Some(value);
|
color = Some(value);
|
||||||
any = true;
|
any = true;
|
||||||
continue
|
continue
|
||||||
|
@ -78,7 +78,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if any {
|
if any {
|
||||||
Ok((color.unwrap_or_else(|| CSSColor::currentcolor()),
|
Ok((color.unwrap_or_else(|| Color::currentcolor()),
|
||||||
style.unwrap_or(BorderStyle::none),
|
style.unwrap_or(BorderStyle::none),
|
||||||
width.unwrap_or(BorderSideWidth::Medium)))
|
width.unwrap_or(BorderSideWidth::Medium)))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
loop {
|
loop {
|
||||||
if color.is_none() {
|
if color.is_none() {
|
||||||
if let Ok(value) = input.try(|i| specified::CSSColor::parse(context, i)) {
|
if let Ok(value) = input.try(|i| specified::Color::parse(context, i)) {
|
||||||
color = Some(value);
|
color = Some(value);
|
||||||
any = true;
|
any = true;
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -3,18 +3,18 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::specified::{BorderStyle, Color, CSSColor};
|
use values::specified::{BorderStyle, Color};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
fn serialize_directional_border<W, I,>(dest: &mut W,
|
fn serialize_directional_border<W, I,>(dest: &mut W,
|
||||||
width: &I,
|
width: &I,
|
||||||
style: &BorderStyle,
|
style: &BorderStyle,
|
||||||
color: &CSSColor)
|
color: &Color)
|
||||||
-> fmt::Result where W: fmt::Write, I: ToCss {
|
-> fmt::Result where W: fmt::Write, I: ToCss {
|
||||||
width.to_css(dest)?;
|
width.to_css(dest)?;
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
style.to_css(dest)?;
|
style.to_css(dest)?;
|
||||||
if color.parsed != Color::CurrentColor {
|
if *color != Color::CurrentColor {
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
color.to_css(dest)?;
|
color.to_css(dest)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
self.text_decoration_style.to_css(dest)?;
|
self.text_decoration_style.to_css(dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.text_decoration_color.parsed != specified::Color::CurrentColor {
|
if *self.text_decoration_color != specified::Color::CurrentColor {
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.text_decoration_color.to_css(dest)?;
|
self.text_decoration_color.to_css(dest)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -912,7 +912,6 @@ impl StrongRuleNode {
|
||||||
-> bool
|
-> bool
|
||||||
where E: ::dom::TElement
|
where E: ::dom::TElement
|
||||||
{
|
{
|
||||||
use cssparser::RGBA;
|
|
||||||
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_BACKGROUND, NS_AUTHOR_SPECIFIED_BORDER};
|
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_BACKGROUND, NS_AUTHOR_SPECIFIED_BORDER};
|
||||||
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_PADDING, NS_AUTHOR_SPECIFIED_TEXT_SHADOW};
|
use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_PADDING, NS_AUTHOR_SPECIFIED_TEXT_SHADOW};
|
||||||
use properties::{CSSWideKeyword, LonghandId, LonghandIdSet};
|
use properties::{CSSWideKeyword, LonghandId, LonghandIdSet};
|
||||||
|
@ -1083,7 +1082,7 @@ impl StrongRuleNode {
|
||||||
if properties.contains(id) {
|
if properties.contains(id) {
|
||||||
if !author_colors_allowed {
|
if !author_colors_allowed {
|
||||||
if let PropertyDeclaration::BackgroundColor(ref color) = *declaration {
|
if let PropertyDeclaration::BackgroundColor(ref color) = *declaration {
|
||||||
return color.parsed == Color::RGBA(RGBA::transparent())
|
return *color == Color::transparent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
144
components/style/values/computed/color.rs
Normal file
144
components/style/values/computed/color.rs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/* 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::{Color as CSSParserColor, RGBA};
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
|
||||||
|
/// This struct represents a combined color from a numeric color and
|
||||||
|
/// the current foreground color (currentcolor keyword).
|
||||||
|
/// Conceptually, the formula is "color * (1 - p) + currentcolor * p"
|
||||||
|
/// where p is foreground_ratio.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub struct Color {
|
||||||
|
/// RGBA color.
|
||||||
|
pub color: RGBA,
|
||||||
|
/// The ratio of currentcolor in complex color.
|
||||||
|
pub foreground_ratio: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blend_color_component(bg: u8, fg: u8, fg_alpha: u8) -> u8 {
|
||||||
|
let bg_ratio = (u8::max_value() - fg_alpha) as u32;
|
||||||
|
let fg_ratio = fg_alpha as u32;
|
||||||
|
let color = bg as u32 * bg_ratio + fg as u32 * fg_ratio;
|
||||||
|
// Rounding divide the number by 255
|
||||||
|
((color + 127) / 255) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
/// Returns a numeric color representing the given RGBA value.
|
||||||
|
pub fn rgba(rgba: RGBA) -> Color {
|
||||||
|
Color {
|
||||||
|
color: rgba,
|
||||||
|
foreground_ratio: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a complex color value representing transparent.
|
||||||
|
pub fn transparent() -> Color {
|
||||||
|
Color::rgba(RGBA::transparent())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a complex color value representing currentcolor.
|
||||||
|
pub fn currentcolor() -> Color {
|
||||||
|
Color {
|
||||||
|
color: RGBA::transparent(),
|
||||||
|
foreground_ratio: u8::max_value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether it is a numeric color (no currentcolor component).
|
||||||
|
pub fn is_numeric(&self) -> bool {
|
||||||
|
self.foreground_ratio == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether it is a currentcolor value (no numeric color component).
|
||||||
|
pub fn is_currentcolor(&self) -> bool {
|
||||||
|
self.foreground_ratio == u8::max_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Combine this complex color with the given foreground color into
|
||||||
|
/// a numeric RGBA color. It currently uses linear blending.
|
||||||
|
pub fn to_rgba(&self, fg_color: RGBA) -> RGBA {
|
||||||
|
// Common cases that the complex color is either pure numeric
|
||||||
|
// color or pure currentcolor.
|
||||||
|
if self.is_numeric() {
|
||||||
|
return self.color;
|
||||||
|
}
|
||||||
|
if self.is_currentcolor() {
|
||||||
|
return fg_color.clone();
|
||||||
|
}
|
||||||
|
// Common case that alpha channel is equal (usually both are opaque).
|
||||||
|
let fg_ratio = self.foreground_ratio;
|
||||||
|
if self.color.alpha == fg_color.alpha {
|
||||||
|
let r = blend_color_component(self.color.red, fg_color.red, fg_ratio);
|
||||||
|
let g = blend_color_component(self.color.green, fg_color.green, fg_ratio);
|
||||||
|
let b = blend_color_component(self.color.blue, fg_color.blue, fg_ratio);
|
||||||
|
return RGBA::new(r, g, b, fg_color.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the more complicated case that the alpha value differs,
|
||||||
|
// we use the following formula to compute the components:
|
||||||
|
// alpha = self_alpha * (1 - fg_ratio) + fg_alpha * fg_ratio
|
||||||
|
// color = (self_color * self_alpha * (1 - fg_ratio) +
|
||||||
|
// fg_color * fg_alpha * fg_ratio) / alpha
|
||||||
|
|
||||||
|
let p1 = (1. / 255.) * (255 - fg_ratio) as f32;
|
||||||
|
let a1 = self.color.alpha_f32();
|
||||||
|
let r1 = a1 * self.color.red_f32();
|
||||||
|
let g1 = a1 * self.color.green_f32();
|
||||||
|
let b1 = a1 * self.color.blue_f32();
|
||||||
|
|
||||||
|
let p2 = 1. - p1;
|
||||||
|
let a2 = fg_color.alpha_f32();
|
||||||
|
let r2 = a2 * fg_color.red_f32();
|
||||||
|
let g2 = a2 * fg_color.green_f32();
|
||||||
|
let b2 = a2 * fg_color.blue_f32();
|
||||||
|
|
||||||
|
let a = p1 * a1 + p2 * a2;
|
||||||
|
if a == 0.0 {
|
||||||
|
return RGBA::transparent();
|
||||||
|
}
|
||||||
|
|
||||||
|
let inverse_a = 1. / a;
|
||||||
|
let r = (p1 * r1 + p2 * r2) * inverse_a;
|
||||||
|
let g = (p1 * g1 + p2 * g2) * inverse_a;
|
||||||
|
let b = (p1 * b1 + p2 * b2) * inverse_a;
|
||||||
|
return RGBA::from_floats(r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Color {
|
||||||
|
fn eq(&self, other: &Color) -> bool {
|
||||||
|
self.foreground_ratio == other.foreground_ratio &&
|
||||||
|
(self.is_currentcolor() || self.color == other.color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RGBA> for Color {
|
||||||
|
fn from(color: RGBA) -> Color {
|
||||||
|
Color {
|
||||||
|
color: color,
|
||||||
|
foreground_ratio: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for Color {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
if self.is_numeric() {
|
||||||
|
self.color.to_css(dest)
|
||||||
|
} else if self.is_currentcolor() {
|
||||||
|
CSSParserColor::CurrentColor.to_css(dest)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computed value type for the specified RGBAColor.
|
||||||
|
pub type RGBAColor = RGBA;
|
|
@ -7,7 +7,7 @@
|
||||||
//!
|
//!
|
||||||
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
||||||
|
|
||||||
use cssparser::Color as CSSColor;
|
use cssparser::RGBA;
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
@ -35,7 +35,7 @@ pub type Gradient = GenericGradient<
|
||||||
Length,
|
Length,
|
||||||
LengthOrPercentage,
|
LengthOrPercentage,
|
||||||
Position,
|
Position,
|
||||||
CSSColor,
|
RGBA,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// A computed gradient kind.
|
/// A computed gradient kind.
|
||||||
|
@ -60,10 +60,10 @@ pub enum LineDirection {
|
||||||
pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>;
|
pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>;
|
||||||
|
|
||||||
/// A computed gradient item.
|
/// A computed gradient item.
|
||||||
pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
|
pub type GradientItem = GenericGradientItem<RGBA, LengthOrPercentage>;
|
||||||
|
|
||||||
/// A computed color stop.
|
/// A computed color stop.
|
||||||
pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
|
pub type ColorStop = GenericColorStop<RGBA, LengthOrPercentage>;
|
||||||
|
|
||||||
/// Computed values for ImageRect.
|
/// Computed values for ImageRect.
|
||||||
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
|
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
|
||||||
|
|
|
@ -23,11 +23,11 @@ use super::generics::grid::TrackList as GenericTrackList;
|
||||||
use super::specified;
|
use super::specified;
|
||||||
|
|
||||||
pub use app_units::Au;
|
pub use app_units::Au;
|
||||||
pub use cssparser::Color as CSSColor;
|
|
||||||
pub use properties::animated_properties::TransitionProperty;
|
pub use properties::animated_properties::TransitionProperty;
|
||||||
pub use self::background::BackgroundSize;
|
pub use self::background::BackgroundSize;
|
||||||
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
||||||
pub use self::border::{BorderRadius, BorderCornerRadius};
|
pub use self::border::{BorderRadius, BorderCornerRadius};
|
||||||
|
pub use self::color::{Color, RGBAColor};
|
||||||
pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect};
|
pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub use self::gecko::ScrollSnapPoint;
|
pub use self::gecko::ScrollSnapPoint;
|
||||||
|
@ -48,6 +48,7 @@ pub use self::transform::{TimingFunction, TransformOrigin};
|
||||||
pub mod background;
|
pub mod background;
|
||||||
pub mod basic_shape;
|
pub mod basic_shape;
|
||||||
pub mod border;
|
pub mod border;
|
||||||
|
pub mod color;
|
||||||
pub mod image;
|
pub mod image;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub mod gecko;
|
pub mod gecko;
|
||||||
|
@ -360,86 +361,6 @@ impl ToCss for Time {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for specified::Color {
|
|
||||||
type ComputedValue = RGBA;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "gecko"))]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> RGBA {
|
|
||||||
match *self {
|
|
||||||
specified::Color::RGBA(rgba) => rgba,
|
|
||||||
specified::Color::CurrentColor => context.inherited_style.get_color().clone_color(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> RGBA {
|
|
||||||
use gecko::values::convert_nscolor_to_rgba as to_rgba;
|
|
||||||
// It's safe to access the nsPresContext immutably during style computation.
|
|
||||||
let pres_context = unsafe { &*context.device.pres_context };
|
|
||||||
match *self {
|
|
||||||
specified::Color::RGBA(rgba) => rgba,
|
|
||||||
specified::Color::System(system) => to_rgba(system.to_computed_value(context)),
|
|
||||||
specified::Color::CurrentColor => context.inherited_style.get_color().clone_color(),
|
|
||||||
specified::Color::MozDefaultColor => to_rgba(pres_context.mDefaultColor),
|
|
||||||
specified::Color::MozDefaultBackgroundColor => to_rgba(pres_context.mBackgroundColor),
|
|
||||||
specified::Color::MozHyperlinktext => to_rgba(pres_context.mLinkColor),
|
|
||||||
specified::Color::MozActiveHyperlinktext => to_rgba(pres_context.mActiveLinkColor),
|
|
||||||
specified::Color::MozVisitedHyperlinktext => to_rgba(pres_context.mVisitedLinkColor),
|
|
||||||
specified::Color::InheritFromBodyQuirk => {
|
|
||||||
use dom::TElement;
|
|
||||||
use gecko::wrapper::GeckoElement;
|
|
||||||
use gecko_bindings::bindings::Gecko_GetBody;
|
|
||||||
let body = unsafe {
|
|
||||||
Gecko_GetBody(pres_context)
|
|
||||||
};
|
|
||||||
if let Some(body) = body {
|
|
||||||
let wrap = GeckoElement(body);
|
|
||||||
let borrow = wrap.borrow_data();
|
|
||||||
borrow.as_ref().unwrap()
|
|
||||||
.styles().primary.values()
|
|
||||||
.get_color()
|
|
||||||
.clone_color()
|
|
||||||
} else {
|
|
||||||
to_rgba(pres_context.mDefaultColor)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_computed_value(computed: &RGBA) -> Self {
|
|
||||||
specified::Color::RGBA(*computed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToComputedValue for specified::CSSColor {
|
|
||||||
type ComputedValue = CSSColor;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "gecko"))]
|
|
||||||
#[inline]
|
|
||||||
fn to_computed_value(&self, _context: &Context) -> CSSColor {
|
|
||||||
self.parsed
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
#[inline]
|
|
||||||
fn to_computed_value(&self, context: &Context) -> CSSColor {
|
|
||||||
match self.parsed {
|
|
||||||
specified::Color::RGBA(rgba) => CSSColor::RGBA(rgba),
|
|
||||||
specified::Color::CurrentColor => CSSColor::CurrentColor,
|
|
||||||
// Resolve non-standard -moz keywords to RGBA:
|
|
||||||
non_standard => CSSColor::RGBA(non_standard.to_computed_value(context)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_computed_value(computed: &CSSColor) -> Self {
|
|
||||||
(match *computed {
|
|
||||||
CSSColor::RGBA(rgba) => specified::Color::RGBA(rgba),
|
|
||||||
CSSColor::CurrentColor => specified::Color::CurrentColor,
|
|
||||||
}).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
impl ToComputedValue for specified::JustifyItems {
|
impl ToComputedValue for specified::JustifyItems {
|
||||||
type ComputedValue = JustifyItems;
|
type ComputedValue = JustifyItems;
|
||||||
|
@ -480,7 +401,7 @@ pub struct Shadow {
|
||||||
pub offset_y: Au,
|
pub offset_y: Au,
|
||||||
pub blur_radius: Au,
|
pub blur_radius: Au,
|
||||||
pub spread_radius: Au,
|
pub spread_radius: Au,
|
||||||
pub color: CSSColor,
|
pub color: Color,
|
||||||
pub inset: bool,
|
pub inset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,9 +480,9 @@ impl IntegerOrAuto {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computed SVG Paint value
|
/// Computed SVG Paint value
|
||||||
pub type SVGPaint = ::values::generics::SVGPaint<CSSColor>;
|
pub type SVGPaint = ::values::generics::SVGPaint<RGBA>;
|
||||||
/// Computed SVG Paint Kind value
|
/// Computed SVG Paint Kind value
|
||||||
pub type SVGPaintKind = ::values::generics::SVGPaintKind<CSSColor>;
|
pub type SVGPaintKind = ::values::generics::SVGPaintKind<RGBA>;
|
||||||
|
|
||||||
impl Default for SVGPaint {
|
impl Default for SVGPaint {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -577,7 +498,7 @@ impl SVGPaint {
|
||||||
pub fn black() -> Self {
|
pub fn black() -> Self {
|
||||||
let rgba = RGBA::from_floats(0., 0., 0., 1.);
|
let rgba = RGBA::from_floats(0., 0., 0., 1.);
|
||||||
SVGPaint {
|
SVGPaint {
|
||||||
kind: ::values::generics::SVGPaintKind::Color(CSSColor::RGBA(rgba)),
|
kind: ::values::generics::SVGPaintKind::Color(rgba),
|
||||||
fallback: None,
|
fallback: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -662,4 +583,4 @@ impl ClipRectOrAuto {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <color> | auto
|
/// <color> | auto
|
||||||
pub type ColorOrAuto = Either<CSSColor, Auto>;
|
pub type ColorOrAuto = Either<Color, Auto>;
|
||||||
|
|
|
@ -2,102 +2,336 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! Non-standard CSS color values
|
//! Specified color values.
|
||||||
|
|
||||||
#[cfg(not(feature = "gecko"))] pub use self::servo::Color;
|
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token};
|
||||||
#[cfg(feature = "gecko")] pub use self::gecko::Color;
|
#[cfg(feature = "gecko")]
|
||||||
|
use gecko_bindings::structs::nscolor;
|
||||||
|
use itoa;
|
||||||
|
use parser::{ParserContext, Parse};
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
use properties::longhands::color::SystemColor;
|
||||||
|
use std::fmt;
|
||||||
|
use std::io::Write;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use super::AllowQuirks;
|
||||||
|
use values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
||||||
|
|
||||||
#[cfg(not(feature = "gecko"))]
|
/// Specified color value
|
||||||
mod servo {
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub use cssparser::Color;
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
use cssparser::Parser;
|
pub enum Color {
|
||||||
use parser::{Parse, ParserContext};
|
/// The 'currentColor' keyword
|
||||||
|
CurrentColor,
|
||||||
|
/// A specific RGBA color
|
||||||
|
Numeric {
|
||||||
|
/// Parsed RGBA color
|
||||||
|
parsed: RGBA,
|
||||||
|
/// Authored representation
|
||||||
|
authored: Option<Box<str>>,
|
||||||
|
},
|
||||||
|
/// A complex color value from computed value
|
||||||
|
Complex(ComputedColor),
|
||||||
|
|
||||||
impl Parse for Color {
|
/// A system color
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
#[cfg(feature = "gecko")]
|
||||||
Color::parse(input)
|
System(SystemColor),
|
||||||
|
/// A special color keyword value used in Gecko
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
Special(gecko::SpecialColorKeyword),
|
||||||
|
/// Quirksmode-only rule for inheriting color from the body
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
InheritFromBodyQuirk,
|
||||||
|
}
|
||||||
|
|
||||||
|
no_viewport_percentage!(Color);
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
mod gecko {
|
||||||
|
use style_traits::ToCss;
|
||||||
|
|
||||||
|
define_css_keyword_enum! { SpecialColorKeyword:
|
||||||
|
"-moz-default-color" => MozDefaultColor,
|
||||||
|
"-moz-default-background-color" => MozDefaultBackgroundColor,
|
||||||
|
"-moz-hyperlinktext" => MozHyperlinktext,
|
||||||
|
"-moz-activehyperlinktext" => MozActiveHyperlinktext,
|
||||||
|
"-moz-visitedhyperlinktext" => MozVisitedHyperlinktext,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RGBA> for Color {
|
||||||
|
fn from(value: RGBA) -> Self {
|
||||||
|
Color::rgba(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for Color {
|
||||||
|
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
|
// Currently we only store authored value for color keywords,
|
||||||
|
// because all browsers serialize those values as keywords for
|
||||||
|
// specified value.
|
||||||
|
let start_position = input.position();
|
||||||
|
let authored = match input.next() {
|
||||||
|
Ok(Token::Ident(s)) => Some(s.to_lowercase().into_boxed_str()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
input.reset(start_position);
|
||||||
|
if let Ok(value) = input.try(CSSParserColor::parse) {
|
||||||
|
Ok(match value {
|
||||||
|
CSSParserColor::CurrentColor => Color::CurrentColor,
|
||||||
|
CSSParserColor::RGBA(rgba) => Color::Numeric {
|
||||||
|
parsed: rgba,
|
||||||
|
authored: authored,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
#[cfg(feature = "gecko")] {
|
||||||
|
if let Ok(system) = input.try(SystemColor::parse) {
|
||||||
|
Ok(Color::System(system))
|
||||||
|
} else {
|
||||||
|
gecko::SpecialColorKeyword::parse(input).map(Color::Special)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "gecko"))] {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for Color {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest),
|
||||||
|
Color::Numeric { authored: Some(ref authored), .. } => dest.write_str(authored),
|
||||||
|
Color::Numeric { parsed: ref rgba, .. } => rgba.to_css(dest),
|
||||||
|
Color::Complex(_) => Ok(()),
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
Color::System(system) => system.to_css(dest),
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
Color::Special(special) => special.to_css(dest),
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
Color::InheritFromBodyQuirk => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A wrapper of cssparser::Color::parse_hash.
|
||||||
|
///
|
||||||
|
/// That function should never return CurrentColor, so it makes no sense
|
||||||
|
/// to handle a cssparser::Color here. This should really be done in
|
||||||
|
/// cssparser directly rather than here.
|
||||||
|
fn parse_hash_color(value: &[u8]) -> Result<RGBA, ()> {
|
||||||
|
CSSParserColor::parse_hash(value).map(|color| {
|
||||||
|
match color {
|
||||||
|
CSSParserColor::RGBA(rgba) => rgba,
|
||||||
|
CSSParserColor::CurrentColor =>
|
||||||
|
unreachable!("parse_hash should never return currentcolor"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
/// Returns currentcolor value.
|
||||||
|
#[inline]
|
||||||
|
pub fn currentcolor() -> Color {
|
||||||
|
Color::CurrentColor
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns transparent value.
|
||||||
|
#[inline]
|
||||||
|
pub fn transparent() -> Color {
|
||||||
|
// We should probably set authored to "transparent", but maybe it doesn't matter.
|
||||||
|
Color::rgba(RGBA::transparent())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a numeric RGBA color value.
|
||||||
|
#[inline]
|
||||||
|
pub fn rgba(rgba: RGBA) -> Self {
|
||||||
|
Color::Numeric {
|
||||||
|
parsed: rgba,
|
||||||
|
authored: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a color, with quirks.
|
||||||
|
///
|
||||||
|
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
||||||
|
pub fn parse_quirky(context: &ParserContext,
|
||||||
|
input: &mut Parser,
|
||||||
|
allow_quirks: AllowQuirks)
|
||||||
|
-> Result<Self, ()> {
|
||||||
|
input.try(|i| Self::parse(context, i)).or_else(|_| {
|
||||||
|
if !allow_quirks.allowed(context.quirks_mode) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a <quirky-color> value.
|
||||||
|
///
|
||||||
|
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
||||||
|
fn parse_quirky_color(input: &mut Parser) -> Result<RGBA, ()> {
|
||||||
|
let (number, dimension) = match input.next()? {
|
||||||
|
Token::Number(number) => {
|
||||||
|
(number, None)
|
||||||
|
},
|
||||||
|
Token::Dimension(number, dimension) => {
|
||||||
|
(number, Some(dimension))
|
||||||
|
},
|
||||||
|
Token::Ident(ident) => {
|
||||||
|
if ident.len() != 3 && ident.len() != 6 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
return parse_hash_color(ident.as_bytes());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let value = number.int_value.ok_or(())?;
|
||||||
|
if value < 0 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let length = if value <= 9 {
|
||||||
|
1
|
||||||
|
} else if value <= 99 {
|
||||||
|
2
|
||||||
|
} else if value <= 999 {
|
||||||
|
3
|
||||||
|
} else if value <= 9999 {
|
||||||
|
4
|
||||||
|
} else if value <= 99999 {
|
||||||
|
5
|
||||||
|
} else if value <= 999999 {
|
||||||
|
6
|
||||||
|
} else {
|
||||||
|
return Err(())
|
||||||
|
};
|
||||||
|
let total = length + dimension.as_ref().map_or(0, |d| d.len());
|
||||||
|
if total > 6 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let mut serialization = [b'0'; 6];
|
||||||
|
let space_padding = 6 - total;
|
||||||
|
let mut written = space_padding;
|
||||||
|
written += itoa::write(&mut serialization[written..], value).unwrap();
|
||||||
|
if let Some(dimension) = dimension {
|
||||||
|
written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
debug_assert!(written == 6);
|
||||||
|
parse_hash_color(&serialization)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns false if the color is completely transparent, and
|
||||||
|
/// true otherwise.
|
||||||
|
pub fn is_non_transparent(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Color::Numeric { ref parsed, .. } => parsed.alpha != 0,
|
||||||
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
mod gecko {
|
fn convert_nscolor_to_computedcolor(color: nscolor) -> ComputedColor {
|
||||||
use cssparser::{Color as CSSParserColor, Parser, RGBA};
|
use gecko::values::convert_nscolor_to_rgba;
|
||||||
use parser::{Parse, ParserContext};
|
ComputedColor::rgba(convert_nscolor_to_rgba(color))
|
||||||
use properties::longhands::color::SystemColor;
|
}
|
||||||
use std::fmt;
|
|
||||||
use style_traits::ToCss;
|
|
||||||
|
|
||||||
/// Color value including non-standard -moz prefixed values.
|
impl ToComputedValue for Color {
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
type ComputedValue = ComputedColor;
|
||||||
pub enum Color {
|
|
||||||
/// The 'currentColor' keyword
|
|
||||||
CurrentColor,
|
|
||||||
/// A specific RGBA color
|
|
||||||
RGBA(RGBA),
|
|
||||||
/// A system color
|
|
||||||
System(SystemColor),
|
|
||||||
/// -moz-default-color
|
|
||||||
MozDefaultColor,
|
|
||||||
/// -moz-default-background-color
|
|
||||||
MozDefaultBackgroundColor,
|
|
||||||
/// -moz-hyperlinktext
|
|
||||||
MozHyperlinktext,
|
|
||||||
/// -moz-activehyperlinktext
|
|
||||||
MozActiveHyperlinktext,
|
|
||||||
/// -moz-visitedhyperlinktext
|
|
||||||
MozVisitedHyperlinktext,
|
|
||||||
/// Quirksmode-only rule for inheriting color from the body
|
|
||||||
InheritFromBodyQuirk,
|
|
||||||
}
|
|
||||||
|
|
||||||
no_viewport_percentage!(Color);
|
fn to_computed_value(&self, _context: &Context) -> ComputedColor {
|
||||||
|
match *self {
|
||||||
impl From<CSSParserColor> for Color {
|
Color::CurrentColor => ComputedColor::currentcolor(),
|
||||||
fn from(value: CSSParserColor) -> Self {
|
Color::Numeric { ref parsed, .. } => ComputedColor::rgba(*parsed),
|
||||||
match value {
|
Color::Complex(ref complex) => *complex,
|
||||||
CSSParserColor::CurrentColor => Color::CurrentColor,
|
#[cfg(feature = "gecko")]
|
||||||
CSSParserColor::RGBA(x) => Color::RGBA(x),
|
Color::System(system) =>
|
||||||
|
convert_nscolor_to_computedcolor(system.to_computed_value(_context)),
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
Color::Special(special) => {
|
||||||
|
use self::gecko::SpecialColorKeyword as Keyword;
|
||||||
|
let pres_context = unsafe { &*_context.device.pres_context };
|
||||||
|
convert_nscolor_to_computedcolor(match special {
|
||||||
|
Keyword::MozDefaultColor => pres_context.mDefaultColor,
|
||||||
|
Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor,
|
||||||
|
Keyword::MozHyperlinktext => pres_context.mLinkColor,
|
||||||
|
Keyword::MozActiveHyperlinktext => pres_context.mActiveLinkColor,
|
||||||
|
Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
#[cfg(feature = "gecko")]
|
||||||
}
|
Color::InheritFromBodyQuirk => {
|
||||||
|
use dom::TElement;
|
||||||
impl Parse for Color {
|
use gecko::wrapper::GeckoElement;
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
use gecko_bindings::bindings::Gecko_GetBody;
|
||||||
if let Ok(value) = input.try(CSSParserColor::parse) {
|
let pres_context = unsafe { &*_context.device.pres_context };
|
||||||
Ok(value.into())
|
let body = unsafe {
|
||||||
} else if let Ok(system) = input.try(SystemColor::parse) {
|
Gecko_GetBody(pres_context)
|
||||||
Ok(Color::System(system))
|
};
|
||||||
} else {
|
if let Some(body) = body {
|
||||||
let ident = input.expect_ident()?;
|
let wrap = GeckoElement(body);
|
||||||
match_ignore_ascii_case! { &ident,
|
let borrow = wrap.borrow_data();
|
||||||
"-moz-default-color" => Ok(Color::MozDefaultColor),
|
ComputedColor::rgba(borrow.as_ref().unwrap()
|
||||||
"-moz-default-background-color" => Ok(Color::MozDefaultBackgroundColor),
|
.styles().primary.values()
|
||||||
"-moz-hyperlinktext" => Ok(Color::MozHyperlinktext),
|
.get_color()
|
||||||
"-moz-activehyperlinktext" => Ok(Color::MozActiveHyperlinktext),
|
.clone_color())
|
||||||
"-moz-visitedhyperlinktext" => Ok(Color::MozVisitedHyperlinktext),
|
} else {
|
||||||
_ => Err(())
|
convert_nscolor_to_computedcolor(pres_context.mDefaultColor)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for Color {
|
fn from_computed_value(computed: &ComputedColor) -> Self {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
if computed.is_numeric() {
|
||||||
match *self {
|
Color::rgba(computed.color)
|
||||||
// Standard values:
|
} else if computed.is_currentcolor() {
|
||||||
Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest),
|
Color::currentcolor()
|
||||||
Color::RGBA(rgba) => rgba.to_css(dest),
|
} else {
|
||||||
Color::System(system) => system.to_css(dest),
|
Color::Complex(*computed)
|
||||||
|
|
||||||
// Non-standard values:
|
|
||||||
Color::MozDefaultColor => dest.write_str("-moz-default-color"),
|
|
||||||
Color::MozDefaultBackgroundColor => dest.write_str("-moz-default-background-color"),
|
|
||||||
Color::MozHyperlinktext => dest.write_str("-moz-hyperlinktext"),
|
|
||||||
Color::MozActiveHyperlinktext => dest.write_str("-moz-activehyperlinktext"),
|
|
||||||
Color::MozVisitedHyperlinktext => dest.write_str("-moz-visitedhyperlinktext"),
|
|
||||||
Color::InheritFromBodyQuirk => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specified color value, but resolved to just RGBA for computed value
|
||||||
|
/// with value from color property at the same context.
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub struct RGBAColor(pub Color);
|
||||||
|
|
||||||
|
no_viewport_percentage!(RGBAColor);
|
||||||
|
|
||||||
|
impl Parse for RGBAColor {
|
||||||
|
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
|
Color::parse(context, input).map(RGBAColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for RGBAColor {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
self.0.to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for RGBAColor {
|
||||||
|
type ComputedValue = RGBA;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> RGBA {
|
||||||
|
self.0.to_computed_value(context)
|
||||||
|
.to_rgba(context.style.get_color().clone_color())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(computed: &RGBA) -> Self {
|
||||||
|
RGBAColor(Color::rgba(*computed))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Color> for RGBAColor {
|
||||||
|
fn from(color: Color) -> RGBAColor {
|
||||||
|
RGBAColor(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRe
|
||||||
use values::generics::image::{LineDirection as GenericsLineDirection, ShapeExtent};
|
use values::generics::image::{LineDirection as GenericsLineDirection, ShapeExtent};
|
||||||
use values::generics::image::PaintWorklet;
|
use values::generics::image::PaintWorklet;
|
||||||
use values::generics::position::Position as GenericPosition;
|
use values::generics::position::Position as GenericPosition;
|
||||||
use values::specified::{Angle, CSSColor, Color, Length, LengthOrPercentage};
|
use values::specified::{Angle, Color, Length, LengthOrPercentage};
|
||||||
use values::specified::{Number, NumberOrPercentage, Percentage};
|
use values::specified::{Number, NumberOrPercentage, Percentage, RGBAColor};
|
||||||
use values::specified::position::{Position, PositionComponent, Side, X, Y};
|
use values::specified::position::{Position, PositionComponent, Side, X, Y};
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ pub type Gradient = GenericGradient<
|
||||||
Length,
|
Length,
|
||||||
LengthOrPercentage,
|
LengthOrPercentage,
|
||||||
Position,
|
Position,
|
||||||
CSSColor,
|
RGBAColor,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// A specified gradient kind.
|
/// A specified gradient kind.
|
||||||
|
@ -72,10 +72,10 @@ pub enum LineDirection {
|
||||||
pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>;
|
pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>;
|
||||||
|
|
||||||
/// A specified gradient item.
|
/// A specified gradient item.
|
||||||
pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
|
pub type GradientItem = GenericGradientItem<RGBAColor, LengthOrPercentage>;
|
||||||
|
|
||||||
/// A computed color stop.
|
/// A computed color stop.
|
||||||
pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
|
pub type ColorStop = GenericColorStop<RGBAColor, LengthOrPercentage>;
|
||||||
|
|
||||||
/// Specified values for `moz-image-rect`
|
/// Specified values for `moz-image-rect`
|
||||||
/// -moz-image-rect(<uri>, top, right, bottom, left);
|
/// -moz-image-rect(<uri>, top, right, bottom, left);
|
||||||
|
@ -386,11 +386,11 @@ impl Gradient {
|
||||||
"to" => 1.,
|
"to" => 1.,
|
||||||
_ => return Err(()),
|
_ => return Err(()),
|
||||||
};
|
};
|
||||||
let color = CSSColor::parse(context, i)?;
|
let color = Color::parse(context, i)?;
|
||||||
if color.parsed == Color::CurrentColor {
|
if color == Color::CurrentColor {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok((color, p))
|
Ok((color.into(), p))
|
||||||
})?;
|
})?;
|
||||||
if reverse_stops {
|
if reverse_stops {
|
||||||
p = 1. - p;
|
p = 1. - p;
|
||||||
|
@ -405,11 +405,11 @@ impl Gradient {
|
||||||
if items.is_empty() {
|
if items.is_empty() {
|
||||||
items = vec![
|
items = vec![
|
||||||
GenericGradientItem::ColorStop(GenericColorStop {
|
GenericGradientItem::ColorStop(GenericColorStop {
|
||||||
color: CSSColor::transparent(),
|
color: Color::transparent().into(),
|
||||||
position: Some(Percentage(0.).into()),
|
position: Some(Percentage(0.).into()),
|
||||||
}),
|
}),
|
||||||
GenericGradientItem::ColorStop(GenericColorStop {
|
GenericGradientItem::ColorStop(GenericColorStop {
|
||||||
color: CSSColor::transparent(),
|
color: Color::transparent().into(),
|
||||||
position: Some(Percentage(1.).into()),
|
position: Some(Percentage(1.).into()),
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
@ -674,7 +674,7 @@ impl GradientItem {
|
||||||
impl Parse for ColorStop {
|
impl Parse for ColorStop {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
Ok(ColorStop {
|
Ok(ColorStop {
|
||||||
color: try!(CSSColor::parse(context, input)),
|
color: try!(RGBAColor::parse(context, input)),
|
||||||
position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(),
|
position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,13 @@
|
||||||
|
|
||||||
use Namespace;
|
use Namespace;
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{self, Parser, Token, serialize_identifier};
|
use cssparser::{Parser, Token, serialize_identifier};
|
||||||
use itoa;
|
|
||||||
use parser::{ParserContext, Parse};
|
use parser::{ParserContext, Parse};
|
||||||
use self::grid::TrackSizeOrRepeat;
|
use self::grid::TrackSizeOrRepeat;
|
||||||
use self::url::SpecifiedUrl;
|
use self::url::SpecifiedUrl;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Write;
|
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use style_traits::values::specified::AllowedNumericType;
|
use style_traits::values::specified::AllowedNumericType;
|
||||||
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
|
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
|
||||||
|
@ -33,7 +31,7 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify
|
||||||
pub use self::background::BackgroundSize;
|
pub use self::background::BackgroundSize;
|
||||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||||
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth};
|
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth};
|
||||||
pub use self::color::Color;
|
pub use self::color::{Color, RGBAColor};
|
||||||
pub use self::rect::LengthOrNumberRect;
|
pub use self::rect::LengthOrNumberRect;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub use self::gecko::ScrollSnapPoint;
|
pub use self::gecko::ScrollSnapPoint;
|
||||||
|
@ -92,166 +90,6 @@ impl ComputedValueAsSpecified for SpecifiedUrl {}
|
||||||
no_viewport_percentage!(SpecifiedUrl);
|
no_viewport_percentage!(SpecifiedUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct CSSColor {
|
|
||||||
pub parsed: Color,
|
|
||||||
pub authored: Option<Box<str>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for CSSColor {
|
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CSSColor {
|
|
||||||
/// Parse a color, with quirks.
|
|
||||||
///
|
|
||||||
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
|
||||||
input: &mut Parser,
|
|
||||||
allow_quirks: AllowQuirks)
|
|
||||||
-> Result<Self, ()> {
|
|
||||||
let start_position = input.position();
|
|
||||||
let authored = match input.next() {
|
|
||||||
Ok(Token::Ident(s)) => Some(s.into_owned().into_boxed_str()),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
input.reset(start_position);
|
|
||||||
if let Ok(parsed) = input.try(|i| Parse::parse(context, i)) {
|
|
||||||
return Ok(CSSColor {
|
|
||||||
parsed: parsed,
|
|
||||||
authored: authored,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if !allow_quirks.allowed(context.quirks_mode) {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
let (number, dimension) = match input.next()? {
|
|
||||||
Token::Number(number) => {
|
|
||||||
(number, None)
|
|
||||||
},
|
|
||||||
Token::Dimension(number, dimension) => {
|
|
||||||
(number, Some(dimension))
|
|
||||||
},
|
|
||||||
Token::Ident(ident) => {
|
|
||||||
if ident.len() != 3 && ident.len() != 6 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
return cssparser::Color::parse_hash(ident.as_bytes()).map(|color| {
|
|
||||||
Self {
|
|
||||||
parsed: color.into(),
|
|
||||||
authored: None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(());
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let value = number.int_value.ok_or(())?;
|
|
||||||
if value < 0 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
let length = if value <= 9 {
|
|
||||||
1
|
|
||||||
} else if value <= 99 {
|
|
||||||
2
|
|
||||||
} else if value <= 999 {
|
|
||||||
3
|
|
||||||
} else if value <= 9999 {
|
|
||||||
4
|
|
||||||
} else if value <= 99999 {
|
|
||||||
5
|
|
||||||
} else if value <= 999999 {
|
|
||||||
6
|
|
||||||
} else {
|
|
||||||
return Err(())
|
|
||||||
};
|
|
||||||
let total = length + dimension.as_ref().map_or(0, |d| d.len());
|
|
||||||
if total > 6 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
let mut serialization = [b'0'; 6];
|
|
||||||
let space_padding = 6 - total;
|
|
||||||
let mut written = space_padding;
|
|
||||||
written += itoa::write(&mut serialization[written..], value).unwrap();
|
|
||||||
if let Some(dimension) = dimension {
|
|
||||||
written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap();
|
|
||||||
}
|
|
||||||
debug_assert!(written == 6);
|
|
||||||
Ok(CSSColor {
|
|
||||||
parsed: cssparser::Color::parse_hash(&serialization).map(From::from)?,
|
|
||||||
authored: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns false if the color is completely transparent, and
|
|
||||||
/// true otherwise.
|
|
||||||
pub fn is_non_transparent(&self) -> bool {
|
|
||||||
match self.parsed {
|
|
||||||
Color::RGBA(rgba) if rgba.alpha == 0 => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
no_viewport_percentage!(CSSColor);
|
|
||||||
|
|
||||||
impl ToCss for CSSColor {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match self.authored {
|
|
||||||
Some(ref s) => dest.write_str(s),
|
|
||||||
None => self.parsed.to_css(dest),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Color> for CSSColor {
|
|
||||||
fn from(color: Color) -> Self {
|
|
||||||
CSSColor {
|
|
||||||
parsed: color,
|
|
||||||
authored: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CSSColor {
|
|
||||||
#[inline]
|
|
||||||
/// Returns currentcolor value.
|
|
||||||
pub fn currentcolor() -> CSSColor {
|
|
||||||
Color::CurrentColor.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Returns transparent value.
|
|
||||||
pub fn transparent() -> CSSColor {
|
|
||||||
// We should probably set authored to "transparent", but maybe it doesn't matter.
|
|
||||||
Color::RGBA(cssparser::RGBA::transparent()).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct CSSRGBA {
|
|
||||||
pub parsed: cssparser::RGBA,
|
|
||||||
pub authored: Option<Box<str>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
no_viewport_percentage!(CSSRGBA);
|
|
||||||
|
|
||||||
impl ToCss for CSSRGBA {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match self.authored {
|
|
||||||
Some(ref s) => dest.write_str(s),
|
|
||||||
None => self.parsed.to_css(dest),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse an `<integer>` value, handling `calc()` correctly.
|
/// Parse an `<integer>` value, handling `calc()` correctly.
|
||||||
pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
|
@ -843,7 +681,7 @@ pub struct Shadow {
|
||||||
pub offset_y: Length,
|
pub offset_y: Length,
|
||||||
pub blur_radius: Length,
|
pub blur_radius: Length,
|
||||||
pub spread_radius: Length,
|
pub spread_radius: Length,
|
||||||
pub color: Option<CSSColor>,
|
pub color: Option<Color>,
|
||||||
pub inset: bool,
|
pub inset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,10 +695,8 @@ impl ToComputedValue for Shadow {
|
||||||
offset_y: self.offset_y.to_computed_value(context),
|
offset_y: self.offset_y.to_computed_value(context),
|
||||||
blur_radius: self.blur_radius.to_computed_value(context),
|
blur_radius: self.blur_radius.to_computed_value(context),
|
||||||
spread_radius: self.spread_radius.to_computed_value(context),
|
spread_radius: self.spread_radius.to_computed_value(context),
|
||||||
color: self.color
|
color: self.color.as_ref().unwrap_or(&Color::CurrentColor)
|
||||||
.as_ref()
|
.to_computed_value(context),
|
||||||
.map(|color| color.to_computed_value(context))
|
|
||||||
.unwrap_or(cssparser::Color::CurrentColor),
|
|
||||||
inset: self.inset,
|
inset: self.inset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -933,7 +769,7 @@ impl Shadow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if color.is_none() {
|
if color.is_none() {
|
||||||
if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
|
if let Ok(value) = input.try(|i| Color::parse(context, i)) {
|
||||||
color = Some(value);
|
color = Some(value);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -961,10 +797,10 @@ impl Shadow {
|
||||||
no_viewport_percentage!(SVGPaint);
|
no_viewport_percentage!(SVGPaint);
|
||||||
|
|
||||||
/// Specified SVG Paint value
|
/// Specified SVG Paint value
|
||||||
pub type SVGPaint = ::values::generics::SVGPaint<CSSColor>;
|
pub type SVGPaint = ::values::generics::SVGPaint<RGBAColor>;
|
||||||
|
|
||||||
/// Specified SVG Paint Kind value
|
/// Specified SVG Paint Kind value
|
||||||
pub type SVGPaintKind = ::values::generics::SVGPaintKind<CSSColor>;
|
pub type SVGPaintKind = ::values::generics::SVGPaintKind<RGBAColor>;
|
||||||
|
|
||||||
impl ToComputedValue for SVGPaint {
|
impl ToComputedValue for SVGPaint {
|
||||||
type ComputedValue = super::computed::SVGPaint;
|
type ComputedValue = super::computed::SVGPaint;
|
||||||
|
@ -991,12 +827,7 @@ impl ToComputedValue for SVGPaintKind {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
self.convert(|color| {
|
self.convert(|color| color.to_computed_value(context))
|
||||||
match color.parsed {
|
|
||||||
Color::CurrentColor => cssparser::Color::RGBA(context.style().get_color().clone_color()),
|
|
||||||
_ => color.to_computed_value(context),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1164,7 +995,7 @@ impl ClipRectOrAuto {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <color> | auto
|
/// <color> | auto
|
||||||
pub type ColorOrAuto = Either<CSSColor, Auto>;
|
pub type ColorOrAuto = Either<Color, Auto>;
|
||||||
|
|
||||||
/// Whether quirks are allowed in this context.
|
/// Whether quirks are allowed in this context.
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
|
44
components/style/values/specified/mod.rs.rej
Normal file
44
components/style/values/specified/mod.rs.rej
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
--- components/style/values/specified/mod.rs
|
||||||
|
+++ components/style/values/specified/mod.rs
|
||||||
|
@@ -4,40 +4,38 @@
|
||||||
|
|
||||||
|
//! Specified values.
|
||||||
|
//!
|
||||||
|
//! TODO(emilio): Enhance docs.
|
||||||
|
|
||||||
|
use Namespace;
|
||||||
|
use context::QuirksMode;
|
||||||
|
use cssparser::{self, Parser, Token, serialize_identifier};
|
||||||
|
-use itoa;
|
||||||
|
use parser::{ParserContext, Parse};
|
||||||
|
use self::grid::TrackSizeOrRepeat;
|
||||||
|
use self::url::SpecifiedUrl;
|
||||||
|
use std::ascii::AsciiExt;
|
||||||
|
use std::f32;
|
||||||
|
use std::fmt;
|
||||||
|
-use std::io::Write;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use style_traits::values::specified::AllowedNumericType;
|
||||||
|
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
|
||||||
|
use super::computed::{self, Context};
|
||||||
|
use super::computed::{Shadow as ComputedShadow, ToComputedValue};
|
||||||
|
use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
|
||||||
|
use super::generics::grid::TrackList as GenericTrackList;
|
||||||
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
use values::specified::calc::CalcNode;
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
|
||||||
|
pub use self::background::BackgroundSize;
|
||||||
|
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||||
|
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth};
|
||||||
|
-pub use self::color::Color;
|
||||||
|
+pub use self::color::{CSSColor, Color};
|
||||||
|
pub use self::rect::LengthOrNumberRect;
|
||||||
|
pub use super::generics::grid::GridLine;
|
||||||
|
pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
|
||||||
|
pub use self::image::{GradientItem, GradientKind, Image, ImageRect, ImageLayer};
|
||||||
|
pub use self::length::AbsoluteLength;
|
||||||
|
pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage};
|
||||||
|
pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
|
pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength};
|
|
@ -2216,10 +2216,10 @@ pub extern "C" fn Servo_DeclarationBlock_SetCurrentColor(declarations:
|
||||||
RawServoDeclarationBlockBorrowed,
|
RawServoDeclarationBlockBorrowed,
|
||||||
property: nsCSSPropertyID) {
|
property: nsCSSPropertyID) {
|
||||||
use style::properties::{PropertyDeclaration, LonghandId};
|
use style::properties::{PropertyDeclaration, LonghandId};
|
||||||
use style::values::specified::{Color, CSSColor};
|
use style::values::specified::Color;
|
||||||
|
|
||||||
let long = get_longhand_from_id!(property);
|
let long = get_longhand_from_id!(property);
|
||||||
let cc = CSSColor { parsed: Color::CurrentColor, authored: None };
|
let cc = Color::currentcolor();
|
||||||
|
|
||||||
let prop = match_wrap_declared! { long,
|
let prop = match_wrap_declared! { long,
|
||||||
BorderTopColor => cc,
|
BorderTopColor => cc,
|
||||||
|
@ -2240,11 +2240,11 @@ pub extern "C" fn Servo_DeclarationBlock_SetColorValue(declarations:
|
||||||
use style::gecko::values::convert_nscolor_to_rgba;
|
use style::gecko::values::convert_nscolor_to_rgba;
|
||||||
use style::properties::{PropertyDeclaration, LonghandId};
|
use style::properties::{PropertyDeclaration, LonghandId};
|
||||||
use style::properties::longhands;
|
use style::properties::longhands;
|
||||||
use style::values::specified::{Color, CSSColor};
|
use style::values::specified::Color;
|
||||||
|
|
||||||
let long = get_longhand_from_id!(property);
|
let long = get_longhand_from_id!(property);
|
||||||
let rgba = convert_nscolor_to_rgba(value);
|
let rgba = convert_nscolor_to_rgba(value);
|
||||||
let color = CSSColor { parsed: Color::RGBA(rgba), authored: None };
|
let color = Color::rgba(rgba);
|
||||||
|
|
||||||
let prop = match_wrap_declared! { long,
|
let prop = match_wrap_declared! { long,
|
||||||
BorderTopColor => color,
|
BorderTopColor => color,
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::{Color, RGBA};
|
use cssparser::RGBA;
|
||||||
use parsing::parse;
|
use parsing::parse;
|
||||||
use style::values::{Auto, Either};
|
use style::values::{Auto, Either};
|
||||||
use style::values::specified::CSSColor;
|
use style::values::specified::Color;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -33,13 +33,13 @@ fn test_caret_color() {
|
||||||
let auto = parse_longhand!(caret_color, "auto");
|
let auto = parse_longhand!(caret_color, "auto");
|
||||||
assert_eq!(auto, Either::Second(Auto));
|
assert_eq!(auto, Either::Second(Auto));
|
||||||
|
|
||||||
let blue_color = CSSColor {
|
let blue_color = Color::Numeric {
|
||||||
parsed: Color::RGBA(RGBA {
|
parsed: RGBA {
|
||||||
red: 0,
|
red: 0,
|
||||||
green: 0,
|
green: 0,
|
||||||
blue: 255,
|
blue: 255,
|
||||||
alpha: 255,
|
alpha: 255,
|
||||||
}),
|
},
|
||||||
authored: Some(String::from("blue").into_boxed_str()),
|
authored: Some(String::from("blue").into_boxed_str()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
use properties::parse;
|
use properties::parse;
|
||||||
use style::computed_values::display::T::inline_block;
|
use style::computed_values::display::T::inline_block;
|
||||||
use style::properties::{PropertyDeclaration, Importance, PropertyId};
|
use style::properties::{PropertyDeclaration, Importance, PropertyId};
|
||||||
use style::properties::longhands::outline_color::computed_value::T as ComputedColor;
|
|
||||||
use style::properties::parse_property_declaration_list;
|
use style::properties::parse_property_declaration_list;
|
||||||
use style::values::{RGBA, Auto};
|
use style::values::{RGBA, Auto};
|
||||||
use style::values::CustomIdent;
|
use style::values::CustomIdent;
|
||||||
use style::values::specified::{BorderStyle, BorderSideWidth, CSSColor, Length, LengthOrPercentage};
|
use style::values::specified::{BorderStyle, BorderSideWidth, Color};
|
||||||
|
use style::values::specified::{Length, LengthOrPercentage};
|
||||||
use style::values::specified::{LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent};
|
use style::values::specified::{LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent};
|
||||||
use style::values::specified::{NoCalcLength, PositionComponent};
|
use style::values::specified::{NoCalcLength, PositionComponent};
|
||||||
use style::values::specified::position::Y;
|
use style::values::specified::position::Y;
|
||||||
|
@ -110,10 +110,7 @@ mod shorthand_serialization {
|
||||||
|
|
||||||
let line = TextDecorationLine::OVERLINE;
|
let line = TextDecorationLine::OVERLINE;
|
||||||
let style = TextDecorationStyle::dotted;
|
let style = TextDecorationStyle::dotted;
|
||||||
let color = CSSColor {
|
let color = RGBA::new(128, 0, 128, 255).into();
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(128, 0, 128, 255)),
|
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
|
|
||||||
properties.push(PropertyDeclaration::TextDecorationLine(line));
|
properties.push(PropertyDeclaration::TextDecorationLine(line));
|
||||||
properties.push(PropertyDeclaration::TextDecorationStyle(style));
|
properties.push(PropertyDeclaration::TextDecorationStyle(style));
|
||||||
|
@ -129,7 +126,7 @@ mod shorthand_serialization {
|
||||||
|
|
||||||
let line = TextDecorationLine::UNDERLINE;
|
let line = TextDecorationLine::UNDERLINE;
|
||||||
let style = TextDecorationStyle::solid;
|
let style = TextDecorationStyle::solid;
|
||||||
let color = CSSColor::currentcolor();
|
let color = Color::currentcolor();
|
||||||
|
|
||||||
properties.push(PropertyDeclaration::TextDecorationLine(line));
|
properties.push(PropertyDeclaration::TextDecorationLine(line));
|
||||||
properties.push(PropertyDeclaration::TextDecorationStyle(style));
|
properties.push(PropertyDeclaration::TextDecorationStyle(style));
|
||||||
|
@ -229,10 +226,7 @@ mod shorthand_serialization {
|
||||||
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
||||||
properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone()));
|
properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone()));
|
||||||
|
|
||||||
let blue = CSSColor {
|
let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)),
|
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
|
|
||||||
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
||||||
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
||||||
|
@ -262,10 +256,7 @@ mod shorthand_serialization {
|
||||||
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
||||||
properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone()));
|
properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone()));
|
||||||
|
|
||||||
let blue = CSSColor {
|
let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)),
|
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
|
|
||||||
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
||||||
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
||||||
|
@ -332,15 +323,8 @@ mod shorthand_serialization {
|
||||||
fn border_color_should_serialize_correctly() {
|
fn border_color_should_serialize_correctly() {
|
||||||
let mut properties = Vec::new();
|
let mut properties = Vec::new();
|
||||||
|
|
||||||
let red = CSSColor {
|
let red = Color::rgba(RGBA::new(255, 0, 0, 255));
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)),
|
let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
|
|
||||||
let blue = CSSColor {
|
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)),
|
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
|
|
||||||
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
||||||
properties.push(PropertyDeclaration::BorderRightColor(red.clone()));
|
properties.push(PropertyDeclaration::BorderRightColor(red.clone()));
|
||||||
|
@ -405,10 +389,7 @@ mod shorthand_serialization {
|
||||||
|
|
||||||
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
||||||
let style = BorderStyle::solid;
|
let style = BorderStyle::solid;
|
||||||
let color = CSSColor {
|
let color = RGBA::new(255, 0, 0, 255).into();
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)),
|
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
|
|
||||||
properties.push(PropertyDeclaration::BorderTopWidth(width));
|
properties.push(PropertyDeclaration::BorderTopWidth(width));
|
||||||
properties.push(PropertyDeclaration::BorderTopStyle(style));
|
properties.push(PropertyDeclaration::BorderTopStyle(style));
|
||||||
|
@ -418,10 +399,10 @@ mod shorthand_serialization {
|
||||||
assert_eq!(serialization, "border-top: 4px solid rgb(255, 0, 0);");
|
assert_eq!(serialization, "border-top: 4px solid rgb(255, 0, 0);");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_border_property_values() -> (BorderSideWidth, BorderStyle, CSSColor) {
|
fn get_border_property_values() -> (BorderSideWidth, BorderStyle, Color) {
|
||||||
(BorderSideWidth::Length(Length::from_px(4f32)),
|
(BorderSideWidth::Length(Length::from_px(4f32)),
|
||||||
BorderStyle::solid,
|
BorderStyle::solid,
|
||||||
CSSColor::currentcolor())
|
Color::currentcolor())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -532,10 +513,7 @@ mod shorthand_serialization {
|
||||||
|
|
||||||
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
||||||
let style = Either::Second(BorderStyle::solid);
|
let style = Either::Second(BorderStyle::solid);
|
||||||
let color = CSSColor {
|
let color = RGBA::new(255, 0, 0, 255).into();
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)),
|
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
|
|
||||||
properties.push(PropertyDeclaration::OutlineWidth(width));
|
properties.push(PropertyDeclaration::OutlineWidth(width));
|
||||||
properties.push(PropertyDeclaration::OutlineStyle(style));
|
properties.push(PropertyDeclaration::OutlineStyle(style));
|
||||||
|
@ -551,10 +529,7 @@ mod shorthand_serialization {
|
||||||
|
|
||||||
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
let width = BorderSideWidth::Length(Length::from_px(4f32));
|
||||||
let style = Either::First(Auto);
|
let style = Either::First(Auto);
|
||||||
let color = CSSColor {
|
let color = RGBA::new(255, 0, 0, 255).into();
|
||||||
parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)),
|
|
||||||
authored: None
|
|
||||||
};
|
|
||||||
properties.push(PropertyDeclaration::OutlineWidth(width));
|
properties.push(PropertyDeclaration::OutlineWidth(width));
|
||||||
properties.push(PropertyDeclaration::OutlineStyle(style));
|
properties.push(PropertyDeclaration::OutlineStyle(style));
|
||||||
properties.push(PropertyDeclaration::OutlineColor(color));
|
properties.push(PropertyDeclaration::OutlineColor(color));
|
||||||
|
|
|
@ -158,9 +158,9 @@ fn test_parse_stylesheet() {
|
||||||
)),
|
)),
|
||||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||||
(PropertyDeclaration::BackgroundColor(
|
(PropertyDeclaration::BackgroundColor(
|
||||||
longhands::background_color::SpecifiedValue {
|
longhands::background_color::SpecifiedValue::Numeric {
|
||||||
authored: Some("blue".to_owned().into_boxed_str()),
|
authored: Some("blue".to_owned().into_boxed_str()),
|
||||||
parsed: cssparser::Color::RGBA(cssparser::RGBA::new(0, 0, 255, 255)),
|
parsed: cssparser::RGBA::new(0, 0, 255, 255),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
Importance::Normal),
|
Importance::Normal),
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[cssstyledeclaration-csstext.htm]
|
|
||||||
type: testharness
|
|
||||||
[uppercase value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue