mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #10959 - heycam:color, r=bholley
Support color-typed properties in geckolib This is on top of https://github.com/servo/servo/pull/10957 though I'm not sure how to make that PR's commits not appear in this one. r? @bholley <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10959) <!-- Reviewable:end -->
This commit is contained in:
commit
1a1ea30f8c
5 changed files with 162 additions and 4 deletions
|
@ -20,6 +20,7 @@
|
||||||
<%call expr="longhand(name, predefined_type=type, **kwargs)">
|
<%call expr="longhand(name, predefined_type=type, **kwargs)">
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
use cssparser::{Color as CSSParserColor, RGBA};
|
||||||
pub type SpecifiedValue = specified::${type};
|
pub type SpecifiedValue = specified::${type};
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub use values::computed::${type} as T;
|
pub use values::computed::${type} as T;
|
||||||
|
|
|
@ -15,12 +15,27 @@ ${helpers.single_keyword("vector-effect", "none non-scaling-stroke", products="g
|
||||||
|
|
||||||
// Section 13 - Gradients and Patterns
|
// Section 13 - Gradients and Patterns
|
||||||
|
|
||||||
|
${helpers.predefined_type(
|
||||||
|
"stop-color", "CSSColor",
|
||||||
|
"CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
|
||||||
|
products="gecko")}
|
||||||
|
|
||||||
${helpers.predefined_type("stop-opacity", "Opacity", "1.0", products="gecko")}
|
${helpers.predefined_type("stop-opacity", "Opacity", "1.0", products="gecko")}
|
||||||
|
|
||||||
// Section 15 - Filter Effects
|
// Section 15 - Filter Effects
|
||||||
|
|
||||||
|
${helpers.predefined_type(
|
||||||
|
"flood-color", "CSSColor",
|
||||||
|
"CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
|
||||||
|
products="gecko")}
|
||||||
|
|
||||||
${helpers.predefined_type("flood-opacity", "Opacity", "1.0", products="gecko")}
|
${helpers.predefined_type("flood-opacity", "Opacity", "1.0", products="gecko")}
|
||||||
|
|
||||||
|
${helpers.predefined_type(
|
||||||
|
"lighting-color", "CSSColor",
|
||||||
|
"CSSParserColor::RGBA(RGBA { red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 })",
|
||||||
|
products="gecko")}
|
||||||
|
|
||||||
// CSS Masking Module Level 1
|
// CSS Masking Module Level 1
|
||||||
// https://www.w3.org/TR/css-masking-1/
|
// https://www.w3.org/TR/css-masking-1/
|
||||||
${helpers.single_keyword("mask-type", "luminance alpha", products="gecko")}
|
${helpers.single_keyword("mask-type", "luminance alpha", products="gecko")}
|
||||||
|
|
|
@ -107,3 +107,8 @@ ${helpers.single_keyword("unicode-bidi", "normal embed isolate bidi-override iso
|
||||||
${helpers.single_keyword("text-decoration-style",
|
${helpers.single_keyword("text-decoration-style",
|
||||||
"-moz-none solid double dotted dashed wavy",
|
"-moz-none solid double dotted dashed wavy",
|
||||||
products="gecko")}
|
products="gecko")}
|
||||||
|
|
||||||
|
${helpers.predefined_type(
|
||||||
|
"text-decoration-color", "CSSColor",
|
||||||
|
"CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
|
||||||
|
products="gecko")}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use style::properties::longhands;
|
||||||
use style::properties::make_cascade_vec;
|
use style::properties::make_cascade_vec;
|
||||||
use style::properties::style_struct_traits::*;
|
use style::properties::style_struct_traits::*;
|
||||||
use gecko_style_structs::{nsStyleUnion, nsStyleUnit};
|
use gecko_style_structs::{nsStyleUnion, nsStyleUnit};
|
||||||
use values::ToGeckoStyleCoord;
|
use values::{ToGeckoStyleCoord, convert_rgba_to_nscolor, convert_nscolor_to_rgba};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GeckoComputedValues {
|
pub struct GeckoComputedValues {
|
||||||
|
@ -184,6 +184,59 @@ def set_gecko_property(ffi_name, expr):
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="clear_color_flags(color_flags_ffi_name)">
|
||||||
|
% if color_flags_ffi_name:
|
||||||
|
self.gecko.${color_flags_ffi_name} &= !(gecko_style_structs::BORDER_COLOR_SPECIAL as u8);
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="set_current_color_flag(color_flags_ffi_name)">
|
||||||
|
% if color_flags_ffi_name:
|
||||||
|
self.gecko.${color_flags_ffi_name} |= gecko_style_structs::BORDER_COLOR_FOREGROUND as u8;
|
||||||
|
% else:
|
||||||
|
// FIXME(heycam): This is a Gecko property that doesn't store currentColor
|
||||||
|
// as a computed value. These are currently handled by converting
|
||||||
|
// currentColor to the current value of the color property at computed
|
||||||
|
// value time, but we don't have access to the Color struct here.
|
||||||
|
// In the longer term, Gecko should store currentColor as a computed
|
||||||
|
// value, so that we don't need to do this:
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=760345
|
||||||
|
unimplemented!();
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="get_current_color_flag_from(field)">
|
||||||
|
(${field} & (gecko_style_structs::BORDER_COLOR_FOREGROUND as u8)) != 0
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="impl_color_setter(ident, gecko_ffi_name, color_flags_ffi_name=None)">
|
||||||
|
#[allow(unreachable_code)]
|
||||||
|
fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||||
|
use cssparser::Color;
|
||||||
|
${clear_color_flags(color_flags_ffi_name)}
|
||||||
|
let result = match v {
|
||||||
|
Color::CurrentColor => {
|
||||||
|
${set_current_color_flag(color_flags_ffi_name)}
|
||||||
|
0
|
||||||
|
},
|
||||||
|
Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba),
|
||||||
|
};
|
||||||
|
${set_gecko_property(gecko_ffi_name, "result")}
|
||||||
|
}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="impl_color_copy(ident, gecko_ffi_name, color_flags_ffi_name=None)">
|
||||||
|
fn copy_${ident}_from(&mut self, other: &Self) {
|
||||||
|
% if color_flags_ffi_name:
|
||||||
|
${clear_color_flags(color_flags_ffi_name)}
|
||||||
|
if ${get_current_color_flag_from("other.gecko." + color_flags_ffi_name)} {
|
||||||
|
${set_current_color_flag(color_flags_ffi_name)}
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
|
||||||
|
}
|
||||||
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_keyword(ident, gecko_ffi_name, keyword, need_clone)">
|
<%def name="impl_keyword(ident, gecko_ffi_name, keyword, need_clone)">
|
||||||
<%call expr="impl_keyword_setter(ident, gecko_ffi_name, keyword)"></%call>
|
<%call expr="impl_keyword_setter(ident, gecko_ffi_name, keyword)"></%call>
|
||||||
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
|
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
|
||||||
|
@ -197,6 +250,11 @@ def set_gecko_property(ffi_name, expr):
|
||||||
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
|
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="impl_color(ident, gecko_ffi_name, color_flags_ffi_name=None)">
|
||||||
|
<%call expr="impl_color_setter(ident, gecko_ffi_name, color_flags_ffi_name)"></%call>
|
||||||
|
<%call expr="impl_color_copy(ident, gecko_ffi_name, color_flags_ffi_name)"></%call>
|
||||||
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_app_units(ident, gecko_ffi_name, need_clone)">
|
<%def name="impl_app_units(ident, gecko_ffi_name, need_clone)">
|
||||||
fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||||
self.gecko.${gecko_ffi_name} = v.0;
|
self.gecko.${gecko_ffi_name} = v.0;
|
||||||
|
@ -274,7 +332,8 @@ impl Debug for ${style_struct.gecko_ffi_name} {
|
||||||
|
|
||||||
<%def name="raw_impl_trait(style_struct, skip_longhands='', skip_additionals='')">
|
<%def name="raw_impl_trait(style_struct, skip_longhands='', skip_additionals='')">
|
||||||
<%
|
<%
|
||||||
longhands = [x for x in style_struct.longhands if not x.name in skip_longhands.split()]
|
longhands = [x for x in style_struct.longhands
|
||||||
|
if not (skip_longhands == "*" or x.name in skip_longhands.split())]
|
||||||
|
|
||||||
#
|
#
|
||||||
# Make a list of types we can't auto-generate.
|
# Make a list of types we can't auto-generate.
|
||||||
|
@ -376,7 +435,8 @@ fn static_assert() {
|
||||||
<% border_style_keyword = Keyword("border-style",
|
<% border_style_keyword = Keyword("border-style",
|
||||||
"none solid double dotted dashed hidden groove ridge inset outset") %>
|
"none solid double dotted dashed hidden groove ridge inset outset") %>
|
||||||
|
|
||||||
<% skip_border_longhands = " ".join(["border-{0}-style border-{0}-width ".format(x.ident) for x in SIDES]) %>
|
<% skip_border_longhands = " ".join(["border-{0}-color border-{0}-style border-{0}-width ".format(x.ident)
|
||||||
|
for x in SIDES]) %>
|
||||||
<%self:impl_trait style_struct_name="Border"
|
<%self:impl_trait style_struct_name="Border"
|
||||||
skip_longhands="${skip_border_longhands}"
|
skip_longhands="${skip_border_longhands}"
|
||||||
skip_additionals="*">
|
skip_additionals="*">
|
||||||
|
@ -385,6 +445,9 @@ fn static_assert() {
|
||||||
<% impl_keyword("border_%s_style" % side.ident, "mBorderStyle[%s]" % side.index, border_style_keyword,
|
<% impl_keyword("border_%s_style" % side.ident, "mBorderStyle[%s]" % side.index, border_style_keyword,
|
||||||
need_clone=True) %>
|
need_clone=True) %>
|
||||||
|
|
||||||
|
<% impl_color("border_%s_color" % side.ident, "mBorderColor[%s]" % side.index,
|
||||||
|
color_flags_ffi_name="mBorderStyle[%s]" % side.index) %>
|
||||||
|
|
||||||
<% impl_app_units("border_%s_width" % side.ident, "mComputedBorder.%s" % side.ident, need_clone=False) %>
|
<% impl_app_units("border_%s_width" % side.ident, "mComputedBorder.%s" % side.ident, need_clone=False) %>
|
||||||
|
|
||||||
fn border_${side.ident}_has_nonzero_width(&self) -> bool {
|
fn border_${side.ident}_has_nonzero_width(&self) -> bool {
|
||||||
|
@ -414,11 +477,13 @@ fn static_assert() {
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="Outline"
|
<%self:impl_trait style_struct_name="Outline"
|
||||||
skip_longhands="outline-style"
|
skip_longhands="outline-color outline-style"
|
||||||
skip_additionals="*">
|
skip_additionals="*">
|
||||||
|
|
||||||
<% impl_keyword("outline_style", "mOutlineStyle", border_style_keyword, need_clone=True) %>
|
<% impl_keyword("outline_style", "mOutlineStyle", border_style_keyword, need_clone=True) %>
|
||||||
|
|
||||||
|
<% impl_color("outline_color", "mOutlineColor", color_flags_ffi_name="mOutlineStyle") %>
|
||||||
|
|
||||||
fn outline_has_nonzero_width(&self) -> bool {
|
fn outline_has_nonzero_width(&self) -> bool {
|
||||||
self.gecko.mCachedOutlineWidth != 0
|
self.gecko.mCachedOutlineWidth != 0
|
||||||
}
|
}
|
||||||
|
@ -484,6 +549,61 @@ fn static_assert() {
|
||||||
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
|
<%self:impl_trait style_struct_name="Background" skip_longhands="background-color" skip_additionals="*">
|
||||||
|
|
||||||
|
<% impl_color("background_color", "mBackgroundColor") %>
|
||||||
|
|
||||||
|
</%self:impl_trait>
|
||||||
|
|
||||||
|
<%self:impl_trait style_struct_name="Text"
|
||||||
|
skip_longhands="text-decoration-color"
|
||||||
|
skip_additionals="*">
|
||||||
|
|
||||||
|
<% impl_color("text_decoration_color", "mTextDecorationColor",
|
||||||
|
color_flags_ffi_name="mTextDecorationStyle") %>
|
||||||
|
|
||||||
|
fn has_underline(&self) -> bool {
|
||||||
|
use gecko_style_structs as gss;
|
||||||
|
(self.gecko.mTextDecorationStyle & (gss::NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE as u8)) != 0
|
||||||
|
}
|
||||||
|
fn has_overline(&self) -> bool {
|
||||||
|
use gecko_style_structs as gss;
|
||||||
|
(self.gecko.mTextDecorationStyle & (gss::NS_STYLE_TEXT_DECORATION_LINE_OVERLINE as u8)) != 0
|
||||||
|
}
|
||||||
|
fn has_line_through(&self) -> bool {
|
||||||
|
use gecko_style_structs as gss;
|
||||||
|
(self.gecko.mTextDecorationStyle & (gss::NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH as u8)) != 0
|
||||||
|
}
|
||||||
|
</%self:impl_trait>
|
||||||
|
|
||||||
|
<%self:impl_trait style_struct_name="SVG"
|
||||||
|
skip_longhands="flood-color lighting-color stop-color"
|
||||||
|
skip_additionals="*">
|
||||||
|
|
||||||
|
<% impl_color("flood_color", "mFloodColor") %>
|
||||||
|
|
||||||
|
<% impl_color("lighting_color", "mLightingColor") %>
|
||||||
|
|
||||||
|
<% impl_color("stop_color", "mStopColor") %>
|
||||||
|
|
||||||
|
</%self:impl_trait>
|
||||||
|
|
||||||
|
<%self:impl_trait style_struct_name="Color"
|
||||||
|
skip_longhands="*">
|
||||||
|
|
||||||
|
fn set_color(&mut self, v: longhands::color::computed_value::T) {
|
||||||
|
let result = convert_rgba_to_nscolor(&v);
|
||||||
|
${set_gecko_property("mColor", "result")}
|
||||||
|
}
|
||||||
|
|
||||||
|
<%call expr="impl_simple_copy('color', 'mColor')"></%call>
|
||||||
|
|
||||||
|
fn clone_color(&self) -> longhands::color::computed_value::T {
|
||||||
|
let color = ${get_gecko_property("mColor")} as u32;
|
||||||
|
convert_nscolor_to_rgba(color)
|
||||||
|
}
|
||||||
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%def name="define_ffi_struct_accessor(style_struct)">
|
<%def name="define_ffi_struct_accessor(style_struct)">
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_snake_case, unused_variables)]
|
#[allow(non_snake_case, unused_variables)]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* 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::RGBA;
|
||||||
use gecko_style_structs::{nsStyleUnion, nsStyleUnit};
|
use gecko_style_structs::{nsStyleUnion, nsStyleUnit};
|
||||||
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
|
|
||||||
|
@ -44,3 +45,19 @@ impl ToGeckoStyleCoord for LengthOrPercentageOrAuto {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
|
||||||
|
(((rgba.alpha * 255.0).round() as u32) << 24) |
|
||||||
|
(((rgba.blue * 255.0).round() as u32) << 16) |
|
||||||
|
(((rgba.green * 255.0).round() as u32) << 8) |
|
||||||
|
((rgba.red * 255.0).round() as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_nscolor_to_rgba(color: u32) -> RGBA {
|
||||||
|
RGBA {
|
||||||
|
red: ((color & 0xff) as f32) / 255.0,
|
||||||
|
green: (((color >> 8) & 0xff) as f32) / 255.0,
|
||||||
|
blue: (((color >> 16) & 0xff) as f32) / 255.0,
|
||||||
|
alpha: (((color >> 24) & 0xff) as f32) / 255.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue